SitePoint
Blog
Forum
Library
Login
Join Premium
Toggle sidebar
Clean Code in Python, 2nd Edition
Toggle community discussions
Close
Content
Files
Bookmarks
Preface
Clean Code in Python - Second Edition
Contributors
About the author
About the reviewer
Preface
Who this book is for?
What this book covers
To get the most out of this book
Download the example code files
Download the color images
Conventions used
Get in touch
Reviews
1
Introduction, Code Formatting, and Tools
Introduction
The meaning of clean code
The importance of having clean code
Some exceptions
Code formatting
Adhering to a coding style guide on your project
Documentation
Code comments
Docstrings
Annotations
Do annotations replace docstrings?
Tooling
Checking type consistency
Generic validations in code
Automatic formatting
Setup for automatic checks
Summary
References
Pythonic Code
Indexes and slices
Creating your own sequences
Context managers
Implementing context managers
Comprehensions and assignment expressions
Properties, attributes, and different types of methods for objects
Underscores in Python
Properties
Creating classes with a more compact syntax
Iterable objects
Container objects
Dynamic attributes for objects
Callable objects
Summary of magic methods
Caveats in Python
Mutable default arguments
Extending built-in types
A brief introduction to asynchronous code
Summary
References
General Traits of Good Code
Design by contract
Preconditions
Postconditions
Pythonic contracts
Design by contract – conclusions
Defensive programming
Error handling
Using assertions in Python
Separation of concerns
Cohesion and coupling
Acronyms to live by
DRY/OAOO
YAGNI
KIS
EAFP/LBYL
Inheritance in Python
When inheritance is a good decision
Anti-patterns for inheritance
Multiple inheritance in Python
Arguments in functions and methods
How function arguments work in Python
The number of arguments in functions
Final remarks on good practices for software design
Orthogonality in software
Structuring the code
Summary
References
The SOLID Principles
The single responsibility principle
A class with too many responsibilities
Distributing responsibilities
The open/closed principle
Example of maintainability perils for not following the OCP
Refactoring the events system for extensibility
Extending the events system
Final thoughts about the OCP
Liskov's substitution principle
Detecting LSP issues with tools
More subtle cases of LSP violations
Remarks on the LSP
Interface segregation
An interface that provides too much
The smaller the interface, the better
How small should an interface be?
Dependency inversion
A case of rigid dependencies
Inverting the dependencies
Dependency injection
Summary
References
Using Decorators to Improve Our Code
What are decorators in Python?
Function decorators
Decorators for classes
Other types of decorator
More advanced decorators
Passing arguments to decorators
Decorators with default values
Decorators for coroutines
Extended syntax for decorators
Good uses for decorators
Adapting function signatures
Validating parameters
Tracing code
Effective decorators – avoiding common mistakes
Preserving data about the original wrapped object
Dealing with side effects in decorators
Creating decorators that will always work
Decorators and clean code
Composition over inheritance
The DRY principle with decorators
Decorators and separation of concerns
Analysis of good decorators
Summary
References
Getting More Out of Our Objects with Descriptors
A first look at descriptors
The machinery behind descriptors
Exploring each method of the descriptor protocol
Types of descriptors
Non-data descriptors
Data descriptors
Descriptors in action
An application of descriptors
Different forms of implementing descriptors
More considerations about descriptors
Analysis of descriptors
How Python uses descriptors internally
Implementing descriptors in decorators
Final remarks about descriptors
Interface of descriptors
Object-oriented design of the descriptors
Type annotations on descriptors
Summary
References
Generators, Iterators, and Asynchronous Programming
Technical requirements
Creating generators
A first look at generators
Generator expressions
Iterating idiomatically
Idioms for iteration
Coroutines
The methods of the generator interface
More advanced coroutines
Asynchronous programming
Magic asynchronous methods
Asynchronous iteration
Asynchronous generators
Summary
References
Unit Testing and Refactoring
Design principles and unit testing
A note about other forms of automated testing
Unit testing and agile software development
Unit testing and software design
Defining the boundaries of what to test
Tools for testing
Frameworks and libraries for unit testing
Refactoring
Evolving our code
Production code isn't the only one that evolves
More about testing
Property-based testing
Mutation testing
Common themes in testing
A brief introduction to test-driven development
Summary
References
Common Design Patterns
Design pattern considerations in Python
Design patterns in action
Creational patterns
Structural patterns
Behavioral patterns
The null object pattern
Final thoughts about design patterns
The influence of patterns over the design
Design patterns as theory
Names in our models
Summary
References
Clean Architecture
From clean code to clean architecture
Separation of concerns
Monolithic applications and microservices
Abstractions
Software components
Packages
Docker containers
Use case
The services
Summary
References
Summing it all up
Index
Open text modal
Community Questions
Close