Clean Code in Python - Second Edition

Book description

Tackle inefficiencies and errors the Pythonic way

Key Features

  • Enhance your coding skills using the new features introduced in Python 3.9
  • Implement the refactoring techniques and SOLID principles in Python
  • Apply microservices to your legacy systems by implementing practical techniques

Book Description

Experienced professionals in every field face several instances of disorganization, poor readability, and testability due to unstructured code.

With updated code and revised content aligned to the new features of Python 3.9, this second edition of Clean Code in Python will provide you with all the tools you need to overcome these obstacles and manage your projects successfully.

The book begins by describing the basic elements of writing clean code and how it plays a key role in Python programming. You will learn about writing efficient and readable code using the Python standard library and best practices for software design.

The book discusses object-oriented programming in Python and shows you how to use objects with descriptors and generators. It will also show you the design principles of software testing and how to resolve problems by implementing software design patterns in your code. In the concluding chapter, we break down a monolithic application into a microservices-based one starting from the code as the basis for a solid platform.

By the end of this clean code book, you will be proficient in applying industry-approved coding practices to design clean, sustainable, and readable real-world Python code.

What you will learn

  • Set up a productive development environment by leveraging automatic tools
  • Leverage the magic methods in Python to write better code, abstracting complexity away and encapsulating details
  • Create advanced object-oriented designs using unique features of Python, such as descriptors
  • Eliminate duplicated code by creating powerful abstractions using software engineering principles of object-oriented design
  • Create Python-specific solutions using decorators and descriptors
  • Refactor code effectively with the help of unit tests
  • Build the foundations for solid architecture with a clean code base as its cornerstone

Who this book is for

This book is designed to benefit new as well as experienced programmers. It will appeal to team leads, software architects and senior software engineers who would like to write Pythonic code to save on costs and improve efficiency. The book assumes that you have a strong understanding of programming

