Clean Code in Python

Book description

Getting the most out of Python to improve your codebase

Key Features

  • Save maintenance costs by learning to fix your legacy codebase
  • Learn the principles and techniques of refactoring
  • Apply microservices to your legacy systems by implementing practical techniques

Book Description

Python is currently used in many different areas such as software construction, systems administration, and data processing.

In all of these areas, experienced professionals can find examples of inefficiency, problems, and other perils, as a result of bad code. After reading this book, readers will understand these problems, and more importantly, how to correct them.

The book begins by describing the basic elements of writing clean code and how it plays an important role in Python programming. You will learn about writing efficient and readable code using the Python standard library and best practices for software design. You will learn to implement the SOLID principles in Python and use decorators to improve your code. The book delves more deeply into 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 software problems by implementing design patterns in your code. In the final chapter we break down a monolithic application to a microservice one, starting from the code as the basis for a solid platform.

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

What you will learn

  • Set up tools to effectively work in a development environment
  • Explore how the magic methods of Python can help us write better code
  • Examine the traits of Python to create advanced object-oriented design
  • Understand removal of duplicated code using decorators and descriptors
  • Effectively refactor code with the help of unit tests
  • Learn to implement the SOLID principles in Python

Who this book is for

This book will appeal to team leads, software architects and senior software engineers who would like to work on their legacy systems to save cost and improve efficiency. A strong understanding of Programming is assumed.

Table of contents

  1. Title Page
  2. Copyright and Credits
    1. Clean Code in Python
  3. Dedication
  4. Packt Upsell
    1. Why subscribe?
  5. Contributors
    1. About the author
    2. About the reviewer
    3. Packt is searching for authors like you
  6. 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. Conventions used
    4. Get in touch
      1. Reviews
  7. Introduction, Code Formatting, and Tools
    1. The meaning of clean code
    2. The importance of having clean code
      1. The role of code formatting in clean code
      2. Adhering to a coding style guide on your project
    3. Docstrings and annotations
      1. Docstrings
      2. Annotations
      3. Do annotations replace docstrings?
      4. Configuring the tools for enforcing basic quality gates
        1. Type hinting with Mypy
        2. Checking the code with Pylint
        3. Setup for automatic checks
    4. Summary
  8. Pythonic Code
    1. Indexes and slices
      1. Creating your own sequences
    2. Context managers
      1. Implementing context managers
    3. Properties, attributes, and different types of methods for objects
      1. Underscores in Python
      2. Properties
    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
    9. Caveats in Python
      1. Mutable default arguments
      2. Extending built-in types
    10. Summary
    11. References
  9. 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
          1. Handle exceptions at the right level of abstraction
          2. Do not expose tracebacks
          3. Avoid empty except blocks
          4. Include the original exception
      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. Composition and inheritance
      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
      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
  10. The SOLID Principles
    1. 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 open/closed principle
      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. Detecting incorrect datatypes in method signatures with Mypy
        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
    6. Summary
    7. References
  11. Using Decorators to Improve Our Code
    1. What are decorators in Python?
      1. Decorate functions
      2. Decorate classes
      3. Other types of decorator
      4. Passing arguments to decorators
        1. Decorators with nested functions
        2. Decorator objects
      5. Good uses for decorators
        1. Transforming parameters
        2. Tracing code
    2. 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
    3. The DRY principle with decorators
    4. Decorators and separation of concerns
    5. Analyzing good decorators
    6. Summary
    7. References
  12. 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. __get__(self, instance, owner)
        2. __set__(self, instance, value)
        3. __delete__(self, instance)
        4. __set_name__(self, owner, name)
    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 global shared state
        2. Accessing the dictionary of the object
        3. Using weak references
      3. More considerations about descriptors
        1. Reusing code
        2. Avoiding 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. Summary
    6. References
  13. Using Generators
    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
          1. Repeated iterations
          2. Nested loops
      2. The iterator pattern in Python
        1. The interface for iteration
        2. Sequence objects as iterables
    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
          1. The simplest use of yield from
          2. Capturing the value returned by a sub-generator
          3. Sending and receiving data to and from a sub-generator
    5. Asynchronous programming
    6. Summary
    7. References
  14. 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. Frameworks and tools for testing
      1. Frameworks and libraries for unit testing
        1. unittest
          1. Parametrized tests
        2. pytest
          1. Basic test cases with pytest
          2. Parametrized tests
          3. Fixtures
      2. Code coverage
        1. Setting up rest coverage
        2. Caveats of test coverage
      3. Mock objects
        1. A fair warning about patching and mocks
        2. Using mock objects
          1. Types of mocks
          2. A use case for test doubles
    3. Refactoring
      1. Evolving our code
      2. Production code isn't the only thing that evolves
    4. More about unit testing
      1. Property-based testing
      2. Mutation testing
    5. A brief introduction to test-driven development
    6. Summary
    7. References
  15. Common Design Patterns
    1. Considerations for design patterns in Python
    2. Design patterns in action
      1. Creational patterns
        1. Factories
        2. Singleton and shared state (monostate)
          1. Shared state
          2. The borg pattern
        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. Names in our models
    5. Summary
    6. References
  16. Clean Architecture
    1. From clean code to clean architecture
      1. Separation of concerns
      2. Abstractions
    2. Software components
      1. Packages
      2. Containers
    3. Use case
      1. The code
        1. Domain models
        2. Calling from the application
        3. Adapters
      2. The services
      3. Analysis
        1. The dependency flow
        2. Limitations
        3. Testability
        4. Intention revealing
    4. Summary
    5. References
    6. Summing it all up
  17. Other Books You May Enjoy
    1. Leave a review - let other readers know what you think

Product information

  • Title: Clean Code in Python
  • Author(s): Mariano Anaya
  • Release date: August 2018
  • Publisher(s): Packt Publishing
  • ISBN: 9781788835831