Python中请问类名()何时会等于类名.__call__() ?


class Foo: 
        def __call__(): 
                print("call") 

if name==‘main’: Foo() print("--------") Foo.call()

上面代码输出如下:

call

请问为何这里 Foo()不等于 Foo.call(),什么情况下才会相等呢? 谢谢


Python中请问类名()何时会等于类名.__call__() ?

5 回复

Foo() 执行的是__init__方法 可以试试这样 f = Foo() f()


在Python里,类名() 这个写法,本质上就是在调用 类名.__call__()。更准确地说,当你写 MyClass() 来实例化一个类时,Python解释器会去查找并执行这个类(注意,是类对象本身)的 __call__ 方法。

默认情况下,一个普通类的 __call__ 方法继承自其元类(通常是 type)。type.__call__() 这个方法里封装了创建实例的标准流程:它会先调用类的 __new__ 方法来创建实例对象,然后再用这个实例和参数去调用 __init__ 方法进行初始化,最后返回这个实例。

所以,类名() 永远等于 类名.__call__() 的执行结果。它们不是“有时”相等,而是在语法层面就是等价的。类名() 是语法糖,底层就是去调用那个 __call__ 方法。

你可以通过一个简单的例子来验证这一点,并看看如果我们自定义类的 __call__ 方法(这通常不是用来控制实例化,而是让实例可调用)会发生什么:

class MyClass:
    # 这是实例的初始化方法
    def __init__(self, x):
        self.x = x
        print(f"__init__ called with x={x}")

    # 这个__call__让MyClass的'实例'变得可调用,而不是类本身。
    # 它并不影响 `MyClass()` 这个实例化过程。
    def __call__(self, y):
        print(f"Instance __call__ called with y={y}")
        return self.x + y

# 1. 正常的实例化过程 `MyClass(10)`, 它触发的是元类type的__call__
obj = MyClass(10)
# 输出: __init__ called with x=10

# 2. 此时obj是一个实例,调用obj(5)才会触发上面定义的实例的__call__方法
result = obj(5)
# 输出: Instance __call__ called with y=5
print(result) # 输出: 15

# 3. 那么,类的__call__在哪?它就是type.__call__。
# 我们可以直接调用它,效果和 `MyClass(10)` 一模一样。
obj2 = MyClass.__call__(10)
# 输出: __init__ called with x=10
print(obj2.x) # 输出: 10

总结一下关键点:

  • 类名() 这个语法,翻译过来就是 类名.__call__(参数)
  • 这个 __call__ 方法是类对象(作为元类 type 的实例)的方法,默认由 type.__call__ 提供。
  • 你在类定义里写的 def __call__(self, ...),是赋予这个类的“实例”可调用的能力,和“类”本身如何被调用(即实例化)是两回事。

简单建议: 理解 类名() 等价于调用其元类的 __call__ 方法是掌握Python对象模型的关键一步。

class Foo:
def call(self):
print(“call”)

if name==‘main’:
f = Foo()
print("--------")
f()

谢谢,我还是有疑问,为何__call__加入 self 参数后就使得 Foo()会调用 Foo.call() ,否则这不会调用呢?

回到顶部