我写了这样的代码
>>> class a(object):
def __init__(self):
self.__call__ = lambda x:x
>>> b = a()
我希望类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
>>>
我无法理解为什么。 请帮帮我。
答案 0 :(得分:18)
在正在操作的对象的类型(例如,类)上查找特殊方法,而不是在特定实例上查找。考虑一下:否则,如果一个类定义__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
你在那儿。当然,在这种情况下这将是愚蠢的,因为每个实例最终只有相同的“所谓的每个实例”(!)__call__
,但如果你真的需要覆盖一个个人实例。
答案 1 :(得分:14)
__call__
,而不是实例
class a(object):
def __init__(self):
pass
__call__ = lambda x:x
但大多数人可能会发现以通常的方式定义方法更具可读性
class a(object):
def __init__(self):
pass
def __call__(self):
return self
如果你需要为每个实例提供不同的行为,你可以这样做
class a(object):
def __init__(self):
self.myfunc = lambda x:x
def __call__(self):
return self.myfunc(self)
答案 2 :(得分:1)
这个怎么样? 定义基类AllowDynamicCall:
class AllowDynamicCall(object):
def __call__(self, *args, **kwargs):
return self._callfunc(self, *args, **kwargs)
然后继承AllowDynamicCall:
class Example(AllowDynamicCall):
def __init__(self):
self._callfunc = lambda s: s