【问题标题】:Python - What does it mean for a Class to be callable?Python - 类可调用意味着什么?
【发布时间】:2018-07-05 19:55:52
【问题描述】:

我试图了解 Python 中的“可调用对象”是什么以及可调用的类意味着什么。我正在使用以下代码:

class A(object):

    def __init__(self):
        pass

print("Is A callable? " + str(callable(A)))
a=A()
print("created a")
a()

这给出了以下结果:

Is A callable? True
created a
Traceback (most recent call last):    
File "test2.py", line 11, in <module>
a()
TypeError: 'A' object is not callable  

此外,

print(type(A.__call__()))

给予:

<class '__main__.A'>

这是否意味着 A 类有一个__call__ 方法?为什么它是类型类?

每次我用 A() 实例化时都会调用 A.__call__() 吗?

【问题讨论】:

  • 您希望a() 做什么?前者是可调用的,因为它在调用时委托给构造函数。您尚未指定允许类的实例可调用的行为,这就是后者失败的原因。
  • 在 Python 中,一切都是对象。如果一个对象具有__call__ 方法,那么它就是callaballe。方法也是对象,所以__call__ 本身有一个__call__ 方法。
  • 我认为标记为重复的问题不能直接回答这个问题。 (从那里的答案中可以理解理解)。
  • 为什么你认为做A()和做a()之间有关系?

标签: python metaclass callable


【解决方案1】:

因此,首先要了解在 Python 中,通常函数是可调用的,而类是可调用的。 撇开将函数标记为可调用的机制不谈,如您所知,Python 类具有特殊的方法。使类的instances 可调用的方法是__call__。所以,如果你的类有一个显式的__call__ 方法,它的实例是可调用的并且故事结束:当你调用实例时,它是被调用的__call__ 方法。

这回答了你一半的问题 - 现在让我们检查类的 __call__ 方法的作用。

Python 中的类本身也是第一类对象 - 但它们必须是 实例 类型。也就是说,调用type就像调用一个类来创建一个实例一样,创建一个新的class。当代码中遇到类主体块时,Python 运行时会自动执行此操作。 (但也可以通过显式调用 type 以三个以上的参数形式以编程方式创建新类)

由于type 本身是object 的子类 - 它的__new__ 方法是它的特殊之处,因为它创建了一个新类,根据cPython ABI 的要求填充所有需要的数据结构,分配内存, 并将值放入纯 Python 代码无法访问的字段中。因为它是 Python 中任何类型的类对象的类,所以它被称为元类。可以在创建类时从类型派生其他类并创建自定义元类,以运行代码、插入属性、注册数据等 - 但这是可选的。创建的任何类都通过类型的__new__

当你实例化一个类时?我在上面写道,使对象在 Python 中可调用的原因是其类中存在 __call__ 方法。 type 是所有类的类,它确实具有__call__ 方法 - 它包含编排调用类的__new____init__ 方法所需的代码。这就是为什么类是可调用的,以及为什么 Python 可以对函数调用和对象实例化使用相同的语法。

每次我用 A() 实例化时都会调用 A.__call__() 吗?

不正确-所谓的type(A).__call__。如果A 中没有定义显式的__call__ 方法,A.__call__type(A).__call__ 将是相同的(然后在其类type 中搜索__call__。但是Python 不会隐式调用特殊方法:普通的属性检索:它们总是从对象的类中挑选出来的——而且是在运行时内部进行的。

您可能会对元类的调用对类不可用感到困惑:这根本不像 Python 的方法检索算法中那样定义。当你请求一个对象的属性或方法时——包括像__call__这样的特殊方法,类会以描述符的形式搜索属性(以提供自定义属性访问)——然后是该类的基类,但不是那个班级的班级。 (另外,对于特殊方法,它们只有在对象的类本身中定义时才是特殊的:直接附加到实例没有效果)。

所有发布的关键文档是 Python 的 Data Model - 不过,可能需要一些时间和试验才能从那里弄清楚所有内容。

【讨论】:

    【解决方案2】:

    当一个对象的__something__ 方法被调用时,会发生这样的事情:

    • 对象的类有吗?如果是,请返回。
    • 它的类的超类有吗?如果是,请返回。
    • 它的类的超类的超类有吗?如果是,请返回。
    • ...

    请注意,它从不查看对象的类。

    由于类是type(或其子类,请参阅here)的实例,因此类是可调用的(type 具有__call__)。但是,除非该类还定义了__call__,否则它的实例不会有它,因为它永远不会在该类的类中查找。

    【讨论】:

      猜你喜欢
      • 2020-06-01
      • 2011-06-28
      • 2021-12-11
      • 2013-01-16
      • 2023-03-10
      • 2023-02-10
      • 1970-01-01
      • 2019-08-07
      • 2020-09-24
      相关资源
      最近更新 更多