Table of Contents
Avoid mutable objects as default parameters
Correct use of variable default parameters
Scope in Python
AttributeHide" >ClassAttributeHide
tuple是“可变的”
Python的深浅拷贝
模块循环依赖
Home Backend Development Python Tutorial Detailed explanation of Python traps and precautions commonly encountered in development

Detailed explanation of Python traps and precautions commonly encountered in development

Mar 16, 2017 pm 05:05 PM
python

I have encountered some pitfalls recently when using Python, such as using the datetime.datetime.now() variable objectAs the default parameters of functions , modules loops dependencies, etc.

Record it here for future query and supplement.

Avoid mutable objects as default parameters

In the process of using functions, default parameters are often involved. In Python, when using mutable objects as default parameters, unexpected results may occur.

Let’s look at an example:

def append_item(a = 1, b = []):
    b.append(a)
    print b
    
append_item(a=1)
append_item(a=3)
append_item(a=5)
Copy after login

The result is:

[1]
[1, 3]
[1, 3, 5]
Copy after login

As you can see from the result, when the append_item function is called twice later, the function parameters b is not initialized to [], but retains the value of the previous function call.

The reason why this result is obtained is that in Python, the default value of a function parameter is only initialized once when the function is defined.

Let’s look at an example below to prove this feature of Python:

class Test(object):  
    def init(self):  
        print("Init Test")  
          
def arg_init(a, b = Test()):  
    print(a)  
arg_init(1)  
arg_init(3)  
arg_init(5)
Copy after login

The result is:

Init Test
1
3
5
Copy after login

As you can see from the results of this example, the Test class has only been instantiated. Once, that is to say The default parameters have nothing to do with the number of function calls and are only initialized once when the function is defined.

Correct use of variable default parameters

For variable default parameters, we can use the following pattern to avoid the above unexpected results:

def append_item(a = 1, b = None):
    if b is None:
        b = []
    b.append(a)
    print b
    
append_item(a=1)
append_item(a=3)
append_item(a=5)
Copy after login

The result is:

[1]
[3]
[5]
Copy after login

Scope in Python

The scope resolution order of Python is Local, Enclosing, Global, Built-in, which means that the Python interpreter will parse according to this ordervariable.


Look at a simple example:

global_var = 0
def outer_func():
    outer_var = 1
    
    def inner_func():
        inner_var = 2
        
        print "global_var is :", global_var
        print "outer_var is :", outer_var
        print "inner_var is :", inner_var
        
    inner_func()
    
outer_func()
Copy after login

The result is:

global_var is : 0
outer_var is : 1
inner_var is : 2
Copy after login

In Python, there is one thing to note about scope. Yes, when assigning a value to a variable in a scope, Python will consider the variable to be a local variable of the current scope.


It is relatively easy to understand this point. For the following code, var_func assigns a value to the num variable, so num here is a local variable in the var_func scope.

num = 0
def var_func():
    num = 1
    print "num is :", num
    
var_func()
Copy after login

Question 1

However, when we use variables in the following way, problems will arise:

num = 0
def var_func():
    print "num is :", num
    num = 1
    
var_func()
Copy after login

The results are as follows:

UnboundLocalError: local variable 'num' referenced before assignment
Copy after login

The reason why this error occurs is because we assigned a value to the num variable in var_func, so the Python interpreter will think that num is a local variable in the var_func scope, but when the code is executed to print "num is:", the num statement At this time, num is still undefined.


Question 2

The above error is relatively obvious, and there is also a more subtle error form as follows:

li = [1, 2, 3]
def foo():
    li.append(4)
    print li
foo()
def bar():
    li +=[5]
    print li
bar()
Copy after login

code The result is:

[1, 2, 3, 4]
UnboundLocalError: local variable 'li' referenced before assignment
Copy after login

In the foo function, according to Python's scope parsing order, the global li variable is used in this function; but in the bar function, the li variable is assigned a value, so li will be Treated as a variable in bar scope.


For this problem of the bar function, you can use the global keyword.

li = [1, 2, 3]
def foo():
    li.append(4)
    print li
    
foo()
def bar():
    global li
    li +=[5]
    print li
    
bar()
Copy after login

ClassAttributeHide

In Python, there are class attributes and instance attributes. Class attributes belong to the class itself and are shared by all class instances.

Class attributes can be accessed and modified through the class name or through the class instance. However, when an instance defines an attribute with the same name as the class, the class attribute is hidden.


Look at the following example:

class Student(object):
    books = ["Python", "JavaScript", "CSS"]
    def init(self, name, age):
        self.name = name
        self.age = age
    pass
    
wilber = Student("Wilber", 27)
print "%s is %d years old" %(wilber.name, wilber.age)
print Student.books
print wilber.books
wilber.books = ["HTML", "AngularJS"]
print Student.books
print wilber.books
del wilber.books
print Student.books
print wilber.books
Copy after login

The result of the code is as follows. At first, the wilber instance can directly access the books attribute of the class, but when the instance wilber After defining the instance attribute named books, the books attribute of the wilber instance "hides" the books attribute of the class; when delete the books attribute of the wilber instance, wilber.books corresponds to the books of the class attribute.

Wilber is 27 years old
['Python', 'JavaScript', 'CSS']
['Python', 'JavaScript', 'CSS']
['Python', 'JavaScript', 'CSS']
['HTML', 'AngularJS']
['Python', 'JavaScript', 'CSS']
['Python', 'JavaScript', 'CSS']
Copy after login

When using inheritance in Python values, you should also pay attention to the hiding of class attributes. For a class, you can view all class attributes through the dict attribute of the class.


When accessing a class attribute through the class name, the dict attribute of the class will be searched first. If the class attribute is not found, the parent class will continue to be searched. However, if a subclass defines a class attribute with the same name as the parent class, the class attributes of the subclass will hide the class attributes of the parent class.


