将模块方法分配给Class变量或Instance变量

时间:2017-07-21 08:52:07

标签: python python-2.7 class class-variables class-instance-variables

在模块 a.py

def task(): 
    print "task called"

a = task

class A:

    func = task              # this show error unbound method
    #func = task.__call__    # if i replace with this work

    def __init__(self):
        self.func_1 = task

    def test_1(self):
        self.func_1()

    @classmethod
    def test(cls):
        cls.func()


a()
A().test_1()
A.test()

输出:

task called
task called
Traceback (most recent call last):
  File "a.py", line 26, in <module>
     A.test()
  File "a.py", line 21, in test
     cls.func()
TypeError: unbound method task() must be called with A instance as 
first argument (got nothing instead)

在模块中,我可以轻松地为变量分配函数。当内部类尝试将模块级别函数分配给类变量 func = task 时,它显示错误,要删除此错误,我必须用 func = task .__ call __ 替换它但是当我将实例分配给实例变量 self.func_1 = task

我的问题是:为什么我不能在没有 __ call __ 的情况下将模块级别函数分配给类变量,并且当我可以分配给实例变量的相同函数正在工作时。

1 个答案:

答案 0 :(得分:2)

因为您将一个函数映射为A的未绑定方法,所以当您调用cls.func时,首先要求的内容等于getattr(cls, 'func'),返回<unbound method A.task>但是这个未绑定需要使用class作为第一个参数调用方法。

因为在这个特定情况下,cls.func表示&#34;为我提供func&#34;的类属性cls。它不能同时意味着呼叫类方法func&#34; - 因此Python不会cls.func()翻译func(cls)

但在同一时间内,由于func<unbound method A.task>(绑定到A.task),因此需要像func(cls)一样调用它。

用以下内容检查:

@classmethod
def test(cls):
    print getattr(cls, 'func') # <unbound method A.task>

您可以使用以下内容修复它:

def task(cls=None):
    if cls is None:
        print 'task()'
    else:
        print 'A.foo({})'.format(cls)

a = task

class A:
    func = task             # this show error unbound method

    def __init__(self):
        self.func_1 = task

    def test_1(self):
        self.func_1()

    @classmethod
    def test(cls):
        cls.func(cls())

a()
A().test_1()
A.test()

输出:

task()
task()
A.foo(<__main__.A instance at 0x7fd0310a46c8>)

请注意,python3删除了未绑定的方法,这仅适用于python2.x