Python Language Specification Pychecker? Run Pychecker definition for your code: Pychecker is a tool for finding bugs in Python source code. For less dynamic C and C + + languages, these bugs are usually captured by the compiler. Pychecker and lint are similar. Some warnings may be incorrect due to the dynamic nature of Python. But false alarms should be few. Pros: You can capture errors that are easily overlooked, such as typing errors, using unassigned variables, and so on. Cons: Pychecker is imperfect. To take advantage of it, we sometimes need: a) around it to write code B) to suppress its alarm c) to improve it, or d) to ignore it. Conclusion: Be sure to run Pychecker on your code. For more information on how to run Pychecker, refer to pychecker home page you can To set a module-level variable called __pychecker__ to suppress the appropriate alarm. For example: __pychecker__ = ' no-callinit no-classattr ' The advantage of this inhibition is that we can easily find inhibition and review them. You can use Pychecker--help to get a list of pychecker alarms. To suppress "Parameter not used" alarm, you can use "_" as the parameter identifier, or add "unused_" in front of the parameter name. When a parameter name cannot be changed, you can eliminate the alarm by "mentioning" them at the beginning of the function. Example: Def foo (A, unused_b, Unused_c, D=none, E=none):(D, e) = (d, e) # Let pychecker not alarm return a ideally, we'll expand pychecker later to make sure you don't really Use these parameters. 16 Import? Import definitions are used only for packages and modules: The reuse mechanism for sharing code between modules. Pros: Namespace management conventions are simple. The source of each identifier is indicated in a consistent manner. X.obj indicates that the OBJ object is defined in module X. Disadvantage: The module name may still conflict. Some module names are too long and inconvenient. Conclusion: Import the packages and modules using import x. Use form x import y, where x is the package prefix and y is the module name without a prefix. Use form x to import y as Z, if two modules to be imported are called Z or Y is too long. For example, the module Sound.effects.echo can be imported in the following ways:From sound.effects import Echo...echo. Echofilter (input, output, delay=0.7, atten=4) do not use relative names when importing. The full package name is used even if the module is in the same package. This can help you avoid accidentally importing a package two times. The bag? Use the full pathname of the module to import each module's advantages: Avoid module name collisions. Finding a package is easier. Cons: Deploying code becomes difficult because you have to replicate the package hierarchy. Conclusion: All new code should be imported with the full package name. Should be imported as follows: # Reference in code with complete Name.import sound.effects.echo17# Reference in code with just module name (preferred). From sound.effects import echo exception? Exceptions are allowed, but must be carefully defined: exceptions are a way to handle errors or other exception conditions by jumping out of the normal control flow of a block of code. Advantage: The control flow of normal operation code is not mixed with error handling code. When a condition occurs, it also allows the flow of control to skip multiple frames. For example, step out of n nested functions without having to continue executing the wrong code. Cons: can lead to confusing control flow. It is easy to miss the error condition when calling the library. Conclusion: The anomaly must obey certain conditions: 1. Trigger an exception like this: Raise MyException ("Error message") or raisemyexception. Do not use the form of two parameters (raise MyException, "errormessage") or obsolete string exceptions (raise "Error Message"). 2. The module or package should define its own domain-specific exception base class, which should inherit from the built-in exception class. The exception base class for the module should be called "Error". 3. Class Error (Exception): 4. Pass5. Never use the except: statement to catch all exceptions, or capture Exception or standarderror unless you intend to re-trigger the exception, or you are already on the outermost layer of the current thread (remember to print an error message). In terms of exceptions, Python is very tolerant, except: It really captures any errors including Python syntax errors. Using except: It's easy to hide real buG.6. Minimize the amount of code in the Try/except block. The larger the size of the try block, the more likely an exception is expected to be triggered. In this case, the try/except block will hide the real error. 7. Use the finally clause to execute code that should be executed regardless of whether there is an exception in the try block. This is often useful for cleaning up resources, such as closing files. Global variables? Avoid global variable definitions: variables defined at the module level. Pros: 18 occasionally useful. Disadvantage: The module behavior can be changed when importing, because module-level variables are assigned values when importing modules. Conclusion: Avoid using global variables instead of class variables. But there are some exceptions: 1. Default options for Scripts. 2. Module-level constants. For example: PI = 3.14159. Constants should be all uppercase and underlined. 3. Sometimes it is useful to cache a value with a global variable or to return a value as a function. 4. If required, global variables should be available only within the module and accessed through a public function at the module level. nested/local/inner class or function? Encourage the use of nested/local/inner classes or function definitions: classes can be defined in methods, functions, or classes. A function can be defined in a method or function. Variables defined in the enclosing interval are read-only for nested functions. Pros: Allows you to define tool classes and functions that are only valid scopes. Disadvantage: Instances of nested classes or local classes cannot be serialized (pickled). Conclusion: Recommended use. list comprehensions? Definitions can be used in simple cases: List derivation (lists comprehensions) and builder Expressions (generator expression) provide a concise and efficient way to create lists and iterators without the help of a map (), filter (), or lambda. Pros: Simple list derivation can be clearer and simpler than other list creation methods. Builder expressions can be very efficient because they avoid creating an entire list. Cons: Complex list derivation or generator expressions can be difficult to read. Conclusion: It is suitable for simple cases. Each section should be placed on a single line: A map expression, a for statement, and a filter expression. Suppresses multiple for statements or filter expressions. In complex cases, loops are used. 19no:result = [(x, y) for x in range (Sun) for y In range (5) if x * y >10]return (X, Y, Z) For x in xrange (5) For y in xrange (5) if x != yfor z in xrange (5) if y != z) Yes:result = []for x in range ( Ten): For y in range (5): If x * y > 10:result.append ((x, y)) for x in xrange (5): For y in xrange (5): If x != y:for z in xrange (5):if y != z:yield (x, y, z) return (x, complicated_ Transform (x)) for x in long_generator_function (parameter) if x is not none) Squares = [x * x for x in range (]eat) (jelly_bean for jelly _bean in jelly_beansif jelly_bean.color == ' black ' default iterators and operators? If the type supports it, the default iterator and operator are used. such as lists, dictionaries, and files. Definitions: container types, like dictionaries and lists, define the advantages of default iterators and relational test operators (in and not): The default operators and iterators are simple and efficient, they express operations directly, and there are no additional method calls. Functions that use the default operators are generic. It can be used to support any type of operation. Cons: 20You can't distinguish the type of object by reading the method name (for example, Has_key () means a dictionary). But it's also a good thing. Conclusion: If type is supported, use default iterators and operators, such as lists, dictionaries, and files. The built-in type also defines the iterator method. These methods are preferred, not those that return a list. You cannot modify a container unless you are traversing it. yes: for key in adict: ...if key not in adict: ...if obj in alist: ...for line in afile: ...for k, v in Dict.iteritems ():  , ..... No: for key in adict.keys (): ...if not adict.has_key (key): ...for line in afile.readlines ():  , ..... Generator? Use the builder on demand. Definition: The so-called generator function, that is, whenever it executes a generation (yield) statement, it returns an iterator that generates a value. After the value is generated, the run state of the generator function is suspended until the next build. Pros: Simplify the code because the local variables and the state of the control flow are saved each time the call is taken. The generator uses less memory than a function that creates a series of values at a time. Cons: No. Conclusion: encourage use. Note Use "yields:" instead of "Returns:" in the document string of the generator function. Lambda function? Applies to single-line function definitions: In contrast to a statement, Lambda defines an anonymous function in an expression. Often used to define callback functions or operators for higher-order functions such as map () and filter (). Advantages: Convenient. Cons: 21 more difficult to read and debug than local functions. No function name means that the stack trace is more difficult to understand. Because lambda functions typically contain only one expression, their ability to express is limited. Conclusion: It is suitable for single-line function. If the code is more than 60-80 characters, it is best to define a regular (nested) function. default parameter values? Suitable for most situations. Definition: You can specify the value of a variable at the end of the function argument list, for example, Def foo (A, b = 0):. If you call Foo with only one argument, B is set to 0. If you have two parameters, the value of B equals the second parameter. Pros: You often come across functions that use a lot of default values, but occasionally (more rarely) you want to override these defaults. Default parameter values provide an easy way to do this, and you don't need to define a large number of functions for these rare exceptions. Also, Python does not support overloaded methods and functions, and default parameters are an easy way to "mimic" overloaded behavior. Disadvantage: The default parameter is evaluated only once when the module is loaded. This can cause problems if the parameter is a mutable type such as a list or dictionary. If a function modifies an object, such as appending an item to a list, the default value is modified. Conclusion: encourage use, but there are the following considerations: Do not use mutable objects as default values in a function or method definition. Yes: def foo (A, b=none): If b is none:b = []no: def foo (A, b=[]): ... The caller code must use a value with a name for the parameter with the default value. This increases the readability of the code and avoids and detects that the interface is corrupted when parameters are added. Def foo (a, b=1): ... Yes: foo (1) foo (1, b=2), No: foo (1, 2) 22 attributes (properties)? When accessing and setting data members, you will typically use simple, lightweight access and setup functions. It is recommended to replace them with attributes. Definition: A way to wrap a method call. It is a standard way to get and set properties (attribute) when the amount of computation is small. Advantages: readability is improved by eliminating explicit get and set method calls when accessing simple attributes (attribute). Allow lazy calculation. Maintain the interface of the class in a pythonic way. In terms of performance, when direct access to variables is justified, adding access methods is trivial and meaningless. The use of attributes (properties) can bypass this problem. In the future, the access method can be added without destroying the interface. Cons: properties are specified after the get and set method declarations, which requires the consumer to note in the following code: Set and get are used for properties ( In addition to the read-only attribute created with the @property adorner). Must inherit from Object class. It is possible to hide side effects such as operator overloading. Inheritance can be confusing. Conclusion: You are usually used to accessing or setting data using Access or setting methods, which are simple and lightweight. However, we recommend that you use attributes in the new code. Read-only properties should be created with the @property adorner. If a subclass does not have an override property, the inheritance of the property may not look obvious. Therefore, the user must ensure that the access method is called indirectly to ensure that overloaded methods in the subclass are called by the property (using the template method design pattern). Yes: import mathclass square (object): "" "a square with two properties: A writable area and aread-only perimeter. To use:>>> sq = square (3) >>> sq.area9>>> sq.perimeter12>>> sq.area = 16>>> sq.side4>>> Sq.perimeter16 "" "23def __init__ (self, side): Self.side = sidedef __get_area (self):" "" calculates the ' area ' property. "" " Return self.side ** 2def ___get_area (self): "" "indirect accessor for ' area ' property. "" " Return self.__get_area () Def __set_area (Self, area): "" "sets the ' area ' property." " Self.side = math.sqrt (area) def ___set_area (Self, area): "" "indirect setter for ' area ' property." "" Self._setarea (area) area = property (___get_area, ___set_area,doc= "" "gets or sets The area of the square. "" ") @propertydef perimeter (self): return self.side * 4 (Translator Note: Frankly speaking, I think this example code is very inappropriate, is it necessary to have such an egg ache?) True/false's evaluation? Use implicit false definitions whenever possible: Python evaluates some values to False in Boolean contexts. By simple intuition, all "null" values are considered false. So 0, None, [], {}, "" are all considered false. Pros: Conditional statements that use Python Boolean values are easier to read and less prone to mistakes. In most cases, it's also faster. Cons: It may seem a bit odd for C + + developers. Conclusion: 24 use implicit false if possible, for example: use if foo: instead of if foo! = []:. But there are a few things to keep in mind: 1. Never use = = or! = To compare a single piece, such as none. Use is or is not.2. Note: When you write down if x: When you actually represent the IF x is not None. For example, if you want to test whether a variable or parameter with a default value of None is set to a different value. This value may be false!3 under Boolean semantics. Never use = = to compare a Boolean amount to false. Use if not x: instead. If you need to differentiate between false and none, you should use a statement like if not X and X are not None: such statements. 4. For sequences (strings, lists, tuples), be aware that the empty sequence is false. So if not seq: or if seq: than if Len (seq): Or if not Len (seq): To be better. 5. When working with integers, using implicit false mayNot worth the candle (that is, the none is treated as a "%"). You can compare a value with 0 that is known to be an integral type (and not a return result of Len ()). yes: if not users:print ' No users ' If foo == 0:self.handle_zero () if i % 10 == 0:self.handle_multiple_of_ten () No: if len (users) == 0: print ' No users ' If foo is not none and not foo:self.handle_zero () If not i % 10:self.handle_multiple_of_ten () 6. Note that ' 0 ' (string) is treated as true. Obsolete language features? Use the string method instead of the string module whenever possible. Use the function call syntax instead of apply (). Using the list derivation, the For loop replaces filter (), map (), and reduce (). Definition: The current version of Python provides alternatives that are generally preferred. Conclusion: We do not use Python versions that do not support these features, so there is no reason to do so without a new approach. 25No: words = string.split (foo, ': ') map (Lambda x: x[1], filter (lambda x: x[2] == 5, my_list) apply (Fn, args, kwargs) yes: words = Foo.split (': ') [X[1] for x in my_list if x[2] == 5]fn (*args, ** Kwargs) static scoping (Lexical scoping)? Recommended usage definitions: nested python Functions can refer to variables defined in the outer function, but they cannot be assigned values. The parsing of variable bindings is using static scoping, which is static-based program text. Any assignment to a name in a block will cause Python to treat all references to that name as local variables, even before the assignment. If the global declaration is encountered, the name is considered a global variable. An example of using this feature: Def get_adder (SUMMAND1): "" "Returns a function that adds numbers to a given number. "" " Def adder (Summand2): Return summand1 + summand2return adder (Translator Note: This is a bit of a weird example, you should use this function: Sum =get_adder (SUMMAND1) (SUMMAND2)) Advantages: It often leads to clearer, more elegant code. In particular, the experienced Lisp and scheme (and Haskell, ML, etc.) programmers are pleased. Cons: can lead to confusing bugs. For example, the following example: I = 4def foo (x): 26def bar ():p rint i,# ...# a bunch of code here# ...for i in x: # ah, i *is* local to foo, so this is what bar seesprint i,bar () so Foo ([1, 2, 3]) will print 1 2 3 3, not 1 2 3 4. (Translator Note: X is a list in which the For loop actually assigns the values in X to I.) so that the assignment of I is implicitly occurring, and I in the whole Foo function body is treated as a local variable, including the one in Bar (). This is quite different from static languages like C + +. Conclusion: Encourage the use of. Function and Method adorners? If the benefits are obvious, use the adorner definition wisely and cautiously: the adorner for the function and method (that is, the @ tag). The most common adorners are @classmethod and @staticmethod, which are used to convert regular functions into class methods or static methods. However, the adorner syntax also allows the user to customize the adorner. In particular, for a function my_decorator, the following two-segment code is equivalent: Class c (object): @my_decoratordef method (self):# method Body ...class c (object):d Ef method (self): # method body ...method = my_ Decorator (method) Pros: Gracefully specify some transformations on the function. The conversion may reduce some duplicate code, keep the existing function unchanged (enforce invariants), etc. disadvantage: adorners can perform any action on the function's arguments or return values, which can lead to amazing hidden behavior. Also, the adorner executes at import time. It is more impossible to recover from the failure of the adorner code. Conclusion: 27 If the benefits are obvious, use the adorner wisely and cautiously. Adorners should follow the same import and naming rules as functions. The python document of the adorner should clearly state that the function is an adorner. Write unit tests for adorners. Avoid the adorner's own reliance on the outside world (that is, do not rely on files, sockets, database connections, etc.), as adorners may not be available when they are run (such as when using Pychecker or other tools when importing). It should be ensured that an adorner called with valid parameters is successful in all cases. Adorners are a special form of "top-level code." Refer to the following topic about main. threads? Do not rely on the atomicity of the built-in type. Although Python's built-in types such as dictionaries appear to have atomic operations, in some cases they are still not atomic (that is, if __hash__ or __eq__ are implemented as Python methods) and their atomicity is unreliable. You can't expect atomic variables to be assigned (because this in turn depends on the dictionary). The queue data type of the queue module is preferred as a data communication method between threads. In addition, the threading module and its lock primitives are used. Understand the appropriate use of conditional variables so that you can use threading. Condition to replace low-levelAnother lock. Too much power? Avoid using these attribute definitions: Python is an exceptionally flexible language that provides you with a lot of fancy features such as the original Class (metaclasses), bytecode access, arbitrary compilation (On-the-fly compilation), dynamic inheritance, Object parent class redefinition ( Object reparenting), import hacker (import hacks), reflection, in-system modification (modification of systems internals), and so on. Pros: Powerful language features to make your code more compact. Cons: Use these very " Cool "features are tempting, but not absolutely necessary. Code that uses artifice will be more difficult to read and debug. It may be OK at first (for the original author), but when you look at the code, they may be more difficult to understand than the slightly longer but straightforward code. Conclusion:
Avoid these features in your code.
Python Language Specification