# CS 410 Python Style Guide Welcome to the CS410 Python Style Guide. Our mission in this course is to help you uplevel your technical skills while mastering the art of writing clean, consistent code. Trust us, your future self and teammates will thank you! Why is this important? Clean code isn't just a nice-to-have; it's essential for effective collaboration, maintenance, and readability. This guide will walk you through industry standards and prepare you for the professional world. Make sure to read through it carefully. We’ll be keeping an eye on your coding style, and **repeated issues will lead to point deductions on your homework**. But don't worry—we're here to help you build great habits that will benefit you not just in this course, but throughout your entire coding career. # Background This style guide is built on the best practices outlined in [PEP 8 Style Guide for Python Code](https://peps.python.org/pep-0008/) and [PEP 257 Docstring Conventions](https://peps.python.org/pep-0257/), the go-to industry standards for writing readable and consistent Python code. PEP 8, created in 2001 by Guido van Rossum, Barry Warsaw, and Alyssa Coghlan, aims to standardize Python code for clarity and uniformity. PEP 257 enhances documentation through clear and consistent docstring conventions. As the PEPs keep evolving with the language, you can be sure they will stay relevant and useful. Stick to these guidelines for happier coding! # Best Practices ## Naming Conventions ### Variables and Functions - **Use descriptive names**: Give variables and functions names that clearly describe their purpose. For example: `user_name`, `calculate_total`. ### Modules - **Lowercase names**: Module names should be all lowercase, with words concatenated together. Keep them short but descriptive. For example: `mymod`. ### Classes - **UpperCamelCase**: Classes should be named using nouns that describe what the class models. Class names should use UpperCamelCase. For example: `Ocean`, `TreeHouse`. - **Exceptions**: Class names for exceptions should end with “Error”. For example: `BadDataError`. ### Constants - **CONSTANT_CASE**: Constant names should be all uppercase with words separated by underscores. For example: `MY_PYTHON_CONSTANT`. ### Everything Else - **snake_case**: Functions, fields, parameters, and variables should use snake_case. For example: `my_variable`, `exciting_new_method`. ## Formatting ### Indentation In Python, indentation is a must. Your code will not compile or run properly if you don’t have the correct indentation. It can be a little finicky, though: if you use spaces to indent in some places and tabs in another your compiler will not be happy. - **Use 4 spaces**: Indent all blocks of code with 4 spaces. Avoid using tabs. - **Block indentation**: A new block is preceded by a colon (:), and the indent level returns to the previous level when the block ends. Example: ```python! def check_adult(age): if age >= 18: print("You are officially an adult!") else: print("Not an adult yet...") ``` - **Configure your editor**: Set your editor to insert 4 spaces when the tab key is pressed. ::: spoiler **Tip: Configure VSCode to insert 4 spaces when tab is pressed.** In the bottom right of your window in VSCode, there’s a portion that will say “Spaces: \<number>” or “Tab Size: \<number>.” **Click on that and choose “Indent using spaces” followed by “4” to have the correct settings. When you’re done you should see “Spaces: 4” in the bottom corner of your code window.** ::: ### Line Wrapping - **80 characters max**: Lines of code should not exceed 80 characters. - **Operator on new line**: When wrapping lines, the operator should start the new line. For example: ```python! # This is correct long_argument_name = even_longer_argument_name \ + yet_another_even_longer_name # This is not correct long_argument_name = even_longer_argument_name + yet_another_even_longer_name # This is also not correct long_argument_name = even_longer_argument_name + yet_another_even_longer_name ``` - **Backslash for wrapping**: Use a backslash (`\`) at the end of a line to indicate continuation. Here's how it may come in handy: ```python! # This is correct now! long_argument_name = even_longer_argument_name \ + yet_another_even_longer_name # And so is this! long_argument_name = even_longer_argument_name + \ yet_another_even_longer_name ``` :::warning **Note:** When wrapping with the backslash, the wrapped line of code must be indented so that the first character of the wrapped line is in line with the beginning of the expression on the original line (in this case, the equality operator). ::: ## Commenting The general principle of commenting is to clarify / explain your code to an outside observer (or to your future self!). ### Implementation Comments - **Use `#`**: Begin all implementation comments with `#`. ```python # This is a multi-line comment # in Python! x = 5 # This is an end-of-line comment ``` ### Type Annotations - **Type annotations**: Include type annotations for all inputs and outputs. Omit output annotations for functions with no return value (e.g., functions that only print). ### Documentation Comments (Docstrings) Also known as a “docstring,” documentation comments in Python appear directly _underneath_ the declaration of each function. :::warning **Write docstrings for all functions** including helper and nested functions. A good docstring should clearly describe the function's inputs, outputs, and purpose, allowing users to understand the function without needing to look at the body. ::: - **Use triple quotes**: Place docstrings directly under the function declaration. - **Follow this format**: - One sentence summary of the function's purpose - Parameter descriptions (if any) - Return value descriptions (if any) - Exceptions thrown (if any) - Additional notes (e.g., restrictions, side effects) **Example docstring:** ```python def sum(x: float, y: float) -> float: """Sums two numbers Parameters: x -- the first number y -- the second number Returns: A number (the sum of x and y) Throws: BadInputError if x or y (or both) is not a number """ ``` ## Other Tips ### `self` Keyword - **Use `self`**: **Always** use `self` to access methods and fields within a class. It should be the first parameter of any method in the class. ```python class Food: def __init__(self, fruit: str, color: str) -> None: self.fruit = fruit self.color = color def show(self) -> None: print("fruit is", self.fruit) print("color is", self.color) ``` ### Import Statements - **Importing**: You can import specific functions or entire modules. ```python from random import randint num = randint(1, 10) import random num = random.randint(1, 10) ``` 1. **Use constants and helper functions appropriately**: Ensure they are not redundant. 2. **Return statements**: Write return statements without parentheses. ```python return value ``` 3. **if statements**: Use newlines for readability. ```python if condition1: print('condition1') elif condition2: print('condition2') else: print('condition3') ```