Look at an example:

class A(object):
    count = 1
    
class B(A):
    pass    
    
class C(A):
    pass        
    
print A.count, B.count, C.count      
B.count = 2
print A.count, B.count, C.count      
A.count = 3
print A.count, B.count, C.count     
print B.dict
print C.dict
Copy after login

The results are as follows. When class B defines the count attribute, the count attribute of the parent class will be hidden:

1 1 1
1 2 1
3 2 3
{'count': 2, 'module': 'main', 'doc': None}
{'module': 'main', 'doc': None}
Copy after login

tuple是“可变的”

在Python中,tuple是不可变对象,但是这里的不可变指的是tuple这个容器总的元素不可变(确切的说是元素的id),但是元素的值是可以改变的。

tpl = (1, 2, 3, [4, 5, 6])
print id(tpl)
print id(tpl[3])
tpl[3].extend([7, 8])
print tpl
print id(tpl)
print id(tpl[3])
Copy after login

代码结果如下,对于tpl对象,它的每个元素都是不可变的,但是tpl[3]是一个list对象。也就是说,对于这个tpl对象,id(tpl[3])是不可变的,但是tpl[3]确是可变的。

36764576
38639896
(1, 2, 3, [4, 5, 6, 7, 8])
36764576
38639896
Copy after login

Python的深浅拷贝

在对Python对象进行赋值的操作中,一定要注意对象的深浅拷贝,一不小心就可能踩坑了。


当使用下面的操作的时候,会产生浅拷贝的效果:


使用切片[:]操作

使用工厂函数(如list/dir/set

使用copy模块中的copy()函数

使用copy模块里面的浅拷贝函数copy():

import copy
will = ["Will", 28, ["Python", "C#", "JavaScript"]]
wilber = copy.copy(will)
print id(will)
print will
print [id(ele) for ele in will]
print id(wilber)
print wilber
print [id(ele) for ele in wilber]
will[0] = "Wilber"
will[2].append("CSS")
print id(will)
print will
print [id(ele) for ele in will]
print id(wilber)
print wilber
print [id(ele) for ele in wilber]
Copy after login

使用copy模块里面的深拷贝函数deepcopy():

import copy
will = ["Will", 28, ["Python", "C#", "JavaScript"]]
wilber = copy.deepcopy(will)
print id(will)
print will
print [id(ele) for ele in will]
print id(wilber)
print wilber
print [id(ele) for ele in wilber]
will[0] = "Wilber"
will[2].append("CSS")
print id(will)
print will
print [id(ele) for ele in will]
print id(wilber)
print wilber
print [id(ele) for ele in wilber]
Copy after login

模块循环依赖

在Python中使用import导入模块的时候,有的时候会产生模块循环依赖,例如下面的例子,module_x模块和module_y模块相互依赖,运行module_y.py的时候就会产生错误。

# module_x.py
import module_y
    
def inc_count():
    module_y.count += 1
    print module_y.count
    
    
# module_y.py
import module_x
count = 10
def run():
    module_x.inc_count()
    
run()
Copy after login


其实,在编码的过程中就应当避免循环依赖的情况,或者代码重构的过程中消除循环依赖。

当然,上面的问题也是可以解决的,常用的解决办法就是把引用关系搞清楚,让某个模块在真正需要的时候再导入(一般放到函数里面)。

对于上面的例子,就可以把module_x.py修改为如下形式,在函数内部导入module_y:

# module_x.py
def inc_count():
    import module_y
    module_y.count += 1
Copy after login


The above is the detailed content of Detailed explanation of Python traps and precautions commonly encountered in development. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
1 months ago By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Can the Python interpreter be deleted in Linux system? Can the Python interpreter be deleted in Linux system? Apr 02, 2025 am 07:00 AM

Regarding the problem of removing the Python interpreter that comes with Linux systems, many Linux distributions will preinstall the Python interpreter when installed, and it does not use the package manager...

How to solve the problem of Pylance type detection of custom decorators in Python? How to solve the problem of Pylance type detection of custom decorators in Python? Apr 02, 2025 am 06:42 AM

Pylance type detection problem solution when using custom decorator In Python programming, decorator is a powerful tool that can be used to add rows...

How to solve permission issues when using python --version command in Linux terminal? How to solve permission issues when using python --version command in Linux terminal? Apr 02, 2025 am 06:36 AM

Using python in Linux terminal...

Python 3.6 loading pickle file error ModuleNotFoundError: What should I do if I load pickle file '__builtin__'? Python 3.6 loading pickle file error ModuleNotFoundError: What should I do if I load pickle file '__builtin__'? Apr 02, 2025 am 06:27 AM

Loading pickle file in Python 3.6 environment error: ModuleNotFoundError:Nomodulenamed...

Do FastAPI and aiohttp share the same global event loop? Do FastAPI and aiohttp share the same global event loop? Apr 02, 2025 am 06:12 AM

Compatibility issues between Python asynchronous libraries In Python, asynchronous programming has become the process of high concurrency and I/O...

What should I do if the '__builtin__' module is not found when loading the Pickle file in Python 3.6? What should I do if the '__builtin__' module is not found when loading the Pickle file in Python 3.6? Apr 02, 2025 am 07:12 AM

Error loading Pickle file in Python 3.6 environment: ModuleNotFoundError:Nomodulenamed...

How to ensure that the child process also terminates after killing the parent process via signal in Python? How to ensure that the child process also terminates after killing the parent process via signal in Python? Apr 02, 2025 am 06:39 AM

The problem and solution of the child process continuing to run when using signals to kill the parent process. In Python programming, after killing the parent process through signals, the child process still...

See all articles