Python - 一个类被称为可调用是什么意思?

15 浏览
0 Comments

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 a()\nTypeError: \'A\'对象不可调用 \n\n此外,\n

print(type(A.__call__()))

\n给出:\n


\n这是否意味着类A有一个__call__方法?为什么它是类的类型?\n每次我用A()实例化时,A.__call__()被调用吗?

0
0 Comments

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

0
0 Comments

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__`方法。这使得类的实例化和函数调用可以使用相同的语法。

0