可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
how to implement a function that will be invoked in the following way sum_numbers(2)(3)(4)......(n)
in python?
the result should be 2+3+4+.....+n
The hint that I have is since functions are object in pythons there is way to do those using a nested function but I am not sure.
def sum_number(x):
def sum_number_2(y):
def sum_number_3(z):
....................
def sum_number_n(n)
return n
return sum_number_n
return sum_number_3
return sum_number_2
return sum_number
But instead of writing so many nested functions we should be able to do it in couple nested functions to compute sum of n values when invoked in the following way sum_numbers(2)(3)(4)......(n)
回答1:
Use Python's data model features to convert the result into the desired type.
class sum_number(object):
def __init__(self, val):
self.val = val
def __call__(self, val):
self.val += val
return self
def __float__(self):
return float(self.val)
def __int__(self):
return int(self.val)
print '{}'.format(int(sum_number(2)(3)(8)))
print '{}'.format(float(sum_number(2)(3)(8)))
回答2:
You could create a subclass of int
that is callable:
class sum_numbers (int):
def __new__ (cls, *args, **kwargs):
return super().__new__(cls, *args, **kwargs)
def __call__ (self, val):
return sum_numbers(self + val)
That way, you have full compatibility with a normal integer (since objects of that type are normal integers), so the following examples work:
>>> sum_numbers(2)(3)(4)(5)
14
>>> isinstance(sum_numbers(2)(3), int)
True
>>> sum_numbers(2)(3) + 4
9
Of course, you may want to override additional methods, e.g. __add__
so that adding a normal integer will still return an object of your type. Otherwise, you would have to call the type with the result, e.g.:
>>> sum_numbers(sum_numbers(2)(3) + 5)(6)
16
回答3:
If your function is returning another function, you can't just chain calls together and expect a human readable result. If you want a function that does what you want without the final result, this works:
def sum(x):
def f(y):
return sum(x+y)
return f
If you're fine with printing out the operations you can try this:
def sum(x):
print(x)
def f(y):
return sum(x+y)
return f
If you absolutely, absolutely need a return value then this is a dirty, horrible hack you could try:
def sum(x, v):
v[0] = x
def f(y, v):
return sum(x+y, v)
return f
v = [0]
sum(1,v)(2,v)(3,v)
print(v[0]) # Should return 6
Here's another solution that uses classes:
class sum(object):
def __init__(self, x=0):
self.x=x
def __call__(self, *y):
if len(y) > 0:
self.x += y[0]
return self
return self.x
print(sum(1)(2)(3)()) # Prints 6
回答4:
What you're asking for is not possible in Python since you aren't providing a way to determine the end of the call chain, as cricket_007 mentions in the comments. However, if you do provide a way to indicate that there are no more calls then the function is easy to code. One way to indicate the end of the chain is to make the last call with no arguments.
I'm using rsum
(recursive sum) as the name of the function in my code because sum
is a built-in function and unnecessarily shadowing the Python built-ins is not a good coding practice: it makes the code potentially confusing, or at least harder to read because you have to keep remembering that the name isn't referring to what you normally expect it to refer to, and can lead to subtle bugs.
def rsum(val=None, tot=0):
if val is None:
return tot
tot += val
return lambda val=None, tot=tot: rsum(val, tot)
print rsum(42)()
print rsum(1)(2)()
print rsum(4)(3)(2)(1)()
print rsum(4100)(310000)(9)(50)()
output
42
3
10
314159
回答5:
class MetaSum(type):
def __repr__(cls):
sum_str = str(cls.sum)
cls.sum = 0
return sum_str
def __call__(cls, *args):
for arg in args:
cls.sum += arg
return cls
class sum_numbers(object, metaclass = MetaSum):
sum = 0
print (sum_numbers(2)(3)(4)) # this only works in python 3