In-depth exploration of the copy and scope of Python variables, python Variables

Source: Internet
Author: User

In-depth exploration of the copy and scope of Python variables, python Variables

In python, the value assignment statement always creates an object reference value, instead of copying an object. Therefore, python variables are more like pointers than data storage areas,

This is similar to most OO languages, such as C ++ and java ~
1. Let's look at the problem first:

In Python, the result of making values = [0, 1, 2]; values [1] = values is [0, [...], 2].
 

>>> values = [0, 1, 2]>>> values[1] = values>>> values[0, [...], 2]

I expected to be

[0, [0, 1, 2], 2]

But why does the result have to be assigned an unlimited number of times?

It can be said that Python has no value assignment and only references. This is equivalent to creating a structure that references itself, resulting in an infinite loop. To understand this problem, we need to clarify a basic concept.

Python does not have a "variable". The variables we usually call are actually "tags" and references.

Run

values = [0, 1, 2]

In this case, Python first creates a list object [0, 1, 2], and then attaches a tag named values to it. If you execute

values = [3, 4, 5]

In this case, Python creates another list object [3, 4, 5], and then extracts the tag named values from the front [0, 1, 2] The object is torn down and re-pasted to the object [3, 4, 5.

At the beginning and end, no list object container named values exists, and Python does not copy the values of any objects into values. Process:

Run

values[1] = values

In this case, Python points the second element of the list object referenced by the values tag to the list object referenced by values. After the execution, the values tag still points to the original object, but the structure of the object has changed from [0, 1, 2] to [0 ,?, 2], and this? It is a reference pointing to the object itself. :

To achieve the desired effect, obtain the object [0, [0, 1, 2], 2, you cannot directly direct values [1] to the object referenced by values. Instead, you need to [0, 1, 2] Copy this object to get a new object, then point values [1] to the Copied object. Operations on copying objects in Python vary with object types. Operations on copying list values are

Values [:] # generate a copy or Copy Sequence of an object. It is no longer a reference or shared variable. However, this method can only be used for top-level replication.

So you need to execute

values[1] = values[:]

In Python, dereference is used to obtain the object [0, 1, 2] pointed to by values, and then [0, 1, 2] [:] copy the operation to get a new object, the content is also [0, 1, 2], and then point the second element of the list object pointed to by values to the list object of the copy, finally, values points to [0, [0, 1, 2], 2]. Process:

To put it deeper, the values [:] replication operation is called shallow copy. When the list object is nested, unexpected errors are generated, such

a = [0, [1, 2], 3]b = a[:]a[0] = 8a[1][1] = 9

Q: What Is a and B respectively?

The correct answer is that a is [8, [1, 9], 3], B is [0, [1, 9], 3]. Found? The second element of B is also changed. Think about why? If you do not understand

The correct way to copy nested elements is to perform deep copy. The method is

 

import copy a = [0, [1, 2], 3]b = copy.deepcopy(a)a[0] = 8a[1][1] = 9

2. Reference VS copy:

(1) fragment expressions without restrictions (L [:]) can copy sequences, but this method can only replicate in a shallow layer.

(2) The dictionary copy method. D. copy () can be used to copy the dictionary, but this method can only be used to copy the dictionary in a shortest mode.

(3) some built-in functions, such as list, can generate copy list (L)

(4) The copy standard library module can generate a complete copy: deepcopy is essentially recursive copy.

(5) For immutable objects and mutable objects, shallow replication is a copy reference, only because the reference of the copy object and the copy object are equivalent (because the object is immutable, the new object will be assigned a new value when it is changed ). So it seems that shortest copy only copies immutable objects (integers, real numbers, strings, etc.). For mutable objects, shortest copy actually creates a reference to this object, that is to say, it only adds another tag to the same object.
 

L = [1, 2, 3]D = {'a':1, 'b':2}A = L[:]B = D.copy()print "L, D"print L, Dprint "A, B"print A, Bprint "--------------------"A[1] = 'NI'B['c'] = 'spam'print "L, D"print L, Dprint "A, B"print A, B  L, D[1, 2, 3] {'a': 1, 'b': 2}A, B[1, 2, 3] {'a': 1, 'b': 2}--------------------L, D[1, 2, 3] {'a': 1, 'b': 2}A, B[1, 'NI', 3] {'a': 1, 'c': 'spam', 'b': 2}

3. Enhanced assignment and shared reference:

X = x + y, x appears twice, it must be executed twice, performance is not good, merging must create object x, and then copy the two lists to merge

Copy/copy

X + = y, x only appears once, and will only be calculated once. The performance is good. If new objects are not generated, only elements are added at the end of the memory block.

When x and y are list, + = will automatically call the extend method for the merge operation, in-place change.

Shared reference
 

L = [1, 2]M = LL = L + [3, 4]print L, Mprint "-------------------"L = [1, 2]M = LL += [3, 4]print L, M  [1, 2, 3, 4] [1, 2]-------------------[1, 2, 3, 4] [1, 2, 3, 4]

4. variable scope problems caused by changing statements from python 2.x to python 3.x

First look at the code segment:
 

def test():  a = False  exec ("a = True")  print ("a = ", a)test() b = Falseexec ("b = True")print ("b = ", b)

In python 2.x and 3.x, you will find that their results are different:
 

2.x:a = Trueb = True 3.x:a = Falseb = True

Why?

Because exec in 3.x is changed from a statement to a function, the variables in the function are local by default, that is

The two a variables you see are in different namespaces without conflict.

For details, refer to learning python P331-P332.

If you know the reason, we can change it like this:
 

def test():  a = False  ldict = locals()  exec("a=True",globals(),ldict)  a = ldict['a']  print(a) test() b = Falseexec("b = True", globals())print("b = ", b)

Someone has asked this question on stackoverflow, and someone has reported a bug in python...

The specific link is as follows:

Http://stackoverflow.com/questions/7668724/variables-declared-in-execed-code-dont-become-local-in-python-3-documentatio

Http://bugs.python.org/issue4831

Http://stackoverflow.com/questions/1463306/how-does-exec-work-with-locals


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.