Today, I’ve summarized some common mistakes that will make learning Python easy.

1. Incorrect indentation, symbols and Spaces

When writing code, people use indentation, alignment, and whitespace to improve the readability of the code.


But in Python, many features rely on indentation.


For example, when you create a new class, everything in that class is indented under the declaration, as is the case with decisions, loops, and other structural statements.


If you find problems with code execution, check to see if you’re using the correct indentation.


Take a look at the following example. Make sure to use correct and appropriate colons and indentation when using IF statements, as they can lead to syntax and indentation errors.


val = 500if val > 100print("value is grater then 100")File "<ipython-input-1-a271e37c300f>", line 2   if val > 100               ^SyntaxError: invalid syntaxCopy the code


In the code above, there are two errors: missing; The next line is not indented correctly, and the code is executed incorrectly.


val = 500if val > 100:print("value is grater then 100")value is grater then 100Copy the code


When you correct two problems in the above code, you will find that the whole code works fine.


2. Incorrect use of class variables

class A(object):x = 1class B(A):passclass C(A):passprint( A.x, B.x, C.x)1 1 1Copy the code


Here the output value is 1, and then we try to change the values of A.x and B.x to see what happens.


B.x = 2print (A.x, B.x, C.x)A.x = 3print (A.x, B.x, C.x)1 2 13 2 3Copy the code


We only changed A.X. Why did C.x change?


Here’s a quick look at Python namespaces.

In Python, namespaces are a combination of name-to-object mappings. Names in different namespaces are not associated. The implementation of such mappings is somewhat similar to dictionaries in Python.

When you access an object’s properties by name, you first look in the object’s namespace. If the property is found, the value of the property is returned; If not, it looks in the class’s namespace, returns the value of the attribute if found, and throws an exception if not found.


In Python, class variables are handled internally as dictionaries and follow a method commonly called method resolution order (MRO).


MRO: Method Resolution Order (MRO) : Method Resolution Order (MRO) : Method Resolution Order (MRO) : Method Resolution Order (MRO), Python supports multiple inheritance.


So in the code above, since X cannot find the property C in the object’s namespace, it will look for it in the class. In other words, C has no x property of its own, independent of A. Thus, a reference to C.x actually refers to A.x.


3. Misunderstanding Python scope rules

It’s easy to make mistakes if you don’t understand Python’s scope rules, because Python uses a unique scope rule to determine the scope of variables.

Python range resolution is based on LEGB rules. Here is an overview of python range rules:

·L – stands for Local. It contains the (identifier/variable) name specified within the function (using def or lambda), instead of being declared using the global keyword.

·E – stands for Enclosing function locals. It contains names from the local scope of any/all enclosing functions (for example, using def or lambda).

·G – for global entity. It includes names that run at the top level of the module file or are defined using the global keyword.

·B – Refers to built-in plug-ins. It spans names that are pre-specified as built-in names, such as print, enter, open, and so on.

The LEGB rule specifies the following order for namespaces to search for names:

Local – > Enclosed – > Global – > Built-in

Consider the following example:


x = 10def foo():  x += 1print(x)foo()UnboundLocalError Traceback (most recent call last):<ipython-input-26-234e54482865> in <module><ipython-input-26-234e54482865> in foo()UnboundLocalError: local variable x referenced before assignmentCopy the code


The above error occurs because when assigning a value to a variable in scope, Python automatically treats that variable as a local variable in that scope and hides any similarly named variables in the outer scope.

As a result, many people are confused when the code prompts an error and says you need to add an assignment statement to a function.


Consider an example encountered when using lists:


lst = [1, 2, 3]def foo1(): lst.append(5)  foo1()lst[1, 2, 3, 5]Copy the code


lst = [1, 2, 3]def foo2():  lst += [5]      foo2()UnboundLocalError  Traceback (most recent call last):<ipython-input-30-579469eed71a> in <module>  <ipython-input-30-579469eed71a> in foo2()UnboundLocalError: local variable lst referenced before assignmentCopy the code


Why is foo2 wrong but foo1 is fine?


In this example, foo1 () does an assignment to LST, while foo2 () LST += [5] is simply short for LST = LST + [5]. We want to assign a value to LST, but the assigned value LST is based on LST itself, but it is not defined yet.


