Python闭包和函数属性

Python闭包和函数属性,python,closures,Python,Closures,我尝试重新实现类似于partial(稍后会有更多行为)的东西。现在在下面的示例中,lazycall1似乎和lazycall2一样好,所以我不明白为什么建议使用较长的第二个版本。有什么建议吗?这会给我带来麻烦吗 def lazycall1(func, *args, **kwargs): def f(): func(*args, **kwargs) return f def lazycall2(func, *args, **kwargs): def f():

我尝试重新实现类似于
partial
(稍后会有更多行为)的东西。现在在下面的示例中,
lazycall1
似乎和
lazycall2
一样好,所以我不明白为什么建议使用较长的第二个版本。有什么建议吗?这会给我带来麻烦吗

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()
编辑:事实上,到目前为止给出的答案并不完全正确。即使有双重理由,这也行得通。还有别的原因吗

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

functools.partial可以在返回的内部函数中接受其他参数或重写的参数。您的内部
f()
函数没有,因此不需要在
lazycall2
中执行任何操作。但是,如果您想做这样的事情:

def sum(a, b):
    return a+b
plusone = lazycall3(sum, 1)
plusone(6) # 7

您需要执行这些文档中显示的操作。

第二个表单唯一的额外功能是一些额外的属性。如果您开始传递lazycall2返回的函数,这可能会有所帮助,以便接收函数可以根据这些值做出决定。

请仔细查看您链接到的Python文档页面中内部函数
newfunc
中的参数名,它们与传递给内部函数的参数名不同,
args
vs.
fargs
关键字
vs.
fkeywords
。它们的
partial
实现保存外部函数的参数,并将其添加到内部函数的参数中

由于在内部函数中重复使用完全相同的参数名称,因此外部函数的原始参数在其中将无法访问

至于在外部函数上设置
func
args
kwargs
属性,函数是Python中的对象,您可以在其上设置属性。这些属性允许您在将原始函数和参数传递到
lazycall
函数后访问它们。因此
a1.func
将是
A
a1.args
将是
[1]

如果不需要跟踪原始函数和参数,就可以了
用你的
lazycall1

这没什么区别。我用一个更一般的例子编辑了我的问题。正确吗?
functools.partial
返回的对象具有
.func
.keywords
.func
属性。这些文档展示了一种在纯python中模拟的方法。但是不,它不会影响对返回对象的调用——它只会使初始传递的函数&args在返回对象上可访问。