3

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

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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.

2 Comments

This wouldn't make a difference. I edited my question with a more general example. Is that correct?
The objects returned by functools.partial have .func, .keywords and .func attributes. The docs are showing a way of emulating that in pure python. But no, it wouldn't affect that calling of the returned object - it would just make the intially-passed function & args accessible on the returned object.
0

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.