You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Python会将实例传入作为类属性的函数?

问题:类属性赋值函数后,实例调用为何自动传入自身?

我定义了一个类属性并为其赋值一个函数。当调用该函数时,实例会被作为第一个参数传入(就像带self的实例方法调用一样)。我原本认为实例不会关心属性fn是函数,更不会将自身作为参数传入,请问这是为什么?

class BStatic:
    fn = None
    @staticmethod
    def static_fn(*args, **kwargs):
        print(args, kwargs)

BStatic.fn = BStatic.static_fn

bs = BStatic()

bs.fn()
# (<__main__.BStatic object at 0x0000022D63214590>,) {}

BStatic.fn()
# () {}

在另一个示例中,我将类属性赋值为模块中定义的函数。当通过类的实例调用该函数时,实例同样会被作为第一个参数传入。

class B:
    fn = None
    def instance_fn(self, *args, **kwargs):
        print(self, args, kwargs)

def fn(*args, **kwargs):
    print(args, kwargs)

B.fn = fn

B.fn()
# () {}

b = B()

b.fn()
# (<__main__.B object at 0x0000022D643D23F0>,) {}

但如果直接在实例上赋值该属性,则不会出现这种情况。

b.fn = fn

b.fn()
# () {}

核心原因:Python的方法绑定机制

这是Python的属性访问绑定规则导致的,关键区别在于你访问的函数是类属性还是实例自身属性:

  • 类属性中的函数会被自动绑定为实例方法
    当你通过实例访问类中定义的函数属性时,Python会自动触发方法绑定:把这个函数包装成一个「绑定方法」,并将当前实例作为第一个参数(也就是常见的self)传入。不管这个函数原本是模块级的普通函数,还是类里定义的函数,只要它是类的属性,通过实例调用时就会触发这个绑定逻辑。
    比如第二个示例里,B.fn是类属性,赋值了模块级的fn函数,当b.fn()调用时,Python自动把b作为第一个参数传给fn,所以输出里会看到实例对象。

  • 直接通过类调用类属性函数不会触发绑定
    当你直接通过类(比如B.fn())调用时,函数就是普通的函数对象,Python不会做绑定处理,所以调用时不会自动传入任何额外参数,输出就是空的参数元组。

  • 实例自身的函数属性不会触发绑定
    当你直接给实例赋值函数属性(比如b.fn = fn),这个属性是属于实例自己的,并非从类继承而来。访问实例自身的函数属性时,Python不会执行方法绑定逻辑,所以调用b.fn()就是普通的函数调用,不会自动传入实例。

关于静态方法的特殊情况

你第一个示例里的static_fn是静态方法,但赋值给BStatic.fn后,通过实例调用时依然传入了实例,这是因为:
@staticmethod装饰的函数本质是一个描述器对象,但当你把它赋值给另一个类属性BStatic.fn后,当通过实例访问bs.fn时,描述器的逻辑没有被正确触发,导致最终还是触发了实例方法的绑定行为。如果直接调用bs.static_fn(),你会发现不会传入实例,这才是静态方法的正常表现。


内容的提问来源于stack exchange,提问作者msrc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 14:52:21