Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the pits that use Python?

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly explains "what are the pits of using Python". The content of the explanation is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn what are the pits of using Python.

Pit 01-pit for integer comparison

In Python, everything is an object, and integers are also objects. When comparing two integers, there are two operators = = and is. The difference between them is:

Is compares whether the id values of two integer objects are equal, that is, whether two references represent the same address in memory.

= = compares whether the contents of two integer objects are equal. When you use = =, you actually call the object's _ _ eq__ () method.

Now that we know the difference between is and = =, let's take a look at the following code to see which pits there are in integer comparisons in Python:

Def main (): X = y =-1 while True: X + = 1 y + = 1 if x is y: print ('d is% d'% (x, y)) else: print ('Attention!% d is not% d'% (x) Y)) break x = y = 0 while True: X-= 1 y-= 1 if x is y: print ('% d is% d'% (x Y) else: print ('Attention!% d is not% d'% (x, y)) breakif _ _ name__ =' _ _ main__': main ()

Part of the running result of the above code is shown in the figure below, which is due to an optimization made by Python for performance reasons. For integer objects, Python caches some frequently used integer objects and saves them to a linked list called small_ints. In the entire life cycle of Python, wherever these integer objects are needed, new objects are not recreated, but objects in the cache are directly referenced. Python sets the value of frequently used integer objects in the range of [- 5256], and if you need integers in this range, get references directly from small_ints instead of temporarily creating new objects. Because integers greater than 256 or less than-5 are not in this range, even if the values of the two integers are the same, they are different objects.

Of course, this pit is not worth mentioning, if you understand the above rules, let's take a look at the following code.

Import disa = 257def main (): B = 257 # Line 6 c = 257 # Line 7 print (b is c) # True print (an is b) # False print (an is c) # Falseif _ _ name__ = = "_ _ main__": main ()

The execution result of the program has been written on the code with comments. How cheating it is! It looks like the values of a, b, and c are all the same, but the result of the is operation is different. First of all, let's talk about the code blocks in the Python program.

The so-called code block is the smallest basic execution unit of a program. A module file, a function body, a class, and a single line of code in interactive commands are all called a code block. The above code consists of two code blocks, a = 257 is a code block, and the main function is another code block.

In order to further improve the performance within Python, if the value of an integer object created in a code block is not within the scope of the small_ints cache, but there is already an integer object with the same value in the same code block, then refer to the object directly, otherwise a new object is created. This rule does not apply to negative numbers that are not in the scope of small_ints, nor to negative floating-point numbers. But it is applicable to both non-negative floating point numbers and strings, which the reader can prove by himself. So b is c returns True, and an and b are not in the same code block, although the values are 257, but they are two different objects, and the result of the is operation is naturally False.

To verify this conclusion, we can look at this code from a bytecode point of view by borrowing the dis module (which is disassembled as you can tell by the name). If you don't understand what bytecode is, you can take a look at the article "talking about how Python programs work". You can first import the dis module with import dis and modify the code as shown below.

If _ _ name__ = "_ _ main__": main () dis.dis (main)

The execution result of the code is shown in the following figure.

You can see that lines 6 and 7, that is, 257 in the main function, are loaded from the same location, so they are the same object; while an in line 9 is obviously loaded from different places, so different objects are referenced.

If you want to dig deeper into this problem, we recommend that you read the article "principles of Python Integer object implementation".

Pit 02-pits with nested lists

There is a built-in data type in Python called list, which is a container that can be used to hold other objects (references to other objects, to be exact). Objects in a list can be called elements of a list. Obviously, we can use a list as an element in a list, which is called a nested list. Nested lists can simulate real tables, matrices, maps of 2D games (such as plants vs. zombies), chessboards (such as chess, black and white), and so on. But be careful when using nested lists, or you are likely to encounter a very embarrassing situation. Here is a small example.

Def main (): names = ['Guan Yu', 'Zhang Fei', 'Zhao Yun','Ma Chao', 'Huang Zhong'] subjs = ['Chinese', 'Mathematics', 'English'] scores = [[0] * 3] * 5 for row, name in enumerate (names): print ('Please enter% s score'% name) for col Subj in enumerate (subjs): scores [row] [col] = float (input (subj +':')) print (scores) if _ _ name__ ='_ main__': main ()

We want to enter the scores of five students in three courses, so we define a list of five elements, and each element in the list is a list of three elements, so the list of such a list happens to be consistent with a table, which is equivalent to five rows and three columns. Then we enter the scores of three courses for each student through a nested for-in loop. After the completion of the program, we found that the scores of each student in the three courses were exactly the same, and it was the result of the last student.

To fill this hole, we first need to distinguish between the two concepts of object and object reference, and to distinguish between the two concepts, we also have to talk about the stack and heap in memory. We often hear people talk about the word "stack", but in fact "stack" and "stack" are two different concepts. As we all know, when a program is running, it needs to occupy some memory space to store data and code, so the memory can be further divided logically. Most programmers who have knowledge of the underlying language (such as C) know that the memory that can be used in a program can be logically divided into five parts, from highest to lowest address: stack, heap, data segment, static area, and code segment. Among them, the stack is used to store local and temporary variables, as well as the data needed to save and recover the site when the function is called. This part is automatically allocated when the code block starts to execute and is automatically released at the end of the code block execution. It is usually automatically managed by the compiler. The size of the heap is not fixed and can be dynamically allocated and recycled, so if there is a large amount of data in the program that needs to be processed, the data is usually placed on the heap. If the heap space is not released correctly, it will cause memory leakage, while programming languages such as Python and Java use garbage collection mechanism to achieve automatic memory management (automatic collection of unused heap space). So in the following code, variable an is not a real object, it is a reference to an object, equivalent to recording the address of the object in the heap space, through which we can access the corresponding object; similarly, variable b is a reference to a list container on the heap space, which refers to a list container on the heap space, while there is no real object in the list container, it only holds a reference to the object.

A = object () b = ['apple',' pitaya', 'grape']

Knowing this, we can look back at the program just now. When we operated [[0] * 3] * 5 on the list, we only copied the address of the list [0,0,0] and did not create a new list object. So although there are five elements in the container, these five elements refer to the same list object. This can be confirmed by checking the addresses of scores [0] and scores [1] by the id function. So the correct code should be modified as follows.

Def main (): names = ['Guan Yu', 'Zhang Fei', 'Zhao Yun','Ma Chao', 'Huang Zhong'] subjs = ['Chinese', 'Mathematics', 'English'] scores = [[]] * 5 for row Name in enumerate (names): print ('Please enter the score of% s'% name) scores [row] = [0] * 3 for col, subj in enumerate (subjs): scores [row] [col] = float (input (subj +':') print (scores) if _ name__ = ='_ main__': main ()

Or

Def main (): names = ['Guan Yu', 'Zhang Fei', 'Zhao Yun','Ma Chao', 'Huang Zhong'] subjs = ['Chinese', 'Mathematics', 'English'] scores = [[0] * 3 for _ in range (5)] for row Name in enumerate (names): print ('Please enter the score of% s'% name) scores [row] = [0] * 3 for col, subj in enumerate (subjs): scores [row] [col] = float (input (subj +':') print (scores) if _ name__ = ='_ main__': main ()

If you don't quite understand the use of memory, you can take a look at the code visualization execution function available on the PythonTutor website. Through visual execution, we can see how memory is allocated, thus avoiding the pitfalls that may be encountered when using nested lists or copying objects.

Pit 03-access the pit of the modifier

Anyone who has done object-oriented programming with Python knows that Python's classes provide two kinds of access control permissions, one is public, the other is private (double underscore before properties or methods). People who are used to programming languages like Java or C # know that the properties (data abstraction) in a class are usually private in order to protect the data, while the methods (behavior abstraction) in the class are usually public because the methods are the services provided by the object to the outside world. However, Python does not guarantee the privacy of private members at the syntax level, because it only names the so-called private members in the class. If you know the naming rules, you can still access private members directly, see the following code.

Class Student (object): def _ init__ (self, name, age): self.__name = name self.__age = age def _ str__ (self): return self.__name +':'+ str (self.__age) def main (): stu = Student ('Luo Hao') 38) # 'Student' object has no attribute' _ _ name' # print (stu.__name) # you can also access the private member print (stu._Student__name) print (stu._Student__age) if _ _ name__ ='_ _ main__': main () in the class in the following way

Why would Python make such a setting? Explain the problem with a popular maxim: "We are all consenting adults here" (we are all adults). This sentence expresses a common view of many Python programmers that it is better to be open than closed, and that we should be responsible for our own actions rather than restricting access to data or methods at the language level.

So in Python we really don't need to treat properties or methods in a class as private members with names that start with a double underscore, because it doesn't make any practical sense. If you want to protect properties or methods, we recommend using protected members that start with a single underscore, although it does not really protect these properties or methods, but it is tantamount to giving the caller a hint that this is a property or method that should not be accessed directly, and doing so does not affect subclasses inheriting these things.

It should be noted that the magic methods in the Python class, such as _ _ str__, _ _ repr__, etc., are not private members. Although they begin with a double underscore, they also end with a double underscore. This naming is not the name of a private member, which is rather tricky for beginners.

Thank you for your reading, the above is the content of "what are the pits that use Python". After the study of this article, I believe you have a deeper understanding of what the pits that use Python have, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report