Easy Tutorial
❮ Android Tutorial Baseadapter Android Tutorial Typeface ❯

Reference and Copy in Variable Assignment in Python

Category Programming Techniques

I once came across a question where an element in a dictionary was a list. When this list element was assigned to a variable and the values within the list were modified, the list in the dictionary was also altered. The question was as follows:

dict = {'a':[1,2,3,4,5],'b':2}
x = dict['a']
for i in range(5):
    x[i] = 0
print(dict['a'])

The program's output was: [0, 0, 0, 0, 0]

This raises the question of whether Python assigns by reference or by copying. In the above scenario, assigning the value of "a" to x resulted in the modification of the dictionary's list. However, if "b" was assigned to x, modifying x would not affect the dictionary.

>>> dict = {'a':[1,2,3,4,5],'b':2}
>>> x = dict['b']
>>> x
2
>>> x=x+3
>>> x
5
>>> dict
{'a': [1, 2, 3, 4, 5], 'b': 2}
>>>

So, when does variable assignment pass by value (copy) and when by reference (address)?

1. Explicit Copying

When unsure whether it's a reference or a copy, you can explicitly copy. For instance, dictionaries have a built-in copy method:

x=dict.copy()

For objects without a copy method, you can use deep copy, which is provided by Python's copy module. Deep copy duplicates all data related to the original variable, creating a separate memory space. Modifying one of these variables will not affect the other. Using the previous example:

import copy
dict = {'a':[1,2,3,4,5],'b':2}
x = copy.deepcopy(dict['a'])
for i in range(5):
    x[i] = 0
print(dict['a'])

The dictionary's value remains unaffected. The copy module also offers a shallow copy method. For simple objects, both deep and shallow copies are identical. The dictionary's copy method is a shallow copy.

>>> dict
{'a': [8, 2, 3, 4, 5], 'b': 4}
>>> dd=copy.copy(dict)
>>> dd
{'a': [8, 2, 3, 4, 5], 'b': 4}
>>> dd['a'][0]=7
>>> dd
{'a': [7, 2, 3, 4, 5], 'b': 4}
>>> dict
{'a': [7, 2, 3, 4, 5], 'b': 4}
>>> ee=dict.copy()
>>> ee
{'a': [7, 2, 3, 4, 5], 'b': 4}
>>> ee['a'][0]=9
>>> ee
{'a': [9, 2, 3, 4, 5], 'b': 4}
>>> dict
{'a': [9, 2, 3, 4, 5], 'b': 4}
>>> ee['b']=5
>>> ee
{'a': [9, 2, 3, 4, 5], 'b': 5}
>>> dict
{'a': [9, 2, 3, 4, 5], 'b': 4}
>>>

Shallow copy modifies the first level independently (e.g., dictionary's b value), but the second level (e.g., dictionary's a list value) affects all copies. Checking the IDs:

>>> id(dict)
20109472
>>> id(dd)
20244496
>>> id(ee)
20495072
>>> id(dd['a'])
20272112
>>> id(ee['a'])
20272112
>>> id(dict['a'])
20272112
>>>

The dictionary copies have different IDs, but the list within the dictionary has the same ID. For a true copy, use deep copy.

2. Assignment Rules

Python does not explicitly distinguish between copying and referencing. Generally, static variables are passed by copy, and dynamic variables by reference. (Note: Static variables are initially passed by reference but require a new memory space for modification.)

Variables can be complex, such as dictionaries containing lists or lists containing dictionaries. However, assignment always falls under one type. If unsure, use the id() function to check if variables reference the same address. For example:

>>> a=6
>>> id(a)
10413476
>>> b=a
>>> id(b)
10413476
>>> b=8
>>> id(b)
10413452
>>>

Before modifying b, a and b reference the same address. After modification, the address changes.

>

Original link: https://blog.csdn.net/iamlaosong/article/details/77505510

** Share My Notes

Cancel

-

-

-

❮ Android Tutorial Baseadapter Android Tutorial Typeface ❯