在 Python 中,函数(function)与方法(method)是两种密切相关但又有所区别的对象。

“方法对象”并非一种独立的新类型,而是函数对象通过机制在类或实例上被访问时,动态生成的包装对象。

要理解方法对象的内部结构,关键在于认识其两个核心属性:

__func__:指向方法背后的原始函数对象。

__self__:指向方法所绑定的对象(实例或类)。

其中 __func__ 是方法对象最核心的组成部分,它决定了方法的最终执行逻辑。

一、方法对象与函数对象的区分

在类体内的使用 def 语句定义函数,在创建时是一个函数对象,并存放在类的命名空间(类.__dict__)中:

print(type(a.f))  #   -> 方法对象

• A.f 直接从类命名空间获取,是一个函数对象

• a.f 通过描述符协议触发函数对象的 __get__ 方法,返回一个绑定方法对象

关键区别:__func__ 是方法对象的专属属性:

hasattr(a.f, "__func__")  # True,方法对象有 __func__

二、__func__ 的定义与语义

对于方法对象,method.__func__ 始终指向定义在类中、存放于类命名空间(类.__dict__)里的那个原始函数对象。

(1)方法对象的结构

当通过实例访问方法(如 a.f)时,Python 内部执行以下流程:

1、在类 A 的命名空间中找到函数对象 A.__dict__['f']。

2、调用该函数对象的 __get__ 方法(描述符协议)。

3、生成一个绑定方法对象,其内部由两部分构成:

• method.__func__:指向原始函数对象。

• method.__self__:指向被绑定的实例 a。

m.__self__ is a                # True,绑定到实例 a

__func__ 永远指向类命名空间中的原始函数,不会指向方法对象本身,也不会因实例不同而变化。

(2)方法调用的展开

一个典型的方法调用 a.f(x),其内部等价于:

a.f.__func__(a.f.__self__, x)  # 即:用绑定的实例作为第一参数调用原始函数

因此:

• method.__func__ 决定了执行哪个函数。

• method.__self__ 决定了自动作为第一个参数传入的对象。

三、__func__ 的常见应用场景

(1)判断两个方法是否基于同一函数

a1.f.__func__ is a2.f.__func__    # True

尽管绑定到不同的实例,但它们背后的函数对象是同一个。

(2)访问函数元数据

方法对象本身不存储 __name__、__doc__ 等元数据,这些信息都存储在 __func__ 中。

print(a.f.__doc__)         # 实际上访问的是 a.f.__func__.__doc__

(3)绕过绑定机制,直接调用底层函数

在某些高级场景(如反射、调试或框架设计)中,可能需要直接操作原始函数。

a.f.__func__(a, 10)        # 通过方法的 __func__ 调用

(4)分析装饰器的影响

装饰器通常会替换类中的原始函数。此时 __func__ 指向的是装饰器返回的包装函数(wrapper)。

# 使用 functools.wraps 装饰器可以保留原始函数的元数据。

四、类方法与静态方法中的 __func__

__func__ 属性也存在于类方法(@classmethod)和静态方法(@staticmethod)对象中,但其 __self__ 的绑定对象有所不同。

• 实例方法:__self__ 绑定到实例。

• 类方法:__self__ 绑定到类本身。

• 静态方法:静态方法访问后返回普通函数对象,因此不具有 __func__ 或 __self__。

print(MyClass.static_method.__self__)        # AttributeError: 'function' object has no attribute '__self__'

五、常见误解与澄清

误解 1:所有函数都有 __func__ 属性。

正解:只有方法对象(包括实例方法、类方法)才拥有 __func__ 属性。普通函数没有。

误解 2:每个方法对象都包含一个独立的函数副本。

正解:所有同源的方法对象共享同一个 __func__ 对象,没有复制行为。

误解 3:通过类访问属性得到的就是方法。

正解:通过类访问得到的是函数对象,通过实例访问才会触发绑定,生成方法对象。

误解 4:__func__ 和 __self__ 是用户可以随意修改的。

正解:它们是只读属性,由 Python 在创建方法对象时自动设置,旨在保证方法绑定机制的正确性。

小结

__func__ 是 Python 方法对象的核心属性,它指向方法所依赖的原始函数对象。绑定方法对象(包括实例方法与类方法)由 __func__ 与 __self__ 组合而成:__func__ 提供执行逻辑,__self__ 提供绑定的对象。因此 a.f(x) 等价于 a.f.__func__(a, x)。只有方法对象(而非函数对象)才具有 __func__。这一属性用于反射、调试、框架内部行为分析,如比较两个方法是否来自同一函数、访问函数元数据、或绕过绑定机制直接调用函数。

理解 __func__ 有助于深入掌握 Python 的方法绑定模型与描述符机制。

打开网易新闻 查看精彩图片

点赞有美意,赞赏是鼓励