A deep understanding of variable assignment in Python and a deep understanding of python
Preface
In Python, the variable name rules, like most other advanced languages, are affected by the C language. In addition, the variable name is case sensitive.
Python is a dynamic type language. That is to say, you do not need to declare the variable type in advance. The type and value of the variable are initialized at the moment of value assignment. The following describes how to assign values to the Python variable. Let's take a look at it.
Let's take a look at the following code:
c = {}def foo(): f = dict(zip(list("abcd"), [1, 2 ,3 ,4])) c.update(f)if __name__ == "__main__": a = b = d = c b['e'] = 5 d['f'] = 6 foo() print(a) print(b) print(c) print(d)
Output result:
{'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4, 'f': 6}{'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4, 'f': 6}{'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4, 'f': 6}{'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4, 'f': 6}
If you are not surprised with the above output results, you don't have to look down. In fact, the content to be discussed in this article is very simple. Do not waste your precious time on this.
Python is a dynamic language. The program structure can be changed at any time during the running process, and python is still a weak-type language. Therefore, if you are switching from a static or strong-type programming language, understanding Python assignment may feel a bit confusing at the beginning.
You may think the output of the above Code will be like this:
{}{'e': 5}{}{'f': 6}
You may think that a has not been changed, because you have not seen any changes to it; B and d changes are obvious; c, because they are changed in the function, you may think that c is a local variable, so the global c will not be changed.
In fact, a, B, c, and d point to a memory space, which can store a dictionary object. This is a bit like a pointer in c. Four pointers, a, B, c, and d, point to the same memory address, that is, four pen names for the memory. Therefore, no matter who you change, the other three variables will change. So why is c changed inside the function and does not use the global statement, but the global c is changed?
Let's look at an example:
>>>a = {1:1, 2:2}>>>b = a>>>a[3] = 3>>>b{1: 1, 2: 2, 3: 3}>>>a = 4>>>b{1: 1, 2: 2, 3: 3}>>>a4
When B = a, a and B point to the same object. Therefore, when an element is added to a, B also changes. When a = 4, a no longer points to the dictionary object, but to a new int object (an integer in python is also an object). At this time, only B points to the dictionary, so when a changes, B does not change. This only shows when the value assignment variable changes qualitatively, and the above problems have not been solved.
Let me look at another example:
class TestObj(object): passx = TestObj()x.x = 8d = {"a": 1, "b": 2, "g": x}xx = d.get("g", None)xx.x = 10print("x.x:%s" % x.x)print("xx.x: %s" % xx.x)print("d['g'].x: %s" % d['g'].x)# Out:# x.x:10# xx.x: 10# d['g'].x: 10
As you can see from the instance above, if you only change the attributes of an object (or change the structure), all the variables pointing to the object will change accordingly. However, if a variable points to an object again, other variables pointing to the object will not change. Therefore, in the first example, although c is changed inside the function, c is a global variable. We only add a value to the memory pointed to by c, instead of pointing c to another variable.
Note that some people may think that the last output in the above example should be d ['G']. x: 8. The reason for this understanding may be that the 'G' value in the dictionary has been taken out and renamed as xx, so xx has nothing to do with the dictionary. Actually, this is not the case. The value corresponding to the key in the dictionary is like a pointer pointing to a memory area. when accessing the key in the dictionary, the value is taken from this area, if the value is assigned to another variable, for example, xx = d ['G'] or xx = d. get ("g", None), so that the variable xx also points to the region, that is, the keys 'g' and xx objects in the dictionary point to the same memory space, when we only change the attributes of xx, the dictionary also changes.
The following example shows this more intuitively:
class TestObj(object): passx = TestObj()x.x = 8d = {"a": 1, "b": 2, "g": x}print(d['g'].x)xx = d["g"]xx.x = 10print(d['g'].x)xx = 20print(d['g'].x)# Out:# 8# 10# 10
This knowledge point is very simple, but if you do not understand it, you may not be able to understand other people's code. This sometimes brings great convenience to program design, such as designing a context that saves the state in the entire program:
class Context(object): passdef foo(context): context.a = 10 context.b = 20 x = 1def hoo(context): context.c = 30 context.d = 40 x = 1if __name__ == "__main__": context = Context() x = None foo(context) hoo(context) print(x) print(context.a) print(context.b) print(context.c) print(context.d)# Out:# None# 10# 20# 30# 40
In the example, we can add the state to be saved to the context, so that these states can be used anywhere during the entire program running.
In the next final example, execute the external code:
Outer_code.py
from __future__ import print_functiondef initialize(context): g.a = 333 g.b = 666 context.x = 888def handle_data(context, data): g.c = g.a + g.b + context.x + context.y a = np.array([1, 2, 3, 4, 5, 6]) print("outer space: a is %s" % a) print("outer space: context is %s" % context)
Main_exec.py
From _ future _ import print_functionimport sysimport impfrom pprint import pprintclass Context (object): passclass PersistentState (object ): pass # Script starts from hereif _ name _ = "_ main _": outer_code_moudle = imp. new_module ('outer _ Code') outer_code_moudle. _ file _ = 'outer _ code. py 'sys. modules ["outer_code"] = outer_code_moudle outer_code_scope = code_scope = outer_code_moudle. _ dict _ head_code = "import numpy as np \ nfrom main_exec import PersistentState \ ng = PersistentState ()" exec (head_code, code_scope) origin_global_names = set (code_scope.keys ()) with open ("outer_code.py", "rb") as f: outer_code = f. read () import _ future _ code_obj = compile (outer_code, "outer_code.py", "exec", flags =__ future __. unicode_literals.compiler_flag) exec (code_obj, code_scope) # removes the attributes of the built-in namespace and only keeps the attributes outer_code_global_names = set (outer_code_scope.keys () added in the external code ()) -origin_global_names outer_func_initialize = code_scope.get ("initialize", None) outer_func_handle_data = code_scope.get ("handle_data", None) context = Context () context. y = 999 outer_func_initialize (context) outer_func_handle_data (context, None) g = outer_code_scope ["g"] assert g. c == 2886 print ("g. c: % s "% g. c) print (dir (g) print (dir (context) pprint (outer_code_moudle. _ dict __)
Summary
The above is all about this article. I hope this article will help you in your study or work. If you have any questions, please leave a message.