PEP 8 Python Coding Standards PDF
Document Details
Uploaded by OrderlyChalcedony6448
Tags
Summary
This document provides guidelines and best practices for writing readable and consistent Python code. It focuses on improving code readability and consistency using PEP 8 standards. The document covers naming conventions and code layout.
Full Transcript
# PEP 8 Coding Standards ## Module 1 ## Learning Outcomes By the end of this module, students will be able to: 1. Write Python code that conforms to PEP 8. 2. Understand the reason behind the guidelines laid out in PEP 8. 3. Set up your development environment so that you can start writing. 4....
# PEP 8 Coding Standards ## Module 1 ## Learning Outcomes By the end of this module, students will be able to: 1. Write Python code that conforms to PEP 8. 2. Understand the reason behind the guidelines laid out in PEP 8. 3. Set up your development environment so that you can start writing. 4. Understand PEP 8 compliant Python code. ## Introduction PEP stands for Python Enhancement Proposal, and is a document that provides guidelines and best practices on how to write Python codes. It was written in 2001 by Guido van Rossum, Barry Warsaw and Nick Coghlan. The primary focus of PEP 8 is to improve readability and consistency of Python codes. This document gives coding conventions for the Python code comprising of the standard library in the main Python distribution. ## Why PEP 8? PEP 8 standards improve the readability of Python codes. You might have some questions in your mind. * Why is readability so important? * Why is writing a readable code one of the important principles in Python programming? Inventor of Python, Guido van Rossum, said, “Code is read much more often than it is written." You may spend a few minutes, or a day or a couple of days, in writing a piece of code to implement a feature in the software you are creating. Once you have written it, you are never going to rewrite it. But you'll definitely have to read it again for debugging or some other purpose. That piece of code might remain part of a project you're working on. Every time you revisit that code, you'll have to know what that code does, and why you wrote it. So, readability is very important. For a beginner, it is difficult to remember what a piece of code does, a few days, or weeks after he/she wrote it. Writing a clear, readable code shows professionalism. By following PEP 8, one can make sure that: * Variables are named properly. * Enough whitespace is added to follow logical steps in the code. * Comments are added to the code properly. Programmers may need to collaborate with others. Writing a readable code is crucial in this situation. Other people will have to read and understand your code. Following PEP standards will make it easier for others to read your code. ## Naming Conventions >"Explicit is better than implicit." >-The Zen of Python When you write a program, you have to name: variables, functions, classes, packages, and so on. Choosing meaningful names will save time and energy later. One should be able to figure out what a certain variable, function, or class represents, from its name. Avoid using inappropriate names that might result in errors that are difficult to debug. Note: Never use i, O, or I in single letter names as these can be mistaken for 1 and 0. **Ex:** O = 123 ### Naming Style: | Type | Naming Convention | Examples | |---|---|---| | Function/Method | Use a lowercase word or words. Separate words by underscores to improve readability. | find_sum(), validate() | | Variable | Use a lowercase single letter, word, or words. Separate words with underscores to improve readability. | x, length, student_age | | Class | Use camel case, i.e., start each word with a capital letter. Words are separated by making the first letter capital. | Student, UserAuthentication | | Constant | Use an uppercase single letter, word, or words. Separate words with underscores to improve readability. | PI, USER_TYPE, THETA | | Module | Use a short, lowercase word or words. Separate words with underscores to improve readability. | module1.py, student_module.py, module.py | | Package | Use a short, lowercase word or words. Do not separate words with underscores. | Userutitlites, student | Even if you follow the naming styles, choosing names of variables, functions, classes, etc., also should be done carefully in order to write readable codes. The best way to name objects in Python is to use descriptive names to make it clear what the object represents. When naming variables, one may be tempted to choose simple, single-letter lowercase names, like x, y etc., But, unless you're using x as the argument of a mathematical function, it is not clear what x represents. When storing a person's name as a string, use variable names like first_name, last_name. Otherwise it will be confusing to collaborators. **Ex**: Function for finding the factorial can be find_factorial() instead of naming simply f(). ## Code Layout >"Beautiful is better than ugly." >-The Zen of Python * Vertical white spaces will improve readability of the code to a large extent. A code that's bunched up together can be overwhelming and hard to read. Similarly, too many blank lines in your code make it look very sparse, and the reader might need to scroll more than necessary. ### Three Key Guidelines on How to Use Vertical Whitespace Are: 1. **Use two line breaks before top-level functions and classes.** **Ex:** ```python class Employee: pass class Student: pass ``` 2. **Use single line break for method definitions inside classes.** **Ex:** ```python class Employee: def calculate_salary(): pass def get_details(): pass ``` 3. **Use single line breaks inside a function to separate logical steps.** Sometimes, a function has to complete several steps inside it. Using white spaces between logical steps will help the reader understand the logic inside the function easily. **Ex:** ```python def calculate_variance(num_list): sum_nos = 0 for number in num_list: sum_nos = sum_nos + number mean = sum_nos / len(number_list) sum_squares = 0 for number in num_list: sum_squares = sum_squares + number**2 mean_squares = sum_squares / len(number_list) return mean_squares - mean**2 ``` ## Maximum Line Length and Line Breaking PEP 8 suggests that lines should be limited to 79 characters, because this allows to have multiple files open next to one another, without line wrapping. But, keeping 79 characters or less in a statement is not always possible. PEP 8 provides ways to allow statements to span over multiple lines. 1. **Python will assume line continuation if the code is contained within parentheses, brackets or braces**: **Ex:** ```python def test_function(param_1, param_2, param_3, param_4): pass ``` 2. **If there are no parentheses, brackets or braces, then use backslash to break the line.** **Ex:** ```python from models import Login, User, \ Product, Category ``` 3. **Line breaks around mathematical operators(+, -, *, /) should occur before the operand**. **Ex:** ```python Total_salary = basic_salary + allowances - tax ``` The reader can see which variable is being added or subtracted, as the operator is right before the operand. ## Indentation >"There should be one-and preferably only one-obvious way to do it." >-The Zen of Python Indentation, or leading whitespace, is extremely important in Python as the indentation level of lines of code determines code blocks. The key indentation rules in PEP 8 are the following: * **Use 4 consecutive spaces to indicate indentation.** * **Prefer spaces over tabs.** Mixing of tabs and spaces is not recommended. Python 3 does not support this. Python 3 will show error if you mix tabs and spaces. **TabError**: Inconsistent use of tabs and spaces in indentation. ### Indentation Following Line Breaks There are two ways of doing this as per PEP 8. 1. **Align the indented block with the opening delimiter.** 2. **Use a hanging indent.** **Align the indented block with the opening delimiter.** **Example:** ```python def test_function(param_1, param_2, param_3, param_4): pass ``` Sometimes, only 4 spaces are required to align with the opening delimiter. This will often occur in "if" statements that span multiple lines as the "if", space, and opening bracket make up 4 characters. In this case, it can be difficult to determine where the code block inside the "if" statement begins. **Ex:** ```python x = 10 if (x > 5 and x < 20): print(x) ``` In this case, PEP 8 provides two alternatives to help improve readability. 1. **Add a comment after the condition. Most of the editors will have separate styles for code and comment.** **Ex:** ```python x = 10 if (x > 5 and x < 20): # prints when conditions satisfied print(x) ``` 2. **Add double indentation on the line continuation.** **Ex:** ```python x = 10 if (x > 5 and x < 20): print(x) ``` When writing a big expression, it is better to keep the expression vertically aligned. It is called a "hanging indent". **Ex:** ```python list_of_candidates = [ "Joseph", "Sam", "Tim" ] ``` Use double indentation if there are chances for the hanging indent to be confused with indentation of code block. **Ex:** ```python # Not recommended def test_function( param_1, param_2, param_3, param_4): return param_4 ``` **Ex:** ```python def test_function( param_1, param_2, param_3, param_4): return param_4 ``` ### Where to Put the Closing Brace PEP 8 provides two options for the position of the closing brace in line continuations: 1. **Line up the closing brace with the first non-whitespace character of the previous line.** **Ex:** ```python list_of_candidates = [ "Joseph", "Sam", "Tim" ] ``` 2. **Line up the closing brace with the first character of the line that starts the construct** ```python list_of_candidates = [ "Joseph", "Sam", "Tim" ] ``` ## Comments >"If the implementation is hard to explain, it's a bad idea." >-The Zen of Python It is very important to document programming codes so that the programmer itself or any collaborators, can understand it easily. Some key points to remember when adding comments are: * **Limit the line length of comments and docstrings to 72 characters.** * **Use complete sentences, starting with a capital letter.** * **Make sure to update comments when changing the code.** ### Block Comments Use block comments to document a section of code. They are useful to explain several lines of code, to perform a single action, such as importing data from a file or updating a database entry. They are important as they help others understand the purpose and functionality of a given code block. PEP 8 provides the following rules for writing block comments: * **Indent block comments to the same level as the code they describe.** * **Start each line with a # followed by a single space.** * **Separate paragraphs by a line containing a single #.** **Ex:** ```python for i in range(0, 10): # Loop over i ten times and print out the value # of i, followed by a # new line character print(i, '\n') ``` Sometimes, it is necessary to use more than one paragraph to describe the code. **Ex:** ```python def login(username, password): # This code is used for user authentication. # Given username and password is validated against existing # values in database. code goes here ``` ### Inline Comments Inline comments explain a single statement in a piece of code. They are useful to explain the purpose of a statement. Here's what PEP 8 has to say about them: * **Use inline comments sparingly.** * **Write inline comments on the same line as the statement they refer to.** * **Separate inline comments by two or more spaces from the statement.** * **Start inline comments with a # and a single space, like block comments.** * **Don't use them to explain the block.** **Ex:** ```python aver = (a+b+c)/3 # Calculates the average of numbers x = 'Steve Jobs' # Student name ``` Inline comments can be used to give extra information. In the above example, x is a variable name for a student name. But it is a bad practice. You can name it as student_name and avoid using the comment. ## Documentation Strings Documentation strings, or docstrings, are strings enclosed in double (""") or single (''') quotation marks that appear on the first line of any function, class, method, or module. Docstrings are used to explain and document a specific block of code. There is an entire PEP, PEP 257, that covers docstrings. The most important rules applying to docstrings are the following: * **Surround docstrings with three double quotes on either sides.** **Ex:** ```python """This is a docstring""" ``` * **Write docstrings for all public modules, functions, classes, and methods.** * **Put the """" that ends a multi line docstring on a line by itself.** **Ex:** ```python def register(param): """This function is for saving details of a product into the database. Your code goes here """ ``` For one-line docstrings, keep the """ on the same line: **Ex:** ```python def test(param): """This is a single line comment.""" Your code goes here ``` ## Whitespace in Expressions and Statements >"Sparse is better than dense." >-The Zen of Python Whitespaces are helpful in expressions and statements when used properly. If there is not enough whitespace, then the code can be difficult to read, as it is all bunched up together. ### Whitespace Around Binary Operators: Surround the binary operators with a single space on either side as follows: * **Assignment operators (=, +=, -=, etc.)** * **Comparisons (==, !=, >, <, >=, <=) and (is, is not, in, not in)** * **Booleans (and, not, or)** When = is used to assign a default value to a function argument, do not surround it with spaces. **Ex:** ```python def function(default_param=10): Your code goes here ``` When there's more than one operator in a statement, adding a single space before and after each operator can look confusing. Instead, it is better to only add whitespace around the operators with the lowest priority, especially when performing mathematical manipulation. Here are a couple of examples. **Ex:** ```python b = a**2 + 15 c = (a+b) * (a-b) ``` You can also apply this to "if" statements where there are multiple conditions: **Ex:** ```python if x>5 and x%2==0: print('x is larger than 5 and divisible by 2!') ``` In slices, colon acts as a binary operator. Therefore, the same rules apply. The following are some examples of valid list slices: **Ex:** ```python num_list[3:4] # Treat the colon as the operator with lowest priority num_list[a+1 : a+2] # In an extended slice, both colons must be # surrounded by the same amount of whitespace num_list[3:4:5] num_list[a+1 : a+2 : a+3] # The space is omitted if a slice parameter is omitted num_list[a+1 : a+2 :] ``` ### When to Avoid Adding Whitespace In some cases, adding whitespace can make the code harder to read. Too much whitespace can make the code overly sparse and difficult to follow. PEP 8 outlines very clear examples where whitespace is inappropriate: * **Immediately inside parentheses, brackets, or braces.** **Ex:** ```python # Recommended my_list = [1, 2, 3] # Not recommended my_list = [ 1, 2, 3, ] ``` * **Before a comma, semicolon, or colon.** **Ex:** ```python # Recommended print(x, y) # Not recommended print(x, y) ``` * **Before the open parenthesis that starts the argument list of a function call.** **Ex:** ```python # Recommended find_factorial(5) # Not recommended find_factorial (5) ``` * **Before the open bracket that starts an index or slice.** **Ex:** ```python # Recommended my_list[3] # Not recommended my_list [3] ``` * **Between a trailing comma and a closing parenthesis.** **Ex:** ```python # Recommended tuple = (1,) # Not recommended tuple = (1, ) ``` * **To align assignment operators.** **Ex:** ```python # Recommended var1 = 5 var2 = 6 some_long_var = 7 # Not recommended var1 = 5 var2 = 6 some_long_var = 7 ``` ## Programming Recommendations >"Simple is better than complex." >-The Zen of Python There are several ways to perform a similar action in Python. PEP 8 provides some suggestions to remove that ambiguity and preserve consistency. * **Don't compare boolean values to True or False using the equivalence operator.** **Ex:** ```python # Not recommended my_bool = 10 > 5 if my_bool == True: return '10 is bigger than 5' # Recommended if my_bool: return '10 is bigger than 5' ``` * **Use the fact that empty sequences are falsy in “if” statements.** If the list is empty, it's length is 0, which is equivalent to False when used in an "if" statement. **Ex:** ```python # Not recommended my_list = [] if not len(my_list): print('List is empty!') # Recommended my_list = [] if not my_list: print('List is empty!') ``` * **Use "is not" rather than "not ... is" in "if" statements.** If you are trying to check whether a variable has a defined value, there are two options. The first is to evaluate an "if" statement with "x is not None". A second option would be to evaluate "x is None" and then have an "if" statement based on the outcome. **Ex:** ```python # Option 1 # Recommended if x is not None: return 'x exists!' # Option 2 # Not recommended if not x is None: return 'x exists!' ``` * **Don't use if x: when you mean if x is not None:** Sometimes, functions will have arguments that are "None" by default. A common mistake when checking such an argument, arg, that has been given a value is to use the following: **Ex:** ```python # Not Recommended if arg: # Do something with arg... ``` This code checks whether arg is truthy. Instead, you have to check that arg is "not None". So it would be better to use the following: **Ex:** ```python # Recommended if arg is not None: # Do something with arg... ``` The mistake being made here is assuming that "not None" and "truthy" are equivalent. You could have set arg = []. As we saw above, empty lists are evaluated as false in Python. So, even though the argument arg has been assigned, the condition is not met, and so the code in the body of the "if" statement will not be executed. ## When to Ignore PEP 8 Adhering to PEP 8 will ensure that the code written is clean, professional and readable. This will benefit collaborators and the organization. However, PEP 8 becomes inconvenient in the following cases: * If complying with PEP 8 would break compatibility with existing software. * If the existing code is inconsistent with PEP 8. * If code needs to remain compatible with older versions of Python. ## How to Ensure that Your Code Follows PEP 8 There is a lot to remember to make sure that the code is PEP 8 compliant. It is difficult to remember all these rules when writing programs. Luckily, there are tools that can help to check whether the code is PEP 8 compliant or not. There are two types of tools that you can use to enforce PEP 8 compliance: linters and autoformatters. ### Linter Linters are programs that analyze source code for syntactic discrepancies and flag errors. They provide suggestions on how to fix the error. **What is "Linting"?** "Linting" means running a basic quality tool against your code. The tool will check your code syntax and provide instructions on how to clean it. **Why should we use it?** * Linting helps to prevent bugs in your program. * Linting helps in creating better quality, readable code. * Linting helps prevent things like syntax errors, typos, bad formatting, incorrect styling, etc. * Linting saves our time as a developer. ### What is Flake8? Flake8 is one of the linting tools available. It is a great toolkit for checking your code base against coding style (PEP8) and programming errors (like "library imported but unused" and "Undefined name"). **Use the following command to install flake8.** ```python python<version> -m pip install flake8 ``` **Running flake8**: **Check particular file:** ```python flake8 path/to/code/code.py ``` **Check entire project:** ```python flake8 path/to/project/ ``` Flake8 will list all the errors in the file if any. **Ex:** ```bash Monishs-MacBook-Air:Desktop monish$ flake8 code.py code.py:5:1: W391 blank line at end of file code.py:5:1: W293 blank line contains whitespace Monishs-MacBook-Air:Desktop monish$ ``` ### Autoformatters Autoformatters are programs that refactor your code to conform with PEP 8 automatically. One such program is “black”, which formats code to meet most of the rules in PEP 8. **Install "black" using pip.** It requires Python 3.6+ to run: ```bash pip install black ``` It can be run via the command line, as with the linters. Let's say you start with the following code that isn't PEP 8 compliant, in a file called code.py: **Ex:** ```python for i in range(0, 10): for j in range(0, 10): if i % 3 == 0: print(i, j) ``` **Run "black" via the command line:** ```bash Monishs-MacBook-Air:Desktop monish$ black code.py reformatted code.py All done! + 1 file reformatted. ```