Python traps and notes in development

Source: Internet
Author: User
Python traps and notes frequently encountered during development recently encountered some pitfalls when using Python, such as using datetime. datetime. now () is the variable object used as the default parameter of the function, and the module cycle dependency.

Record it here to facilitate future query and supplement.

Avoid using mutable objects as default parameters

When using a function, default parameters are often involved. In Python, when a mutable object is used as the default parameter, unexpected results may be generated.

The following is 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)

Result:

[1][1, 3][1, 3, 5]

The result shows that when the append_item function is called for the next two times, function B is not initialized to [], but the value of the previous function call is maintained.

In Python, the default value of a function parameter is initialized only once when the function is defined.

The following example demonstrates 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)

Result:

Init Test135

From the results of this example, we can see that the Test class is only instantiated once, that is, the default parameter has nothing to do with the number of function calls and is initialized only once when the function is defined.

Correct use of variable default parameters

For variable default parameters, we can use the following mode 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)

Result:

[1][3][5]

Scope in Python

The scope resolution sequence of Python is Local, Enclosing, Global, and Built-in. that is to say, the Python interpreter parses the variables in this order.


Let's look at a simple example:

global_var = 0def 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()


Result:

global_var is : 0outer_var is : 1inner_var is : 2

In Python, when assigning values to a variable in a scope, Python considers the variable as a local variable in the current scope.


This is also easy to understand. in the following code, var_func assigns a value to the num variable, so the num here is the local variable in the var_func scope.

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

Question 1

However, when we use a variable in the following ways, the problem arises:

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

The result is as follows:

UnboundLocalError: local variable 'num' referenced before assignment

This error occurs because we assigned a value to the num variable in var_func. Therefore, the Python interpreter considers num as a local variable in the var_func scope, however, when the code runs the print "num is:" or num statement, num is still undefined.


Question 2

The above error is still obvious, and there is a more concealed form of error as follows:

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

The result of the code is:

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

In the foo function, the global li variable is used in the function according to the scope parsing sequence of Python. However, in the bar function, the li variable is assigned a value, therefore, li will be treated as a variable in the bar scope.


For 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()

Hide class attributes

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

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


Let's look at the example below:

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.booksprint wilber.bookswilber.books = ["HTML", "AngularJS"]print Student.booksprint wilber.booksdel wilber.booksprint Student.booksprint wilber.books

The result of the code is as follows. at first, the wilber instance can directly invoke the books attribute of the class, but after the wilber instance defines the attributes of the instance named books, the books attribute of the wilber instance "hides" the books attribute of the class. after the books attribute of the wilber instance is deleted, the wilber. books corresponds to the books attribute of the class.

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

When using inheritance for Python values, you must also note the hiding of class attributes. For a class, you can view all the class attributes through the _ dict _ attribute of the class.


When you access a class attribute through the class name, the _ dict _ attribute of the class is first searched. if the class attribute is not found, the parent class is searched. However, if the subclass defines a class attribute with the same name as the parent class, the class attribute of the subclass hides the class attribute of the parent class.


Let's 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 = 2print A.count, B.count, C.count      A.count = 3print A.count, B.count, C.count     print B.__dict__print C.__dict__

The result is as follows. when Class B defines the count class attribute, the count attribute of the parent class is hidden:

1 1 11 2 13 2 3{'count': 2, '__module__': '__main__', '__doc__': None}{'__module__': '__main__', '__doc__': None}

Tuple is "variable"

In Python, tuple is an immutable object, but here immutable means that the total elements of the tuple container are immutable (specifically, the element id ), however, the value of an element can be changed.

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

The code result is as follows. for a tpl object, each element of the object is immutable, but tpl [3] is a list object. That is to say, for this tpl object, id (tpl [3]) is immutable, but tpl [3] is indeed mutable.

3676457638639896(1, 2, 3, [4, 5, 6, 7, 8])3676457638639896

Python deep copy

When assigning values to a Python object, you must pay attention to the depth copy of the object. if you are not careful about the object, you may step on it.


When you use the following operations, the shallow copy effect will be generated:


Use Slice [:]

Use factory functions (such as list/dir/set)

Use the copy () function in the copy module

Use the copy function copy () in the copy module ():

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

Use the deep copy function deepcopy () in the copy module ():

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

Module cycle dependency

When using the import module in Python, module circular dependency is sometimes generated. for example, in the following example, the module_x module and module_y module depend on each other, and errors may occur when running module_y.py.

# module_x.pyimport module_y     def inc_count():    module_y.count += 1    print module_y.count          # module_y.pyimport module_xcount = 10def run():    module_x.inc_count()     run()


In fact, circular dependencies should be avoided in the coding process, or circular dependencies should be eliminated during code reconstruction.


Of course, the above problem can also be solved. The common solution is to clarify the reference relationship so that a module can be imported (usually put in a function) when it is actually needed ).


For the above example, you can modify module_x.py to the following form and import module_y to the function:

# module_x.pydef inc_count():    import module_y    module_y.count += 1

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.