在python中使对象可调用的问题

kjs*_*him 18 python

我写了这样的代码

>>> class a(object):
        def __init__(self):
            self.__call__ = lambda x:x

>>> b = a()
Run Code Online (Sandbox Code Playgroud)

我期望类a的对象应该是可调用的对象,但最终它不是.

>>> b()

Traceback (most recent call last):
    File "<pyshell#5>", line 1, in <module>
        b()
TypeError: 'a' object is not callable
>>> callable(b)
False

>>> hasattr(b,'__call__')
True
>>> 
Run Code Online (Sandbox Code Playgroud)

我不明白为什么.请帮我.

Ale*_*lli 19

查询正在操作的对象的类型(例如,类)的特殊方法,而不是特定实例.想一想:否则,如果一个类定义__call__了例如,当调用类时__call__应该调用它......这真是一场灾难!但幸运的是,特殊的方法是在类的类型,AKA元类上查找,而且一切都很好("遗留类"在这方面有非常不规则的行为,这就是为什么我们的新风格更好 - 这是Python 3)中唯一剩下的.

因此,如果需要"按实例覆盖"特殊方法,则必须确保实例具有自己的唯一类.这很容易:

class a(object):
    def __init__(self):
        self.__class__ = type(self.__class__.__name__, (self.__class__,), {})
        self.__class__.__call__ = lambda x:x
Run Code Online (Sandbox Code Playgroud)

你在那里 当然,在这种情况下,这将是愚蠢的,因为每个实例最终只有相同的"所谓的每个实例"(!)__call__,但如果你真的需要在每个个体实例的基础上覆盖它将是有用的.


Joh*_*ooy 14

__call__ 需要在类上定义,而不是在实例上定义

class a(object):
    def __init__(self):
        pass
    __call__ = lambda x:x
Run Code Online (Sandbox Code Playgroud)

但大多数人可能会发现以通常的方式定义方法更具可读性

class a(object):
    def __init__(self):
        pass
    def __call__(self):
        return self
Run Code Online (Sandbox Code Playgroud)

如果你需要为每个实例提供不同的行为,你可以像这样做

class a(object):
    def __init__(self):
        self.myfunc = lambda x:x

    def __call__(self):
        return self.myfunc(self)
Run Code Online (Sandbox Code Playgroud)