4. Python closure variable bindings

The python closure variable issue is also a point of confusion for beginners. Take a look at the following example:


def create_multipliers():  return [lambda x : i * x for i in range(5)]for multiplier in create_multipliers():   print (multiplier(2))88888Copy the code


Why is it 88888, not 02468, as I thought?


This is due to Python’s late binding mechanism, where the value of an internal function in a closure is queried only when it is called.


So when the lambda function returned by create_multipliers is called, the value of variable I is queried in a nearby scope. After create_multipliers generates the return array, the integer I is 4 and does not change, so each anonymous function in the return array is actually: Lambda x: 4 * x. ,


The solution is to keep the temporary values in the scope of the anonymous function as well, and query the value of the variable when the anonymous function is declared.


With that in mind, let’s change the code, surprise!


def create_multipliers():    return [lambda x, i=i : i * x for i in range(5)]for multiplier in create_multipliers():    print (multiplier(2))02468Copy the code


5. Name conflicts with Python standard library module

Python has a large library of modules right out of the box. However, problems can arise if you encounter a name conflict between a module’s name and that of a module with the same name in the standard library that comes with Python.


For example, import another library, which will try to import the Python standard library version of the module, but because you have a module with the same name, another package will import your version instead of the Python standard library by mistake.


Therefore, care should be taken to avoid using the same names as in Python standard library modules, and it is easier to change module names in packages than to submit Python Enhancement Proposal (PEP) to request name changes.


== == == == == == =

Python has many operators, such as is, =, ==. Many beginners will misunderstand the meaning and usage of these three operators, resulting in code errors.


Comparison between objects is used in Python. You can use == or is, but the comparison between objects is not the same.


· IS compares whether the ID values of two objects are equal, whether they point to the same memory address, == Compares whether the contents of two objects are equal, whether the values are equal;


a = ["Python"]b = ab is aTrueCopy the code


id(a)2222222id(b)2222222b == aTrueCopy the code


As you can see in the above example, b and A have the same memory address. They refer to the same block of memory, so is and == are both True because direct assignments are references to assignments. If b and A point to different memory after creating a new object, then b is a is False and b==a is True.


· Small integer objects [-5,256] are placed in the cache for reuse within the scope of the global interpreter, for example:


a = 1b = 1a is bTruea == bTrueCopy the code


a = 257b = 257a is bFalseCopy the code


Python caches only small integer objects (range [-5, 256]), not all integer objects. Note that this is only executed on the command line and is not the same when executed on Pycharm or saved as a file because the interpreter has been partially optimized.


= and == have different meanings:


= means to assign, to assign some value to some variable, say a=3, to assign the value 3 to A.

Returns True or False, such as 1==1. They are equal, so return true. 1==2, they are not equal, so return false.

Example:


A = [1,2]b = [1,2]c = aa is bFalsea is ctruea == btrueCopy the code


7. __init__ abuse

The __init__ method is used as a constructor in Python and is automatically called when Python allocates memory to a new class object.

First, __init__ is not equivalent to a constructor in C#; the instance is already constructed at the time it is executed.


class A(object):  def __init__(self,name):      self.name=name  def getName(self):      return A +self.nameCopy the code

Execution code:


a=A( hello )Copy the code


It can be understood as:


a=object.__new__(A)A.__init__(a, hello )Copy the code


That is, __init__ initializes an instantiated object.


Second, subclasses do not override __init__. When instantiating a subclass, __init__ defined in the superclass is automatically called.


class B(A):   def getName(self):       return B +self.nameif __name__== __main__ :   b=B( hello )   print (b.getName())Copy the code


However, if __init__ is overridden, instantiating a subclass does not implicitly invoke __init__ defined in the superclass.


class C(A):   def __init__(self):       pass   def getName(self):       return C   +self.nameif __name__== __main__ :   c=C()   print (c.getName())Copy the code

An AttributeError: C object has noattribute name error is reported, so if __init__ is overridden, it is best to explicitly call __init__ of the superclass in order to use or extend the behavior in the superclass.



class C(A):   def __init__(self,name):       super(C,self).__init__(name)   def getName(self):       return C   +self.nameif __name__== __main__ :   c=C( hello )     print (c.getName())Copy the code


Source/DataCastle DataCastle