Background:我试图理解为什么静态和类方法在作为描述符时是不可调用的,而类的普通方法(即既不是静态方法也不是类方法的类的方法)和函数是不是类的属性既是描述符又是可调用的。
在Python中,可调用类型的定义是什么?
来自https://docs.python.org/3/reference/datamodel.html
可调用类型这些类型可以应用函数调用操作(请参阅调用部分):
运算符是"函数调用操作" ()
?一个是
callable类型定义为函数调用其实例的类型
运营商()
可以应用于?
来自https://docs.python.org/3/reference/expressions.html#calls
主要必须求值为可调用对象(用户定义函数,内置函数,内置对象方法,类 对象,类实例的方法,以及具有的所有对象
__call__()
方法可以调用)。
这是否意味着可调用类型可能有也可能没有
__call__()
方法?如果一个类有__call__()
方法,那么它
必须是可调用的类型?如果一个班级没有__call__()
方法,那么它可能是也可能不是可调用的类型?
做"用户定义的函数,内置函数,内置方法
对象,类对象,类实例的方法"没有
__call__()
方法?它们是可调用类型的实例吗?什么
他们分别有哪些具体类型?
感谢。
答案 0 :(得分:1)
检查可调用的定义
from collections import Callable
源代码如下:
class Callable(metaclass=ABCMeta):
__slots__ = ()
@abstractmethod
def __call__(self, *args, **kwds):
return False
@classmethod
def __subclasshook__(cls, C):
if cls is Callable:
if any("__call__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
棘手的部分是 __ subclasshook __ 的方法,因此任何可以找到__call__方法的类都可以被视为Callable的子类,而不是直接从它继承。
PS:不仅__subclasshook__可以这样做,register()方法还可以将另一个类注册为基类的子类。
答案 1 :(得分:0)
运算符是"函数调用操作"
()
?那么一个可调用类型定义为一个类型,其函数调用操作符()
可以应用于哪个类型?
是的,确实。
这是否意味着可调用类型可能有也可能没有
__call__()
方法?如果一个类有一个__call__()
方法,那么它必须是一个可调用的类型?如果某个类没有__call__()
方法,那么它可能是也可能不是可调用类型?
对于给定对象是可调用的,它必须定义__call__
,函数可以,例如:
def foo():
pass
callable(foo) # True
staticmethod
或classmethod
s(继续上一个问题),不要定义__call__
:
s = staticmethod(foo)
callable(s) # False
(callable
基本上执行getattr(foo, '__call__', False)
)
做"用户定义的函数,内置函数,内置对象的方法,类对象,类实例的方法"没有调用()方法?它们是可调用类型的实例吗?他们分别有哪些具体类型?
用户定义的函数(function
类型,如foo
)具有__call__
。
内置函数(例如max
)也有__call__
,请参阅callable(max)
。
内置对象的方法,是:callable(str.isupper)
。
类对象,是(type
为他们定义__call__
):
>>> class Spam: pass
>>> callable(Spam) # True
类实例的方法:
>>> class Spam2:
... def do_spam(self):
... return "spam"
...
>>> callable(Spam2().do_spam) # True
它们都是可调用的,因为它们定义了__call__
特殊方法。这是使对象可调用的唯一方法。
对于staticmethods和classmethods,虽然它们通常包装callables(然后它们通过描述符协议公开),但它们本身不可调用,因为它们没有定义__call__
特殊方法。