Variables are fundamental concepts in programming, and Python variables may seem simple, but they can cause problems if not understood properly and copied mechanically.
Here are 10 code examples to show the nature of variables in Python.
It’s just a name
When a appears on the left side of an assignment statement, it simply represents a name:
a = 1024
a = 'davycloud'
a = ['thumb up'.'attention'.'collection']
Copy the code
Once the assignment is complete, the name is bound to the object on the right. And in the process,
-
a
It doesn’t matter if you’re already bound to other objects, that is, you don’t care
a
It’s bound to something, or it’s not bound to anything, it’s a name. -
As long as the name is legal, it can be bound to any object regardless of its type
2. Object reference
The name of the bound object, known as a variable, represents a reference to the object when it appears on the right side of an assignment statement:
a = []
b = a
Copy the code
When a is assigned to b, a represents a reference to a list object, that is:
-
List object ontologies are not affected
-
A new list is not copied
-
a
和
b
After that it’s all references to the same list
Since lists are mutable objects, they can be changed by either a or B, both of which reflect the change in the object:
a.append(1) # a = [1], b = [1]
b.append(2) # a = [1, 2], b = [1, 2]
Copy the code
”
Mutable objects are discussed again below
3. First right, then left
When multiple assignments are concatenated, they are processed from right to left:
a = b = []
Copy the code
Here b is first used as a name, bound to a list object; It then acts as a reference to the object and gives it another name, A, which is equivalent to:
Writing # 1
b = []
a = b
Copy the code
This has very different consequences from the following assignment:
# write 2
b = []
a = []
Copy the code
In this case, two variables are bound to two different lists that are unrelated to each other.
But there is an interesting point here. If we replace [] with an integer 1 or a string, there is no difference in the result between the 1 and 2 assignments.
4. Change depends on the object
Continuing with the example above, where two names are bound to the same list and the other is affected by manipulating one of them:
b = []
a = b
a.append(1)
Copy the code
This is because a list is a mutable object. If you replace a list with a number or string:
b = 'davy'
a = b
a += 'cloud'
Copy the code
Increment operation on A does not affect B. First give the equivalent form of the increment operation:
a = a + 'cloud'
Copy the code
So this is still an assignment. Using the previous conclusion:
-
The right of the
a
Represents a reference to an object, that is
'davy'
, and it
'cloud'
The sum generates a new object -
On the left side of the
a
Is a name, it again and the new object, i.e
'davycloud'
Bind together
In other words, there are three string objects created.
When we look closely, we can see that when we want to change an object, we must do so through the interface provided by the object (append or subscript in the case of a list, or change its properties in the case of other objects), not through reassignment.
Assignment is just a binding of the name, again.
Here’s another conclusion:
Immutable objects are referenced/bound multiple times without side effects. Such as:
# a, b bind to the same object
a = b = 'davy'
# a and b are bound to an object
a = 'davy'
b = 'davy'
Copy the code
In the example above, the syntactic meaning of the two bindings is different, but because strings are immutable, that is, even if A and B are bound to the same string, they do not affect each other. Why create two identical Davy strings in memory? Better direct reuse, can save a bit of memory:
>>> a = 'davy'
>>> b = 'davy'
>>> a is b
True
Copy the code
Again, however, this optimization is not global, that is, it is not necessarily a unique object as long as it is the same string:
>>> a += 'cloud'
>>> b += 'cloud'
>>> a is b
False
>>> a
'davycloud'
>>> b
'davycloud'
>>> a == b
True
Copy the code
So, it’s good to know that for immutable objects, use == instead of is, because it can produce weird results that are sometimes true and sometimes false.
5. The secret of instant exchange
When multiple objects, or references to multiple objects, appear to the right of an assignment statement, they are automatically packaged into a tuple.
On the left side of the assignment statement, there needs to be the same number of names to unpack:
a = [1024]
b = 'davycloud'
a, b = b, a
Copy the code
In this example, a combination of the first three rules is used:
-
Right rear left first
-
Variables are references to objects
-
On the left is the name
It is not hard to conclude that the two names have swapped references to objects, and the object body has not been moved.
6. It’s all about the name
A does not assign a value, and runs directly as a result:
>>> print(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
Copy the code
This seems easy to explain, but the variable A is not defined. Just add a line of assignment.
But:
-
The error reported here is
NameError
:
name‘A’ is not defined, the name is not defined error, not the variable is not defined -
If you think about it, this
a
What is it? Numbers? The string? Function? The class? Modules?
7. We’re all variables
Here’s another example:
a = 1
def a():
pass
class a():
pass
import sys as a
Copy the code
Not only do you assign values, define functions, define classes, import modules or objects in modules, it’s all in the binding name.
To define a function is to bind a name to a function object, to define a class is to bind a name to a class object, and to import a module is to bind a name to a module object.
Everything is an object in Python, so they are variables.
8. Passing references is just naming
Now that we’re talking about functions, let’s look at passing parameters to functions:
def func(x):
return x
Copy the code
This function is useless, but it does explain the passing in and out of arguments.
a = func(1024)
b = func(a)
Copy the code
The parameter x is also a name, but its scope is limited to the func function itself.
Passing a parameter to a function is like assigning, binding an object to the inner name, and passing a reference to an object, like the variable appearing on the right side of the assignment:
# pseudocode
func(1024):
x = 1024
a = x
Copy the code
”
The scope of a variable is covered here and will be discussed in more detail.
Note that the above rules are the same for all object types, whether mutable or immutable.
From the above analysis, it is easy to draw the conclusion that:
-
If the argument/return is an immutable object, then it has no side effects
-
If the argument/return is a mutable object, then operations on it within the function affect other variables bound to the object
Therefore, you need to be careful about passing arguments to mutable objects. In particular, do not use mutable objects for default arguments to functions.
Because the binding of default arguments happens at the function definition stage:
def get_people(people=[]):
return people
Copy the code
When get_people is called, unless people is given an argument, it is always bound to the list that was created at the time the function was defined. Our intention might be to generate an empty list if there are no arguments by default.
A common practice is to create a new object inside the function:
def get_people(people=None):
if people is None:
people = []
return people
Copy the code
9. Undeleted objects
Python provides the del keyword to be used
Variable, however, the effect of this operation is to unbind the variable name from the object and then delete the name. The deleted name will trigger if accessed again
NameError
It’s as if it never existed.
Objects, on the other hand, just subtract a reference:
a = [1, 2, 3]
b = a
del a # doesn't affect B at all
Copy the code
It makes sense that an object will not be cleared if more than one variable is referenced to it. Even if no name is currently bound to the object, the object will not be deleted immediately:
>>> a = []
>>> id(a)
2292904305736
>>> del a
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> b = []
>>> id(b)
2292904305736
Copy the code
In short, del means unbind, don’t expect it to delete objects.
”
Reference counting and destruction of objects are maintained internally in Python, and generally we don’t care. For those interested, check out Python’s garbage collection section.
Shallow copy? Zero copy!
Final example:
a = [[]] * 3
a[0].append(1)
print(a) # [[1], [1], [1]]
Copy the code
It’s a little confusing here, because you’re using the * operation on the list. When multiplying a list, the common understanding is to copy its elements.
See copy is easy to refer to the so-called shallow copy and deep copy, here is obviously not a deep copy, so it is easy to take for granted is a shallow copy, wrong!
Here’s just another invisible assignment, so let’s expand it:
x = []
y = [x]
a = [x, x, x] The equivalent of a = y * 3
a[0].append(1)
print(a)
Copy the code
The most important thing is line 3:
-
y * 3
Is to get the
y
Element replication in
3
份 -
And now this element is going to be
x
. -
let
x
repeated
3
Time! -
The actual effect is that
[x, x, x]
.
X is a reference to the object, so we just made three copies of the reference to the object, leaving the object itself untouched.
So what do you do to actually copy this list? Using the system-provided shallow copy function, or using slicing:
# list built-in copy method
a = [x.copy() for i in range(3)]
# Using slices
a = [x[:] for i in range(3)]
Make use of the Copy library
from copy import copy
a = [copy(x) for i in range(3)]
Copy the code
The first two methods are built-in interfaces for list objects, while the copy module is more generic.
summary
-
A variable is a name bound to an object
-
When binding, the variable is the name
-
When used, a variable represents a reference to an object
-
Variables change only the binding relationship
-
To change/copy an object, you need to see if the object provides methods
In addition to the above, another important concept about variables is understanding their scope, which will be covered in another article.
If this article has been helpful to you, please like, share and follow. Thank you!