Table of contents

  1. Preface
    1. Who this book is for?
    2. What this book covers
    3. To get the most out of this book
      1. Download the example code files
      2. Download the color images
      3. Conventions used
    4. Get in touch
      1. Reviews
  2. Introduction, Code Formatting, and Tools
    1. Introduction
      1. The meaning of clean code
      2. The importance of having clean code
      3. Some exceptions
    2. Code formatting
      1. Adhering to a coding style guide on your project
    3. Documentation
      1. Code comments
      2. Docstrings
      3. Annotations
      4. Do annotations replace docstrings?
    4. Tooling
      1. Checking type consistency
      2. Generic validations in code
      3. Automatic formatting
      4. Setup for automatic checks
    5. Summary
    6. References
  3. Pythonic Code
    1. Indexes and slices
      1. Creating your own sequences
    2. Context managers
      1. Implementing context managers
    3. Comprehensions and assignment expressions
    4. Properties, attributes, and different types of methods for objects
      1. Underscores in Python
      2. Properties
      3. Creating classes with a more compact syntax
      4. Iterable objects
        1. Creating iterable objects
        2. Creating sequences
      5. Container objects
      6. Dynamic attributes for objects
      7. Callable objects
      8. Summary of magic methods
    5. Caveats in Python
      1. Mutable default arguments
      2. Extending built-in types
    6. A brief introduction to asynchronous code
    7. Summary
    8. References
  4. General Traits of Good Code
    1. Design by contract
      1. Preconditions
      2. Postconditions
      3. Pythonic contracts
      4. Design by contract – conclusions
    2. Defensive programming
      1. Error handling
        1. Value substitution
        2. Exception handling
      2. Using assertions in Python
    3. Separation of concerns
      1. Cohesion and coupling
    4. Acronyms to live by
      1. DRY/OAOO
      2. YAGNI
      3. KIS
      4. EAFP/LBYL
    5. Inheritance in Python
      1. When inheritance is a good decision
      2. Anti-patterns for inheritance
      3. Multiple inheritance in Python
        1. Method Resolution Order (MRO)
        2. Mixins
    6. Arguments in functions and methods
      1. How function arguments work in Python
        1. How arguments are copied to functions
        2. Variable number of arguments
        3. Positional-only parameters
        4. Keyword-only arguments
      2. The number of arguments in functions
        1. Function arguments and coupling
        2. Compact function signatures that take too many arguments
    7. Final remarks on good practices for software design
      1. Orthogonality in software
      2. Structuring the code
    8. Summary
    9. References
  5. The SOLID Principles
    1. The single responsibility principle
      1. A class with too many responsibilities
      2. Distributing responsibilities
    2. The open/closed principle
      1. Example of maintainability perils for not following the OCP
      2. Refactoring the events system for extensibility
      3. Extending the events system
      4. Final thoughts about the OCP
    3. Liskov's substitution principle
      1. Detecting LSP issues with tools
        1. Using mypy to detect incorrect method signatures
        2. Detecting incompatible signatures with pylint
      2. More subtle cases of LSP violations
      3. Remarks on the LSP
    4. Interface segregation
      1. An interface that provides too much
      2. The smaller the interface, the better
      3. How small should an interface be?
    5. Dependency inversion
      1. A case of rigid dependencies
      2. Inverting the dependencies
      3. Dependency injection
    6. Summary
    7. References
  6. Using Decorators to Improve Our Code
    1. What are decorators in Python?
      1. Function decorators
      2. Decorators for classes
      3. Other types of decorator
    2. More advanced decorators
      1. Passing arguments to decorators
        1. Decorators with nested functions
        2. Decorator objects
      2. Decorators with default values
      3. Decorators for coroutines
      4. Extended syntax for decorators
    3. Good uses for decorators
      1. Adapting function signatures
      2. Validating parameters
      3. Tracing code
    4. Effective decorators – avoiding common mistakes
      1. Preserving data about the original wrapped object
      2. Dealing with side effects in decorators
        1. Incorrect handling of side effects in a decorator
        2. Requiring decorators with side effects
      3. Creating decorators that will always work
    5. Decorators and clean code
      1. Composition over inheritance
      2. The DRY principle with decorators
      3. Decorators and separation of concerns
      4. Analysis of good decorators
    6. Summary
    7. References
  7. Getting More Out of Our Objects with Descriptors
    1. A first look at descriptors
      1. The machinery behind descriptors
      2. Exploring each method of the descriptor protocol
        1. The get method
        2. The set method
        3. The delete method
        4. The set name method
    2. Types of descriptors
      1. Non-data descriptors
      2. Data descriptors
    3. Descriptors in action
      1. An application of descriptors
        1. A first attempt without using descriptors
        2. The idiomatic implementation
      2. Different forms of implementing descriptors
        1. The issue of shared state
        2. Accessing the dictionary of the object
        3. Using weak references
      3. More considerations about descriptors
        1. Reusing code
        2. An alternative to class decorators
    4. Analysis of descriptors
      1. How Python uses descriptors internally
        1. Functions and methods
        2. Built-in decorators for methods
        3. Slots
      2. Implementing descriptors in decorators
    5. Final remarks about descriptors
      1. Interface of descriptors
      2. Object-oriented design of the descriptors
      3. Type annotations on descriptors
    6. Summary
    7. References
  8. Generators, Iterators, and Asynchronous Programming
    1. Technical requirements
    2. Creating generators
      1. A first look at generators
      2. Generator expressions
    3. Iterating idiomatically
      1. Idioms for iteration
        1. The next() function
        2. Using a generator
        3. Itertools
        4. Simplifying code through iterators
        5. The iterator pattern in Python
    4. Coroutines
      1. The methods of the generator interface
        1. close()
        2. throw(ex_type[, ex_value[, ex_traceback]])
        3. send(value)
      2. More advanced coroutines
        1. Returning values in coroutines
        2. Delegating into smaller coroutines – the 'yield from' syntax
    5. Asynchronous programming
      1. Magic asynchronous methods
        1. Asynchronous context managers
        2. Other magic methods
      2. Asynchronous iteration
      3. Asynchronous generators
    6. Summary
    7. References
  9. Unit Testing and Refactoring
    1. Design principles and unit testing
      1. A note about other forms of automated testing
      2. Unit testing and agile software development
      3. Unit testing and software design
      4. Defining the boundaries of what to test
    2. Tools for testing
      1. Frameworks and libraries for unit testing
        1. unittest
        2. pytest
        3. Code coverage
        4. Mock objects
    3. Refactoring
      1. Evolving our code
      2. Production code isn't the only one that evolves
    4. More about testing
      1. Property-based testing
      2. Mutation testing
      3. Common themes in testing
        1. Boundaries or limit values
        2. Classes of equivalence
        3. Edge cases
      4. A brief introduction to test-driven development
    5. Summary
    6. References
  10. Common Design Patterns
    1. Design pattern considerations in Python
    2. Design patterns in action
      1. Creational patterns
        1. Factories
        2. Singleton and shared state (monostate)
        3. Builder
      2. Structural patterns
        1. Adapter
        2. Composite
        3. Decorator
        4. Facade
      3. Behavioral patterns
        1. Chain of responsibility
        2. The template method
        3. Command
        4. State
    3. The null object pattern
    4. Final thoughts about design patterns
      1. The influence of patterns over the design
      2. Design patterns as theory
      3. Names in our models
    5. Summary
    6. References
  11. Clean Architecture
    1. From clean code to clean architecture
      1. Separation of concerns
      2. Monolithic applications and microservices
      3. Abstractions
    2. Software components
      1. Packages
        1. Managing dependencies
        2. Other considerations when managing dependencies
        3. Artifact versions
      2. Docker containers
      3. Use case
        1. The code
        2. Domain models
        3. Calling from the application
        4. Adapters
      4. The services
        1. Analysis
        2. The dependency flow
        3. Limitations
        4. Testability
        5. Intention revealing
    3. Summary
    4. References
    5. Summing it all up
  12. Other Books You May Enjoy
  13. Index

Product information

  • Title: Clean Code in Python - Second Edition
  • Author(s): Mariano Anaya
  • Release date: January 2021
  • Publisher(s): Packt Publishing
  • ISBN: 9781800560215