可调用类型的定义是什么?

时间:2017-09-17 11:11:48

标签: python python-3.x types callable-object

Background:我试图理解为什么静态和类方法在作为描述符时是不可调用的,而类的普通方法(即既不是静态方法也不是类方法的类的方法)和函数是不是类的属性既是描述符又是可调用的。

在Python中,可调用类型的定义是什么?

  1. 来自https://docs.python.org/3/reference/datamodel.html

      

    可调用类型这些类型可以应用函数调用操作(请参阅调用部分):

    运算符是"函数调用操作" ()?一个是 callable类型定义为函数调用其实例的类型 运营商()可以应用于?

  2. 来自https://docs.python.org/3/reference/expressions.html#calls

      

    主要必须求值为可调用对象(用户定义函数,内置函数,内置对象方法,类   对象,类实例的方法,以及具有的所有对象   __call__()方法可以调用)。

    这是否意味着可调用类型可能有也可能没有 __call__()方法?如果一个类有__call__()方法,那么它 必须是可调用的类型?如果一个班级没有__call__() 方法,那么它可能是也可能不是可调用的类型?

    做"用户定义的函数,内置函数,内置方法 对象,类对象,类实例的方法"没有 __call__()方法?它们是可调用类型的实例吗?什么 他们分别有哪些具体类型?

  3. 感谢。

2 个答案:

答案 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

staticmethodclassmethod 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__特殊方法。