Python 中的 is 和 id,pythonisid

(ob1 is ob2) 等价于 (id(ob1) == id(ob2))

首先id函数可以获得对象的内存地址,如果两个对象的内存地址是一样的,那么这两个对象肯定是一个对象。和is是等价的。Python源代码为证。

4451 static PyObject *
4452 cmp_outcome(int op, register PyObject *v, register PyObject *w)
4453 {
4454     int res = 0;
4455     switch (op) {
4456     case PyCmp_IS:
4457         res = (v == w);
4458         break;
4459     case PyCmp_IS_NOT:
4460         res = (v != w);
4461         break;

但是请看下边代码的这种情况怎么会出现呢?

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   29281 (29281)
         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   29281 (29281)
         25 STORE_SLICE+1  

In [8]: dis.dis("foo.bar is Foo.bar")
          0 BUILD_TUPLE     28527
          3 <46>           
          4 DELETE_GLOBAL   29281 (29281)
          7 SLICE+2        
          8 BUILD_MAP        8307
         11 PRINT_EXPR     
         12 JUMP_IF_FALSE_OR_POP 11887
         15 DELETE_GLOBAL   29281 (29281)

真实情况是当执行.操作符的时候,实际是生成了一个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.barFoo.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
[2]。根据文档:

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 的文档[3]:

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表达式 [4] 也是一样的,你现在得到了正确的结果,完全是因为 CPython
现在的实现细节决定的。现在的is的实现,是左右两边的对象都计算出来,然后再比较这两个对象的地址是否一样。万一哪天改成了,先算左边,保存地址,把左边释放掉,再算右边,再比较的话,你的is的结果可能就错了。官方文档里也提到了这个问题
[5]。我认为正确的方法也是像id那样,先把左右两边都计算下来,并显式绑定到各自的名字上,然后再用is判断。

[1]
http://docs.python.org/2/reference/expressions.html\#attribute-references
[2]
http://docs.python.org/2/tutorial/classes.html\#method-objects
[3]
http://docs.python.org/2/library/functions.html\#id
[4]
http://docs.python.org/2/reference/expressions.html\#index-68
[5]
http://docs.python.org/2/reference/expressions.html\#id26

is比较内存地址是否相等

 is 主要是判断 2 个变量的值是否指向同一个内存地址,如果是的话,则返回
true,否则返回 false。

>>> a = 5555555
>>> b = 5555555
>>> a is b
False
>>> id(a) #a与b在内存中各开辟了一个地址存放它的值,虽然它们的值相同,但内存地址不同
1925864837008
>>> id(b)
1925868899600

>>> a = 123
>>> b = 123
>>> a is b
True
>>> id(a)
1880121952 #在这里可以看到,两个变量的值都指向了一个内存地址,在python解释器中,为了节省内存的占用,字符和数字在一定范围内存在一个小数据池,数据在这个范内指向同一个内存地址,列表、字典、元组、集合等不存在小数据池
>>> id(b)
1880121952
>>>

Python中的is和id用法分析,pythonisid用法

本文实例讲述了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);
 break;
 case PyCmp_IS_NOT:
res = (v != w);
 break;

但是请看下边代码的这种情况怎么会出现呢?

复制代码 代码如下:

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   29281 (29281)
         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   29281 (29281)
         25 STORE_SLICE+1
 
In [8]: dis.dis(“foo.bar is Foo.bar”)
          0 BUILD_TUPLE     28527
          3 <46>          
          4 DELETE_GLOBAL   29281 (29281)
          7 SLICE+2      
          8 BUILD_MAP        8307
         11 PRINT_EXPR    
         12 JUMP_IF_FALSE_OR_POP 11887
         15 DELETE_GLOBAL   29281 (29281)

真实情况是当执行.操作符的时候,实际是生成了一个proxy对象,foo.bar is

Python中的id()函数指的什么,pythonid函数指

Python官方文档给出的解释是

id(object)
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.

由此可以看出:

1、id(object)返回的是对象的“身份证号”,唯一且不变,但在不重合的生命周期里,可能会出现相同的id值。此处所说的对象应该特指复合类型的对象(如类、list等),对于字符串、整数等类型,变量的id是随值的改变而改变的。

2、一个对象的id值在CPython解释器里就代表它在内存中的地址。(CPython解释器:)

class Obj(): 
 def __init__(self,arg): 
  self.x=arg 
if __name__ == '__main__': 
 obj=Obj(1) 
 print id(obj)  #32754432 
 obj.x=2 
 print id(obj)  #32754432 
 s="abc" 
 print id(s)   #140190448953184 
 s="bcd" 
 print id(s)   #32809848 
 x=1 
 print id(x)   #15760488 
 x=2 
 print id(x)   #15760464 

令外,用is判断两个对象是否相等时,依据就是这个id值

class Obj(): 
 def __init__(self,arg): 
  self.x=arg 
 def __eq__(self,other): 
  return self.x==other.x 
if __name__ == '__main__': 
 obj1=Obj(1) 
 obj2=Obj(1) 
 print obj1 is obj2 #False 
 print obj1 == obj2 #True 
 lst1=[1] 
 lst2=[1] 
 print lst1 is lst2 #False 
 print lst1 == lst2 #True 
 s1='abc' 
 s2='abc' 
 print s1 is s2  #True 
 print s1 == s2  #True 
 a=2 
 b=1+1 
 print a is b  #True 
 a = 19998989890 
 b = 19998989889 +1 
 print a is b  #False 

is与==的区别就是,is是内存中的比较,而==是值的比较

总结

以上所述是小编给大家介绍Python中的id函数,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对帮客之家网站的支持!

Python官方文档给出的解释是 id(object) Return the “identity” of an
object. This is an integer (or long integer)…

 (ob1 is ob2) 等价于 (id(ob1) == id(ob2))

  首先id函数可以获得对象的内存地址,如果两个对象的内存地址是一样的,那么这两个对象肯定是一个对象。和is是等价的。Python源代码为证。

1 2 3 4 5 6 7 8 9 10 11 static PyObject *  cmp_outcome(int op, register PyObject *v, register PyObject *w) {  int res = 0;  switch (op) {  case PyCmp_IS:   res = (v == w);  break;  case PyCmp_IS_NOT: res = (v != w);  break;

  但是请看下边代码的这种情况怎么会出现呢?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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模块去看下两个比较语句到底做了什么。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 In [7]: dis.dis("id(foo.bar) == id(Foo.bar)")           0 BUILD_MAP       10340           3 BUILD_TUPLE     28527           6 <46>                     7 DELETE_GLOBAL   29281 (29281)          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   29281 (29281)          25 STORE_SLICE+1    In [8]: dis.dis("foo.bar is Foo.bar")           0 BUILD_TUPLE     28527           3 <46>                     4 DELETE_GLOBAL   29281 (29281)           7 SLICE+2                  8 BUILD_MAP        8307          11 PRINT_EXPR              12 JUMP_IF_FALSE_OR_POP 11887          15 DELETE_GLOBAL   29281 (29281)

  真实情况是当执行.操作符的时候,实际是生成了一个proxy对象,foo.bar is

 id内存地址

>>> a = 321
>>> b = 456
>>> id(a)
1801244593360
>>> id(b)
1801244593392

 

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程序设计有所帮助。

本文实例讲述了Python中的is和id用法。分享给大家供大家参考。具体分析如下:
(ob1 is ob2) 等价于 (i…

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
[2]。根据文档:

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是没有意义的。

  一个更明显的例子是,

1 print id(foo.bar) == id(foo.__init__)

  输出的结果也是True

  看 id 的文档[3]:

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
来比较两个对象。所以,如果你非要比的话,得这样写:

1 2 3 fb = foo.bar Fb = Foo.bar print id(fb) == id(Fb)

  即把两个表达式的结果绑定到名字上,再来比是不是同一个对象,你才能得到正确的结果。

  is表达式 [4] 也是一样的,你现在得到了正确的结果,完全是因为
CPython
现在的实现细节决定的。现在的is的实现,是左右两边的对象都计算出来,然后再比较这两个对象的地址是否一样。万一哪天改成了,先算左边,保存地址,把左边释放掉,再算右边,再比较的话,你的is的结果可能就错了。官方文档里也提到了这个问题
[5]。我认为正确的方法也是像id那样,先把左右两边都计算下来,并显式绑定到各自的名字上,然后再用is判断。

  [1] 
  [2] 
  [3] 
  [4] 
  [5] 

中的 is 和 id,pythonisid (ob1 is ob2)
等价于 (id(ob1) == id(ob2))
首先id函数可以获得对象的内存地址,如果两个对象的内存地址是一样的,那…

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图