Python programming often encountered some inexplicable errors, in fact, this is not a problem of the language itself, but we ignored some of the characteristics of the language itself, today we will look at the use of Python variables lead to three incredible errors, the future in the programming to pay more attention.
About Python programming runtime novice easy to make mistakes, here for the time being, see details:A short summary of 17 common mistakes made by newbies when running Python
1. Variable data types as default parameters in function definitions
Does this seem right? You wrote a little function that, for example, searches for links on the current page and optionally appends them to another provided list.
def search_for_links(page, add_to=[]): new_links = page.search_for_links() add_to.extend(new_links) return add_to
On the surface, this looks like perfectly normal Python code, and indeed it is, and it works. But there's a problem. If we give the add_to argument a list, it will work as we expect. But if we let it use the default values, something magical happens.
Try the code below:
def fn(var1, var2=[]): (var1) print(var2) fn(3) fn(4) fn(5)
Maybe you think we'll see:
[3] [4] [5]
But in reality, we see it:
[3] [3,4] [3,4,5]
Why? As you can see, the same list is used each time, so why is the output the way it is? In Python, when we write a function like this, the list is instantiated as part of the function definition. When the function runs, it's not instantiated every time. This means that the function will always use the exact same list object unless we provide a new one:
fn(3,[4]) [4,3]
The answer is just as we thought it would be. The correct way to get this result is:
def fn(var1, var2=None): ifnot var2: var2 =[] (var1)
Or in the first example:
def search_for_links(page, add_to=None): ifnot add_to: add_to =[] new_links = page.search_for_links() add_to.extend(new_links) return add_to
This will remove the instantiation when the module is loaded so that list instantiation occurs every time the function is run. Note that there is no need to take this into account for immutable data types such as tuples, strings, and integers. This means that code like the following is very doable:
def func(message="my message"): print(message)
2. Variable data types as class variables
This is very similar to the last error mentioned above. Think about the following code:
class URLCatcher(object): urls =[] def add_url(self, url): (url)
This code looks perfectly normal. We have an object that stores URLs. When we call the add_url method, it adds a given URL to the store. It looks pretty much right, right? Let's see what it actually looks like:
a =URLCatcher() a.add_url('') b =URLCatcher() b.add_url('') print() print()
Results:
['',''] ['','']
Wait, what's going on? That's not what we thought. We instantiated two separate objects, a and b. We gave one URL to a and the other to b. How can both objects have both URLs?
This is the same problem as the first wrong example. The URL list is instantiated when the class definition is created. All instances of the class use the same list. There are times when this is useful, but most of the time you don't want it. You want each object to have a separate storage. To do this, we modify the code to:
class URLCatcher(object): def __init__(self): =[] def add_url(self, url): (url)
Now, when the object is created, the URL list is instantiated. When we instantiate two separate objects, they will each use two separate lists.
3. Variable allocation error
This problem has been bothering me for some time. Let's make some changes and use another variable data type - dictionary.
a ={'1':"one",'2':'two'}
Now, suppose we want to use this dictionary for something else and keep its initial data intact.
b = a b['3']='three'
Easy, right?
Now, let's look at the original dictionary a that we don't want to change:
{'1':"one",'2':'two','3':'three'}
Whoa wait a minute, let's see b?
{'1':"one",'2':'two','3':'three'}
Wait, what? It's a bit messy ...... Let's go back and see what happens to other immutable types in this case, such as a tuple:
c =(2,3) d = c d =(4,5)
Now c is (2, 3) and d is (4, 5).
This function turned out as we expected. So what happened in the previous example? When using a mutable type, it behaves a bit like a pointer in C. In the code above, we have b = a. What we're really saying is that b becomes a reference to a. In the code above, when we say b = a, what we're really saying is that b is a reference to a. They both point to the same object in Python memory. Sound familiar? That's because this problem is similar to the previous one.
Does the same thing happen with lists? Yes. So how do we fix it? This has to be done very carefully. If we really need to copy a list for processing, we can do so:
b = a[:]
This will traverse and copy the reference to each object in the list and put it in a new list. But be careful: if every object in the list is mutable, we'll get references to them again, not full copies.
Suppose a list is made on a piece of paper. In the equivalent of the original example, person A and person B are looking at the same piece of paper. If one person changes this list, both will see the same changes. When we copy the reference, each person now has their own list. However, let's assume that this list includes places to find food. If "refrigerator" is the first in the list, even if it is copied, the entries in both lists point to the same refrigerator. So, if the fridge is modified by A and the big cake inside is eaten, B will also see the cake disappear. There is no easy way to fix it here. Just keep it in mind and write your code in a way that doesn't cause this problem.
Dictionaries work in the same way, and you can create an expensive copy by:
b = ()
Again, this only creates a new dictionary pointing to the same entries that existed originally. So if we have two identical lists, and we modify the mutable object pointed to by one of the keys in dictionary a, then we will see these changes in dictionary b as well.
The trouble with mutable data types is also what makes them powerful. None of these are problems in practice; they are problems to be careful to prevent. Using an expensive copy operation as a solution in a third project is not necessary 99% of the time.
summarize
The above is the whole content of this article about the 3 mistakes to avoid when using Python variables, I hope it will be helpful to you. Interested friends can continue to refer to this site:python explore BaseHTTPServer-implementation web server introduction、Python Exploration of SocketServer Detailsetc., if there are deficiencies, welcome to leave a message to point out. Thank you friends for the support of this site!