一个非常简单的类不是可调用的类型:
>>> class myc:
... pass
...
>>> c=myc()
>>> callable(c)
False
如何判断某个类是否有方法__call__
?为什么以下两种方式会产生相反的结果呢?
>>> myc.__call__
<method-wrapper '__call__' of type object at 0x1104b18>
>>> __call__ in myc.__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '__call__' is not defined
感谢。
答案 0 :(得分:5)
myc.__call__
为您提供__call__
方法,用于调用myc
本身,而不是myc
的实例。这是你执行
new_myc_instance = myc()
不是你做的时候
new_myc_instance()
__call__ in myc.__dict__
给你一个NameError,因为你忘了在__call__
周围加上引号,如果你记得要加上引号,那么它会给你假,因为myc.__call__
不是通过myc.__dict__
找到了。它是通过type(myc).__dict__
(a.k.a。type.__dict__
找到的,因为type(myc) is type
)。
要检查myc
是否有针对其实例的__call__
实施,您可以执行手动MRO搜索,但collections.abc.Callable
已经为您实现了这一点:
issubclass(myc, collections.abc.Callable)
答案 1 :(得分:1)
myc.__call__
给你回复 1 而不是提出AttributeError
的原因是因为myc
(type
)的元类有一个__call__
方法。如果在实例上找不到某个属性(在本例中为您的类),则会查找该类(在本例中为元类)。
例如,如果您有自定义元类,__call__
查找将返回不同的内容:
class mym(type):
def __call__(self, *args, **kwargs):
return super().__call__(*args, **kwargs)
class myc(metaclass=mym):
pass
>>> myc.__call__
<bound method mym.__call__ of <class '__main__.myc'>>
关于已经在评论中回答的__call__ in myc.__dict__
和已经回答的其他答案:您刚忘记引文:
>>> '__call__' in myc.__dict__
False
然而,myc
也可以是一个可调用类的子类,在这种情况下它也会给False
:
class mysc:
def __call__(self):
return 10
class myc(mysc):
pass
>>> '__call__' in myc.__dict__
False
所以你需要更强大的东西。就像搜索所有超类一样:
>>> any('__call__' in cls.__dict__ for cls in myc.__mro__)
True
或者,正如user2357112所指出的,collections.Callable
使用__call__
,以便找到>>> from collections.abc import Callable
>>> issubclass(myc, Callable)
True
:
hasattr(myc, '__call__')
1 这也是您不能仅使用__call__
查明其本身是否有var date = moment('2017-09-27');
方法的原因。