Python#
import this
Effective Python#
90 specific ways to write better Python
It's not safe to code review alone. Take these with you
Pythonic Thinking#
1-10
- Know Which Version of Python You're Using
- Follow the PEP 8 Style Guide
- Know the Differences Between bytes and str
- Prefer Interpolated F-Strings Over C-style Format Strings and str.format
- Write Helper Functions Instead of Complex Expressions
- Prefer Multiple Assignment Unpacking Over Indexing
- Prefer enumerate Over range
- Use zip to Process Iterators in Parallel
- Avoid else Blocks After for and while Loops
- Prevent Repetition with Assignment Expressions
Lists and Dictionaries#
11-18
- Know How to Slice Sequences
- Avoid Striding and Slicing in a Single Expression
- Prefer Catch-All Unpacking Over Slicing
- Sort by Complex Criteria Using the key Parameter
- Be Cautious When Relying on dict Insertion Ordering
- Prefer get Over in and KeyError to Handle Missing Dictionary Keys
- Prefer defaultdict Over setdefault to Handle Missing Items in Internal State
- Know How to Construct Key-Dependent Default Values with
__missing__
Functions#
19-26
- Never Unpack More Than Three Variables When Functions Return Multiple Values
- Prefer Raising Exceptions to Returning None
- Know How Closures Interact with Variable Scope
- Reduce Visual Noise with Variable Positional Arguments
- Provide Optional Behavior with Keyword Arguments
- Use None and Docstrings to Specify Dynamic Default Arguments
- Enforce Clarity with Keyword-Only and Positional-Only Arguments
- Define Function Decorators with
functools.wraps
Comprehensions and Generators#
27-36
- Use Comprehensions Instead of map and filter
- Avoid More Than Two Control Subexpressions in Comprehensions
- Avoid Repeated Work in Comprehensions by Using Assignment Expressions
- Consider Generators Instead of Returning Lists
- Be Defensive When Iterating Over Arguments
- Consider Generator Expressions for Large List Comprehensions
- Compose Multiple Generators with yield from
- Avoid Injecting Data into Generators with send
- Avoid Causing State Transitions in Generators with throw
- Consider itertools for Working with Iterators and Generators
Classes and Interfaces#
37-43
- Compose Classes Instead of Nesting Many Levels of Built-in Types
- Accept Functions Instead of Classes for Simple Interfaces
- Use
@classmethodPolymorphism to Construct Objects Generically - Initialize Parent Classes with super
- Consider Composing Functionality with Mix-in Classes
- Prefer Public Attributes Over Private Ones
- Inherit from collections.abc for Custom Container Types
Metaclasses and Attributes#
44-51
- Use Plain Attributes Instead of Setter and Getter Methods
- Consider @property Instead of Refactoring Attributes
- Use Descriptors for Reusable @property Methods
- Use
__getattr__,__getattribute__, and__setattr__for Lazy Attributes - Validate Subclasses with
__init_subclass__ - Register Class Existence with
__init_subclass__ - Annotate Class Attributes with
__set_name__ - Prefer Class Decorators Over Metaclasses for Composable Class Extensions
Concurrency and Parallelism#
52-64
- Use subprocess to Manage Child Processes
- Use Threads for Blocking I/O, Avoid for Parallelism
- Use Lock to Prevent Data Races in Threads
- Use Queue to Coordinate Work Between Threads
- Know How to Recognize When Concurrency Is Necessary
- Avoid Creating New Thread Instances for On-demand Fan-out
- Understand How Using Queue for Concurrency Requires Refactoring
- Consider ThreadPoolExecutor When Threads Are Necessary for Concurrency
- Achieve Highly Concurrent I/O with Coroutines
- Know How to Port Threaded I/O to asyncio
- Mix Threads and Coroutines to Ease the Transition to asyncio
- Avoid Blocking the asyncio Event Loop to Maximize Responsiveness
- Consider concurrent.futures for True Parallelism
Robustness and Performance#
65-74
- Take Advantage of Each Block in try/except /else/finally
- Consider contextlib and with Statements for Reusable try/finally Behavior
- Use datetime Instead of time for Local Clocks
- Make pickle Reliable with copyreg
- Use decimal When Precision Is Paramount
- Profile Before Optimizing
- Prefer deque for Producer-Consumer Queues
- Consider Searching Sorted Sequences with bisect
- Know How to Use heapq for Priority Queues
- Consider memoryview and bytearray for Zero-Copy Interactions with bytes
Testing and Debugging#
75-81
- Use repr Strings for Debugging Output
- Verify Related Behaviors in TestCase Subclasses
- Isolate Tests from Each Other with setUp, tearDown, setUpModule, and tearDownModule
- Use Mocks to Test Code with Complex Dependencies
- Encapsulate Dependencies to Facilitate Mocking and Testing
- Consider Interactive Debugging with pdb
- Use tracemalloc to Understand Memory Usage and Leaks
Collaboration#
82-90
- Know Where to Find Community-Built Modules
- Use Virtual Environments for Isolated and Reproducible Dependencies
- Write Docstrings for Every Function, Class, and Module
- Use Packages to Organize Modules and Provide Stable APIs
- Consider Module-Scoped Code to Configure Deployment Environments
- Define a Root Exception to Insulate Callers from APIs
- Know How to Break Circular Dependencies
- Consider warnings to Refactor and Migrate Usage
- Consider Static Analysis via typing to Obviate Bugs
Links#
Essential libraries#
Essential packages#
- Python Click Argument Parser
- Python Django Content Management Framework
- Python Requests Http Requests Library