Python实例方法内存表现及与C#的对比技术问询
Python实例方法的怪异行为解析
示例代码
class wow: var = 90 def __init__(self): self.wow = 30 def great(self): self.eme = 90 print('wow') var = wow() varss = wow() varsss = wow() print(id(var.great)) print(id(varss.great)) print(id(varsss.great)) print(var.great is varsss.great)
输出结果
1861171310144 1861171310080 1861171310144 False
问题解答
1. 绑定方法的动态生成与内存地址复用
- 当访问
var.great这类实例方法时,Python会动态创建绑定方法对象——这个对象把当前实例和类中的原始函数绑定,确保调用方法时self参数能正确指向实例。 - 第一个和第三个实例的方法地址相同,是因为绑定方法是临时对象,第一个绑定方法被垃圾回收后,内存地址被第三个复用,但它们本质是绑定不同实例的独立对象,所以
is比较返回False。 - 第二个实例的地址不同,只是因为当时该内存地址未被回收,Python分配了新地址。而
wow.great是类的未绑定函数,和绑定方法属于不同对象类型,地址自然不同。
2. 实例与类方法的存储关系
类的方法不会复制到每个实例中,它们存储在类的命名空间里。当实例访问方法时,Python会通过属性查找链(先查实例__dict__,找不到再查类__dict__)找到类中的函数,再动态包装成绑定方法返回。所以var.__dict__里看不到方法,因为方法属于类而非单个实例。
3. 函数本体的共享机制
所有实例共享类中存储的那一份函数本体,不会在每个实例内存中复制函数。每次访问实例方法时生成的只是绑定方法对象(仅关联实例和函数),这个临时对象使用后会被垃圾回收,函数本体始终只有一份,保存在类的内存空间中。
C#的实例方法机制
C#的非静态实例方法同样只有一份本体,存储在类的元数据区域,所有实例共享。调用实例方法时,会把实例的引用(即this参数)隐式传递给方法,不需要为每个实例复制方法代码。和Python的函数本体共享逻辑类似,但C#没有Python中“绑定方法”这类临时对象,直接通过实例引用+方法地址完成调用。
内容的提问来源于stack exchange,提问作者kenshieva
相关产品推荐
相关产品推荐

