Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
108 views
in Technique[技术] by (71.8m points)

python - Why variable = object doesn't work like variable = number

These variable assignments work as I expect:

>>> a = 3
>>> b = a
>>> print(a, b)
(3, 3)
>>> b=4
>>> print(a, b)
(3, 4)

However, these assignments behave differently:

>>> class number():
...     def __init__(self, name, number):
...         self.name = name
...         self.number = number
... 
>>> c = number("one", 1)
>>> d = c
>>> print(c.number, d.number)
(1, 1)
>>> d.number = 2
>>> print(c.number, d.number)
(2, 2)

Why is c is same as d, unlike in (a, b) example? How can I do something like in (a, b) in (c, d) classes example? That is, copy the object and then change one part of it (that won't affect the object that I borrowed properties from)?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

These lines:

c = number("one", 1)
d = c

...are effectively:

  • Create a new instance of number and assign it to c
  • Assign the existing reference called c to a new variable d

You haven't changed or modified anything about c; d is another name that points to the same instance.

Without cloning the instance or creating a new instance, you can't do anything similar to how the primitive int is behaving.


To correct a bit of information, the explanation above is rather simplified and a bit incomplete in its nature, although it mostly describes what's going on at 10,000 feet.

For a closer look, we have to realize a few things about Python's variables, or "names", and how they interact with this program.

As mentioned above, you have the notion of "names" and "bindings", which are pretty straightforward to reason at:

a = 3
b = a

In this context, a is a name, and b is a binding to a. We haven't modified or changed anything about a.

As noted before, there are two types of data in Python: mutable and immutable. A name that points to immutable data, such as primitives and tuples, can be reassigned without any ill effect to any other bindings present on it, because no state is changing with respect to the binding.

This is why this reassignment does what we would expect it to:

print(a, b)
b = 4
print(a, b)

The result of b = 4 is that b is now pointing at a new copy of an integer, the value 4.

Recall that I did mention tuples as immutable data. You can't change the binding of a particular entity in your tuple...

t = ('foo', 'bar')
t[0] = 'baz' # illegal

...but you can have mutable data structures as part of those bindings.

t = ([1, 2, 3], 'bar')
t[0].append([4, 5, 6]) # ([1, 2, 3, [4, 5, 6]], 'bar')

So where does that leave our example?

c = number("one", 1)
d = c

number is a mutable type which is named as c, and its values can be changed at will between multiple different bindings to c.

Effectively, we've got a name and a binding to a name:

  • We have a new instance of number and refer to it by the name c.
  • Bind the reference c to another name d.

Again, nothing's changed about c, but it can be referenced through another name.

Unlike with the immutable data, when we reassign the value of d.number, we're reassigning the same binding that c is aware of:

>>> id(d.number)
36696408
>>> id(c.number)
36696408

This is why you require either a new instance or a copy. You have to refer to a different instance of number. With this simple binding, you're not going to accomplish that.

from copy import copy
c = number("one", 1)
d = copy(c)
id(c) # 140539175695784
id(d) # 140539175695856

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...