Python - 一个类被称为可调用是什么意思?
Python - 一个类被称为可调用是什么意思?
我正在努力理解在Python中什么是\'可调用\'(callables),以及一个类被称为可调用的含义。我正在尝试以下代码:\n
class A(object): def __init__(self): pass print("A是可调用的吗?" + str(callable(A))) a = A() print("创建了a") a()
\n这会得到以下结果:\nA是可调用的吗?True\n创建了a\nTraceback (most recent call last): \n File \"test2.py\", line 11, in
\n此外,\n
print(type(A.__call__()))
\n给出:\n
\n这是否意味着类A有一个__call__
方法?为什么它是类的类型?\n每次我用A()
实例化时,A.__call__()
被调用吗?
Python中,当一个对象的__something__
方法被调用时,会按照以下顺序进行查找:
- 对象的类是否有这个方法,如果有,则返回。
- 对象的类的超类是否有这个方法,如果有,则返回。
- 对象的类的超类的超类是否有这个方法,如果有,则返回。
- ...
需要注意的是,它不会查找对象的类的类。
由于类是type
的实例(或者它的子类,参见这里),类是可调用的(type
具有__call__
)。然而,除非类也定义了__call__
,否则它的实例将不具有__call__
方法,因为它永远不会在类的类中查找。
问题的出现原因是,对象的类的类不会被搜索,因此即使类是可调用的,但它的实例却不具有__call__
方法。要解决这个问题,需要在类中定义__call__
方法。这样,当类的实例被调用时,__call__
方法将被触发。
以下是一个示例代码,演示了如何定义一个可调用的类以及如何调用实例:
class CallableClass:
def __call__(self):
print("CallableClass instance is called")
callable_obj = CallableClass()
callable_obj()
输出结果为:CallableClass instance is called
。
Python中,函数和类都是可调用的。在Python中,类的实例可以通过定义`__call__`方法来使其可调用。当你调用该实例时,实际上会调用`__call__`方法。
至于类的`__call__`方法的作用,先来看看类的类的`__call__`方法是什么。
Python中的类本身也是一等对象,但它们必须是`type`的一个实例。也就是说,调用`type`来创建一个实例,实际上是创建了一个新的类。当代码中遇到类体块时,Python运行时会自动执行这个操作。(但是也可以通过显式调用`type`的形式来以编程方式创建新的类)
由于`type`本身是`object`的子类,它的`__new__`方法是它的特殊之处,因为它创建了一个新的类,并根据cPython ABI的要求填充了所有所需的数据结构,分配了内存,并将值放入了从纯Python代码中无法访问的字段中。由于它是Python中任何类型的类对象,它被称为元类。可以从`type`派生出其他类,并创建自定义的元类,以在创建类的同时运行代码、插入属性、注册数据等 - 但这是可选的。创建的任何类都会经过`type`的`__new__`方法。
那么实例化一个类时会发生什么呢?我在上面写过,在Python中,使对象可调用的是其类中存在`__call__`方法。`type`是所有类的类,它确实有一个`__call__`方法,其中包含了编排调用类的`__new__`和`__init__`方法所需的代码。这就是为什么类是可调用的,为什么Python可以使用相同的语法进行函数调用和对象实例化的原因。
“每次我用A()实例化时,是否都会调用`A.__call__()`?”
不完全正确 - 实际调用的是`type(A).__call__`。如果`A`中没有显式定义`__call__`方法(那么会在其类`type`中搜索`__call__`),`A.__call__`和`type(A).__call__`是相同的。但是,Python不会隐式调用特殊方法,它们总是从对象的类中选择 - 这是在运行时内部完成的。
你可能会对元类的调用不能对类可用感到困惑:在Python的方法检索算法中并没有像这样定义。当你请求对象的属性或方法时 - 包括特殊方法`__call__`,会在类中搜索该属性,以形成描述符(提供自定义属性访问) - 然后搜索该类的基类,但不搜索该类的类本身。(此外,对于特殊方法,只有在其定义在对象的类本身时才是特殊的:直接附加到实例上不会产生效果)。
解释这一切的关键文档是Python的数据模型 - 从中理解这一切可能需要一些时间和实验。
总结起来,Python中的类可以通过定义`__call__`方法来使其实例可调用。当你调用该实例时,实际上是调用了`__call__`方法。这使得类的实例化和函数调用可以使用相同的语法。