在 class 中的默认参数中使用 functools.partial 时的意外行为
Surprising behaviour when using functools.partial in default argument inside a class
class A:
def _add(a, b):
return a + b
def f_add():
return _add
def lambda_add():
return lambda x, y: _add(x, y)
def lambda_arg_add(l=lambda x, y: _add(x, y)):
return l
def partial_add():
return partial(_add)
def partail_arg_add(f=partial(_add)):
return f
A.f_add()(1, 2)
A.lambda_add()(1, 2)
A.lambda_arg_add()(1, 2)
A.partial_add()(1, 2)
A.partail_arg_add()(1, 2)
除最后一个函数调用外,所有函数调用都会引发错误,指出 _add
未定义,但对 partail_arg_add
的调用执行成功。这背后的逻辑是什么?为什么解释器在创建部分函数时知道在哪里寻找 _add
但只有当它作为默认参数完成时才知道?
functools.partial 不涉及此行为。
这是因为默认 arg 是在函数定义处创建的,在 class 定义期间,它出现在 class 的范围内,因此您不需要任何“self. ".
这就是它起作用的原因:
class Example:
def A(self):
pass
def B(self, x=print(A, 1)):
print(self.A, 2)
print(A, 3)
输出:
<function Example.A at 0x7fcf8ebc5950> 1
<function Example.A at 0x7fcf8ebc5950> 3
即使不调用任何 Example.B()
,它也应该在定义 class 时打印 <function Example.A at 0x7fcf8ebc5950>
1 和 3。
但是您不能使用尚未创建的方法创建部分 class
或者,也许你可以,但我不知道有什么方法可以做到。
我试图修复你class:
class A:
@staticmethod
def _add(a, b):
return a + b
@classmethod
def f_add(cls): # valid
return cls._add
@classmethod
def lambda_add(cls): # valid
return lambda x, y: cls._add(x, y)
@staticmethod
def lambda_arg_add(l=lambda x, y: A._add(x, y)): # valid
return l
@classmethod
def partial_add(cls): # valid
return partial(cls._add)
@staticmethod
def partial_arg_add(f=partial(_add)): # TypeError: 'staticmethod' object is not callable
return f
但是 partial_arg_add 会失败,因为在创建部分时 _add 还不可调用 :
class A:
@staticmethod
def _add(a, b):
return a + b
print(_add(1, 3)) # TypeError: 'staticmethod' object is not callable
class A:
@staticmethod
def _add(a, b):
return a + b
print(A._add(1, 3)) # 4
class A:
def _add(a, b):
return a + b
def f_add():
return _add
def lambda_add():
return lambda x, y: _add(x, y)
def lambda_arg_add(l=lambda x, y: _add(x, y)):
return l
def partial_add():
return partial(_add)
def partail_arg_add(f=partial(_add)):
return f
A.f_add()(1, 2)
A.lambda_add()(1, 2)
A.lambda_arg_add()(1, 2)
A.partial_add()(1, 2)
A.partail_arg_add()(1, 2)
除最后一个函数调用外,所有函数调用都会引发错误,指出 _add
未定义,但对 partail_arg_add
的调用执行成功。这背后的逻辑是什么?为什么解释器在创建部分函数时知道在哪里寻找 _add
但只有当它作为默认参数完成时才知道?
functools.partial 不涉及此行为。
这是因为默认 arg 是在函数定义处创建的,在 class 定义期间,它出现在 class 的范围内,因此您不需要任何“self. ".
这就是它起作用的原因:
class Example:
def A(self):
pass
def B(self, x=print(A, 1)):
print(self.A, 2)
print(A, 3)
输出:
<function Example.A at 0x7fcf8ebc5950> 1
<function Example.A at 0x7fcf8ebc5950> 3
即使不调用任何 Example.B()
,它也应该在定义 class 时打印 <function Example.A at 0x7fcf8ebc5950>
1 和 3。
但是您不能使用尚未创建的方法创建部分 class
或者,也许你可以,但我不知道有什么方法可以做到。
我试图修复你class:
class A:
@staticmethod
def _add(a, b):
return a + b
@classmethod
def f_add(cls): # valid
return cls._add
@classmethod
def lambda_add(cls): # valid
return lambda x, y: cls._add(x, y)
@staticmethod
def lambda_arg_add(l=lambda x, y: A._add(x, y)): # valid
return l
@classmethod
def partial_add(cls): # valid
return partial(cls._add)
@staticmethod
def partial_arg_add(f=partial(_add)): # TypeError: 'staticmethod' object is not callable
return f
但是 partial_arg_add 会失败,因为在创建部分时 _add 还不可调用 :
class A:
@staticmethod
def _add(a, b):
return a + b
print(_add(1, 3)) # TypeError: 'staticmethod' object is not callable
class A:
@staticmethod
def _add(a, b):
return a + b
print(A._add(1, 3)) # 4