Python中id与is针对方法的行为不符合预期,如何处理引用判断?
Python中方法引用的一致性判断问题
在Python里,对象和函数的引用用is或id()判断一致性时表现符合预期,但实例方法的情况却不一样——每次访问实例的方法,Python都会生成一个新的绑定方法对象,这就导致直接用is判断会返回False,即使它们本质上是同一个实例的同一个方法。
看你提供的示例:
>>> fred = "abcd" >>> bill = fred >>> id(fred) 139890760324016 >>> id(bill) 139890760324016 >>> bill is fred True >>> harry = fred.join >>> id(fred.join) 139890761574896 >>> id(harry) 139890760308992 >>> harry is fred.join False >>> fred.join <built-in method join of str object at 0x7f3adb1393b0> >>> harry <built-in method join of str object at 0x7f3adb1393b0> >>> harry == fred.join True >>> >>> def testFn(): ... return ... >>> mary = testFn >>> id(testFn) 139890760327952 >>> id(mary) 139890760327952 >>> mary is testFn True
原因分析
- 对于普通对象(如字符串
fred)和函数(如testFn),变量存储的是直接指向内存中对象的引用,赋值后两个变量指向同一个对象,is判断自然为True。 - 对于实例方法(如
fred.join),每次访问时Python都会动态创建一个绑定方法对象,这个对象包含了对实例(fred)和原始函数(str.join)的引用。所以每次访问fred.join都会生成新的绑定对象,内存地址不同,is返回False。
解决方案
不需要对方法做完全独立的特殊处理,有两种可行方式:
- 统一使用
==判断:绑定方法的__eq__方法会自动比较其绑定的实例和底层函数是否一致,所以harry == fred.join会返回True。对于普通对象和函数,==在大多数场景下和is表现一致(尤其是不可变类型),可以作为统一的判断方式。 - 用
is判断方法的核心属性:如果一定要用is,可以直接比较绑定方法的__self__(绑定的实例)和__func__(底层函数)属性:
这样就能精准判断两个绑定方法是否属于同一个实例的同一个方法。>>> harry.__self__ is fred and harry.__func__ is str.join True
内容的提问来源于stack exchange,提问作者Steven Smith
相关产品推荐
相关产品推荐

