Reference vs Assignment in Python mutable objects

柔情痞子 提交于 2019-12-24 03:53:02

问题


Assignment:

>>> a = ['spam']
>>> b = ['spam']
>>> a is b
False

Reference:

>>> c = ['spam']
>>> d = c
>>> c is d
True
  1. What is the difference between above both?
  2. Why assignment results False?
  3. Why reference results True?

回答1:


Your first snippet creates two unique list objects, which are not the same. Hence a is b returns false because a and b are pointing to distinct objects:

          +------+
a ------> | list |
          +------+

          +------+
b ------> | list |
          +------+

Your second snippet creates a single list object, and points both c and d to that objects, hence c is d return true:

          +------+
c ------> | list | &lt------ d
          +------+

Note the following, from http://docs.python.org/3/reference/datamodel.html:

Every object has an identity, a type and a value. An object’s identity never changes once it has been created; you may think of it as the object’s address in memory. The is operator compares the identity of two objects; the id() function returns an integer representing its identity.

So is and == are very different; while the former compares object identity, the latter compares object values. Indeed, == tests in your snippets would return true.


Given the explanation above, it may come as a surprise that that the story is slightly different with strings:

>>> a = 'str'
>>> b = 'str'
>>> 
>>> a is b
True

This is due to string interning, which occurs in CPython (i.e. it's implementation specific). Therefore, if the same string literal shows up in two different places, the same string object will be used for both (with restrictions).

This is explained in greater detail in "Python string interning".




回答2:


when compare with is, like a is b, it's the same as id(a) == id(b), the code xx=['spam'] creates a new list each time and assigns it to xx, it's id changes each time, so a is b gives False




回答3:


Let me just add a few function calls to what you were originally doing. I think you will pick it up.

>>> a = ['spam']
>>> b = ['spam']
>>> a is b
False
>>> id(a)
4552359808
>>> id(b)
4552446176
>>> a == b
True
>>> c = ['spam']
>>> d = c
>>> id(c)
4552513296
>>> id(d)
4552513296
>>> c is d
True
>>> c == d
True
>>> print id.__doc__
id(object) -> integer

Return the identity of an object.  This is guaranteed to be unique among
simultaneously existing objects.  (Hint: it's the object's memory address.)



回答4:


This has nothing to do with some (inexistant) "assignment vs reference" question.

>>> a = ['spam']

creates a list with the string 'spam' in it, and binds it to names 'a' in the current scope.

>>> b = ['spam']

creates another list with the string 'spam' in it, and binds it to names 'b' in the current scope.

You create two lists, you have two lists. Plain simple.

>>> c = ['spam']

creates yet another list with the string 'spam' in it, and binds it to names 'c' in the current scope.

>>> d = c

binds name 'd' to whatever 'c' is bound to at that time in the current scope.

Here you create one list and bind 2 names to it. Both name points to the same object.

The point is: Python's "variables" are not named memory adresses, just names pointing to objects. At a given time, one object can be bound to (pointed to by) any number of names (and even by no name at all).



来源:https://stackoverflow.com/questions/21092937/reference-vs-assignment-in-python-mutable-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!