尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

函数的描述符特性与绑定方法的生成机制

函数的描述符特性与绑定方法的生成机制
📅 发布时间:2026/6/21 0:28:10

函数的描述符特性与绑定方法的生成机制

一、为什么把两件事放在同一篇讲

在 Python 中,「函数」(function)本身是一种非数据描述符(non-data descriptor)。
解释器把函数放进类属性槽里时,正是靠描述符协议把它**魔术般地」变成「绑定方法」(bound method)。
理解描述符是理解「方法绑定」的唯一入口;理解绑定过程又能反向验证描述符的工作方式。二者不可分割。


二、描述符协议(descriptor protocol)速览

协议成员 是否必须 调用时机 作用
__get__(self, obj, objtype=None) 必须 读取属性时 返回「计算后的值」
__set__(self, obj, value) 可选 赋值时 拦截写操作
__delete__(self, obj) 可选 del 时 拦截删除
  • 数据描述符:至少实现 __set__ 或 __delete__;优先级高于实例字典。
  • 非数据描述符:只实现 __get__;优先级低于实例字典,高于类字典的普通值。

三、函数对象:一个典型的非数据描述符

CPython 源码:Objects/funcobject.c
PyFunction 结构体里自带:

PyDescrObject f_descr;   /* 嵌入的 descriptor 头部 */

因此所有函数天生带 __get__,签名:

function.__get__(self, obj, objtype=None) -> method
  • obj is None → 返回未绑定函数本身(Python 3 里就是原函数)。
  • obj is not None → 返回绑定方法,把 obj 作为第一个参数(self)固化。

四、绑定方法(bound method)的生成过程

  1. 类属性检索
    MyClass.spam 触发 type.__getattribute__ → PyType_Lookup 找到类字典里的函数对象 spam。

  2. 描述符触发
    因为函数实现了 __get__,解释器转而执行:
    method = spam.__get__(None, MyClass) # 未绑定
    或
    method = spam.__get__(instance, MyClass) # 绑定

  3. 方法对象诞生
    CPython 内部新建一个 PyMethodObject,保存:

    • im_func → 原函数指针
    • im_self → 绑定的实例(或 NULL)
    • im_class → 所属类
      这一步对用户完全透明。
  4. 调用阶段
    绑定方法被执行时,它的 __call__ 把 im_self 插到参数列表最前面,再转发给 im_func。


五、代码级演示:从函数到绑定方法

class Foo:def bar(self, x):return x * 2f = Foo()
print(Foo.bar)   # <function Foo.bar at ...>   (未绑定)
print(f.bar)     # <bound method Foo.bar of <__main__.Foo object ...>>

验证描述符身份:

>>> Foo.bar.__get__(None, Foo) is Foo.bar
True
>>> f.bar.__func__ is Foo.bar
True
>>> f.bar.__self__ is f
True

六、静态方法与类方法:描述符的「二次包装」

staticmethod / classmethod 同样是描述符,只是它们在 __get__ 里不返回原函数,而是返回:

  • staticmethod:原函数(无绑定)
  • classmethod:绑定到类对象的新方法

源码级等价:

class staticmethod:def __init__(self, func):self.func = funcdef __get__(self, obj, objtype=None):return self.funcclass classmethod:def __init__(self, func):self.func = funcdef __get__(self, obj, objtype=None):if objtype is None:objtype = type(obj)return self.func.__get__(objtype, objtype)

因此:
函数 → 描述符 →(被 staticmethod/classmethod 再次包装)→ 新的描述符
形成一条「描述符链」。


七、优先级现场实验

class A:def f(self): pass          # 非数据描述符a = A()
a.f = 123                     # 实例字典覆盖
print(a.f)                    # 123
del a.f                       # 删除后恢复描述符
print(a.f)                    # <bound method A.f ...>

把函数升级为数据描述符:

class DataDescriptor:def __get__(self, obj, objtype=None):return 42def __set__(self, obj, value):passclass B:f = DataDescriptor()b = B()
b.f = 99
print(b.f)   # 42,优先级:数据描述符 > 实例字典

八、CPython 源码级鸟瞰(快速索引)

文件 关键函数 说明
Objects/funcobject.c func_descr_get 函数描述符入口
Objects/classobject.c method_call 绑定方法执行
Objects/typeobject.c type_getattro 属性检索总控
Python/ceval.c _PyMethodDef_RawFastCall 方法调用加速

九、常见面试速答模板

Q: “Python 的函数写在类里就能自动变成方法,底层是怎么做到的?”
A:
函数本身是非数据描述符,实现了 __get__(self, obj, cls)。
类属性检索时,解释器发现它带描述符协议,于是把 obj 传进去;
__get__ 返回一个新对象——绑定方法,内部保存原函数与实例。
调用阶段,绑定方法把实例插到参数最前面,再转发给原函数,于是看似“自动传 self”。


十、结论一句话

函数 →(描述符协议)→ 绑定方法;
静态/类方法 →(再包装成描述符)→ 改变绑定规则。
整个“方法”概念在 Python 里完全是描述符协议的副作用,无魔法,唯协议。

相关新闻

  • 猴子测试
  • Flutter 开发文档
  • 别再只用S3了!RustFS的权限管理系统更安全?

最新新闻

  • 后端开发新趋势:探索前沿技术栈的融合应用
  • 2026新余漏水检测维修本地口碑防水商家榜单:厨卫/阳台/屋面/地下室渗漏水维修,持证施工+明码实价,防水补漏公司TOP5推荐 - 即刻修防水
  • 基于分层智能体架构的AI模型自动化构建系统设计与实践
  • 2026新乡漏水检测维修本地口碑防水商家榜单:厨卫/阳台/屋面/地下室渗漏水维修,持证施工+明码实价,防水补漏公司TOP5推荐 - 即刻修防水
  • 2026年靠谱的杀菌机饮料设备/梁山杀菌机饮料设备/包装机饮料设备深度厂家推荐 - 品牌宣传支持者
  • 2026年靠谱的做网站/定制网站/网站建设全国知名公司 - 行业平台推荐

日新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号