Reputation: 12697
I tried to reimplement something like partial
(which later will have more behavior). Now in the following example lazycall1
seems to work just as fine as lazycall2
, so I don't understand why the documentation of partial
suggests using the longer second version. Any suggestions? Can it get me in trouble?
def lazycall1(func, *args, **kwargs):
def f():
func(*args, **kwargs)
return f
def lazycall2(func, *args, **kwargs):
def f():
func(*args, **kwargs)
f.func=func # why do I need that?
f.args=args
f.kwargs=kwargs
return f
def A(x):
print("A", x)
def B(x):
print("B", x)
a1=lazycall1(A, 1)
b1=lazycall1(B, 2)
a1()
b1()
a2=lazycall2(A, 3)
b2=lazycall2(B, 4)
a2()
b2()
EDIT: Actually the answers given so far aren't quite right. Even with double arguments it would work. Is there another reason?
def lazycall(func, *args):
def f(*args2):
return func(*(args+args2))
return f
def sum_up(a, b):
return a+b
plusone=lazycall(sum_up, 1)
plustwo=lazycall(sum_up, 2)
print(plusone(6)) #7
print(plustwo(9)) #11
Upvotes: 3
Views: 773
Reputation: 12867
The only extra thing the second form has, are some extra properties. This might be helpful if you start passing around the functions returned by lazycall2, so that the receiving function may make decisions based on these values.
Upvotes: 2
Reputation: 1562
Look closer at the argument names in the inner function newfunc
in the Python documentation page you link to, they are different than those passed to the inner function, args
vs. fargs
, keywords
vs. fkeywords
. Their implementation of partial
saves the arguments that the outer function was given and adds them to the arguments given to the inner function.
Since you reuse the exact same argument names in your inner function, the original arguments to the outer function won't be accessible in there.
As for setting func
, args
, and kwargs
attributes on the outer function, a function is an object in Python, and you can set attributes on it. These attributes allow you to get access to the original function and arguments after you have passed them into your lazycall
functions. So a1.func
will be A
and a1.args
will be [1]
.
If you don't need to keep track of the original function and arguments, you should be fine
with your lazycall1
.
Upvotes: 0
Reputation: 14081
functools.partial can accept additional arguments - or overridden arguments - in the inner, returned function. Your inner f()
functions don't, so there's no need for what you're doing in lazycall2
. However, if you wanted to do something like this:
def sum(a, b):
return a+b
plusone = lazycall3(sum, 1)
plusone(6) # 7
You'd need to do what is shown in those docs.
Upvotes: 0