必须使用<class>实例作为第一个参数调用unbound方法<method>

时间:2016-03-23 22:54:29

标签: python-2.7 numpy

我想为类提供默认行为,如下所示。

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

我错过了什么?

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这样的内置函数不支持描述符协议,因此问题不会出现。