Python中java 判断对象相同是否相同是不是判断内存id?

Python中的is和id用法分析
转载 & & 投稿:shichen2014
这篇文章主要介绍了Python中的is和id用法,实例分析了is和id的功能及使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
本文实例讲述了Python中的is和id用法。分享给大家供大家参考。具体分析如下:
(ob1 is ob2) 等价于 (id(ob1) == id(ob2))
首先id函数可以获得对象的内存地址,如果两个对象的内存地址是一样的,那么这两个对象肯定是一个对象。和is是等价的。Python源代码为证。
代码如下:static PyObject *
&cmp_outcome(int op, register PyObject *v, register PyObject *w)
&int res = 0;
&switch (op) {
&case PyCmp_IS:
& res = (v == w);
&case PyCmp_IS_NOT:
res = (v != w);
但是请看下边代码的这种情况怎么会出现呢?
代码如下:In [1]: def bar(self, x):
...:&&&& return self.x + y
In [2]: class Foo(object):
...:&&&& x = 9
...:&&&& def __init__(self ,x):
...:&&&&&&&& self.x = x
...:&&&& bar = bar
In [3]: foo = Foo(5)
In [4]: foo.bar is Foo.bar
Out[4]: False
In [5]: id(foo.bar) == id(Foo.bar)
Out[5]: True
两个对象用is判断是False,用id判断却是True,这与我们已知的事实不符啊,这种现象该如何解释呢?遇到这种情况最好的解决方法就是调用dis模块去看下两个比较语句到底做了什么。
代码如下:In [7]: dis.dis("id(foo.bar) == id(Foo.bar)")
&&&&&&&&& 0 BUILD_MAP&&&&&& 10340
&&&&&&&&& 3 BUILD_TUPLE&&&& 28527
&&&&&&&&& 6 &46&&&&&&&&&&&
&&&&&&&&& 7 DELETE_GLOBAL&& 2)
&&&&&&&& 10 STORE_SLICE+1
&&&&&&&& 11 SLICE+2&&&&&&
&&&&&&&& 12 DELETE_SUBSCR&
&&&&&&&& 13 DELETE_SUBSCR&
&&&&&&&& 14 SLICE+2&&&&&&
&&&&&&&& 15 BUILD_MAP&&&&&& 10340
&&&&&&&& 18 PRINT_EXPR&&&&
&&&&&&&& 19 JUMP_IF_FALSE_OR_POP 11887
&&&&&&&& 22 DELETE_GLOBAL&& 2)
&&&&&&&& 25 STORE_SLICE+1
In [8]: dis.dis("foo.bar is Foo.bar")
&&&&&&&&& 0 BUILD_TUPLE&&&& 28527
&&&&&&&&& 3 &46&&&&&&&&&&&
&&&&&&&&& 4 DELETE_GLOBAL&& 2)
&&&&&&&&& 7 SLICE+2&&&&&&
&&&&&&&&& 8 BUILD_MAP&&&&&&& 8307
&&&&&&&& 11 PRINT_EXPR&&&&
&&&&&&&& 12 JUMP_IF_FALSE_OR_POP 11887
&&&&&&&& 15 DELETE_GLOBAL&& 2)
真实情况是当执行.操作符的时候,实际是生成了一个proxy对象,foo.bar is Foo.bar的时候,两个对象顺序生成,放在栈里相比较,由于地址不同肯定是False,但是id(foo.bar) == id(Foo.bar)的时候就不同了,首先生成foo.bar,然后计算foo.bar的地址,计算完之后foo.bar的地址之后,就没有任何对象指向foo.bar了,所以foo.bar对象就会被释放。然后生成Foo.bar对象,由于foo.bar和Foo.bar所占用的内存大小是一样的,所以又恰好重用了原先foo.bar的内存地址,所以id(foo.bar) == id(Foo.bar)的结果是True。
下面内容由邮件Leo Jay大牛提供,他解释的更加通透。
用id(expression a) == id(expression b)来判断两个表达式的结果是不是同一个对象的想法是有问题的。
foo.bar 这种形式叫 attribute reference [1],它是表达式的一种。foo是一个instance object,bar是一个方法,这个时候表达式foo.bar返回的结果叫method object。根据文档:
When an instance attribute is referenced that isn't a data attribute,
its class is searched. If the name denotes a valid class attribute
that is a function object, a method object is created by packing
(pointers to) the instance object and the function object just found
together in an abstract object: this is the method object.
foo.bar本身并不是简单的名字,而是表达式的计算结果,是一个 method object,在id(foo.bar)这样的表达式里,method object只是一个临时的中间变量而已,对临时的中间变量做id是没有意义的。
一个更明显的例子是,
代码如下:print id(foo.bar) == id(foo.__init__)
输出的结果也是True
看 id 的文档:
Return the “identity” of an object. This is an integer (or long
integer) which is guaranteed to be unique and constant for this object
during its lifetime. Two objects with non-overlapping lifetimes may
have the same id() value.
CPython implementation detail: This is the address of the object in memory.
只有你能保证对象不会被销毁的前提下,你才能用 id 来比较两个对象。所以,如果你非要比的话,得这样写:
代码如下:fb = foo.bar
Fb = Foo.bar
print id(fb) == id(Fb)
即把两个表达式的结果绑定到名字上,再来比是不是同一个对象,你才能得到正确的结果。
is表达式也是一样的,你现在得到了正确的结果,完全是因为 CPython 现在的实现细节决定的。现在的is的实现,是左右两边的对象都计算出来,然后再比较这两个对象的地址是否一样。万一哪天改成了,先算左边,保存地址,把左边释放掉,再算右边,再比较的话,你的is的结果可能就错了。官方文档里也提到了这个问题 。我认为正确的方法也是像id那样,先把左右两边都计算下来,并显式绑定到各自的名字上,然后再用is判断。
希望本文所述对大家的Python程序设计有所帮助。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具为什么Python有相同的不可变对象id不同_百度知道
为什么Python有相同的不可变对象id不同
我有更好的答案
这就涉及到python的内存管理机制了,python里面,所有变量都是对象,数据在内存中占用物理内存,然后指针的头指向不同的对象,就好比两台相同的电脑,编号却不一样,这其实是两个对象;但是也不是所有对象都是这样处理的,为了节省内存,对于小的整数和短的字符串,python在处理的时候会把相同的数据指向不同的对象,但它们的id是一样的。
采纳率:72%
来自团队:
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。python 值相同变量名不同,内存地址相同吗?
[问题点数:40分,结帖人github_]
python 值相同变量名不同,内存地址相同吗?
[问题点数:40分,结帖人github_]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2018年3月 其他开发语言大版内专家分月排行榜第二2018年1月 其他开发语言大版内专家分月排行榜第二2017年11月 其他开发语言大版内专家分月排行榜第二2016年12月 其他开发语言大版内专家分月排行榜第二
2017年12月 其他开发语言大版内专家分月排行榜第三
匿名用户不能发表回复!|在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
下面是这个文章里面所演示的代码,
我有点费解的就是,按道理a和b完全就不是同一个变量,那么理论上他们无论值是什么,都应该是放在两个不同的内存空间啊,为什么他们相等的时候就放在了同一个内存空间呢?难道是python的运行时环境会自动判断他们的值,如果相同就放到同一个内存空间,为的是节省内存占用吗?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
为了性能上的优化而使用了常量池。而且这也不是 python 独有的,很多其他语言也使用了类似的技巧。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
Python实现int的时候有个小整数池。为了效率, Python首先在内心里创建出这些整数,然后复用了这部分整数,创建一个值为1的int,其实直接从这个池里拿出1。一般是-5到257。你弄个啥的看看。就不会这样了。看看这个:
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。如何使用python比较两分类数据(比如1月与2月)中是否有相同的ID?_百度知道
如何使用python比较两分类数据(比如1月与2月)中是否有相同的ID?
我有更好的答案
用集合set呀比如1月的数据有jan = set( [1,2,3,4,5] )二月的数据有feb = set( [3,6,8,9,10] )是否有相同ID就是求交集interval = jan & feb判断interval就知道是否有相同id了set还可以去重,求并集,求差集等,你可以去了解set的相关用法
采纳率:84%
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。}

我要回帖

更多关于 判断数组内相同对象 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信