我想为类提供默认行为,如下所示。
import numpy as np
class Test:
def __init__(self, my_method=None):
self.my_method = my_method or np.min
Test().my_method([1, 2, 3]) # >>> 1
代码按预期工作。要将所有默认值保持在一起以便于代码维护,我想将代码更改为
import numpy as np
class Test:
default_method = np.min
def __init__(self, my_method=None):
self.my_method = my_method or Test.default_method
Test().my_method([1, 2, 3]) # >>> TypeError
但是对my_method
的调用失败,并显示错误消息unbound method amin() must be called with Test instance as first argument (got list instance instead)
。奇怪的是,如果我使用内置min
而不是np.min
,代码将按预期工作,即以下工作符合预期。
import numpy as np
class Test:
default_method = min # no np.
def __init__(self, my_method=None):
self.my_method = my_method or Test.default_method
Test().my_method([1, 2, 3]) # >>> 1
我错过了什么?
答案 0 :(得分:2)
作为类对象存储为属性的任何函数都被Python视为方法。在Python 2上,这意味着它要求第一个参数是类的实例(如果通过实例请求属性,它将自动传递)。在Python 3上,未绑定的方法不再以这种方式检查它们的参数(因此您的代码将以书面形式工作)。
要解决Python 2上的问题,请尝试使用default_method
包装staticmethod
值:
class Test(object):
default_method = staticmethod(np.min)
#...
即使在Python 3上,这也许不是一个坏主意,因为您还可以使用self.default_method
而不是显式命名该类。
至于为什么代码适用于min
而不是np.min
,这是因为它们的实现方式不同。你可以从type
s:
>>> type(min)
<class 'builtin_function_or_method'>
>>> type(np.min)
<class 'function'>
常规函数(如np.min
)在它们是类的属性时充当描述符(从而获得导致问题的“绑定”行为)。像min
这样的内置函数不支持描述符协议,因此问题不会出现。