On Codewars.com I encountered the following task:
Create a function
add
that adds numbers together when called in succession. Soadd(1)
should return1
,add(1)(2)
should return1+2
, ...
While I'm familiar with the basics of Python, I've never encountered a function that is able to be called in such succession, i.e. a function f(x)
that can be called as f(x)(y)(z)...
. Thus far, I'm not even sure how to interpret this notation.
As a mathematician, I'd suspect that f(x)(y)
is a function that assigns to every x
a function g_{x}
and then returns g_{x}(y)
and likewise for f(x)(y)(z)
.
Should this interpretation be correct, Python would allow me to dynamically create functions which seems very interesting to me. I've searched the web for the past hour, but wasn't able to find a lead in the right direction. Since I don't know how this programming concept is called, however, this may not be too surprising.
How do you call this concept and where can I read more about it?
Method chaining, also known as named parameter idiom, is a common syntax for invoking multiple method calls in object-oriented programming languages. Each method returns an object, allowing the calls to be chained together in a single statement without requiring variables to store the intermediate results.
The __call__ method enables Python programmers to write classes where the instances behave like functions and can be called like a function. When the instance is called as a function; if this method is defined, x(arg1, arg2, ...) is a shorthand for x.
I don't know whether this is function chaining as much as it's callable chaining, but, since functions are callables I guess there's no harm done. Either way, there's two ways I can think of doing this:
int
and defining __call__
:The first way would be with a custom int
subclass that defines __call__
which returns a new instance of itself with the updated value:
class CustomInt(int): def __call__(self, v): return CustomInt(self + v)
Function add
can now be defined to return a CustomInt
instance, which, as a callable that returns an updated value of itself, can be called in succession:
>>> def add(v): ... return CustomInt(v) >>> add(1) 1 >>> add(1)(2) 3 >>> add(1)(2)(3)(44) # and so on.. 50
In addition, as an int
subclass, the returned value retains the __repr__
and __str__
behavior of int
s. For more complex operations though, you should define other dunders appropriately.
As @Caridorc noted in a comment, add
could also be simply written as:
add = CustomInt
Renaming the class to add
instead of CustomInt
also works similarly.
The only other way I can think of involves a nested function that requires an extra empty argument call in order to return the result. I'm not using nonlocal
and opt for attaching attributes to the function objects to make it portable between Pythons:
def add(v): def _inner_adder(val=None): """ if val is None we return _inner_adder.v else we increment and return ourselves """ if val is None: return _inner_adder.v _inner_adder.v += val return _inner_adder _inner_adder.v = v # save value return _inner_adder
This continuously returns itself (_inner_adder
) which, if a val
is supplied, increments it (_inner_adder += val
) and if not, returns the value as it is. Like I mentioned, it requires an extra ()
call in order to return the incremented value:
>>> add(1)(2)() 3 >>> add(1)(2)(3)() # and so on.. 6
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With