Clean Code in Python
eBook - ePub

Clean Code in Python

Develop maintainable and efficient code, 2nd Edition

Mariano Anaya

Share book
  1. 422 pages
  2. English
  3. ePUB (mobile friendly)
  4. Available on iOS & Android
eBook - ePub

Clean Code in Python

Develop maintainable and efficient code, 2nd Edition

Mariano Anaya

Book details
Book preview
Table of contents

About This Book

Tackle inefficiencies and errors the Pythonic wayKey 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 techniquesBook DescriptionExperienced 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 cornerstoneWho this book is forThis 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

Frequently asked questions

How do I cancel my subscription?
Simply head over to the account section in settings and click on “Cancel Subscription” - it’s as simple as that. After you cancel, your membership will stay active for the remainder of the time you’ve paid for. Learn more here.
Can/how do I download books?
At the moment all of our mobile-responsive ePub books are available to download via the app. Most of our PDFs are also available to download and we're working on making the final remaining ones downloadable now. Learn more here.
What is the difference between the pricing plans?
Both plans give you full access to the library and all of Perlego’s features. The only differences are the price and subscription period: With the annual plan you’ll save around 30% compared to 12 months on the monthly plan.
What is Perlego?
We are an online textbook subscription service, where you can get access to an entire online library for less than the price of a single book per month. With over 1 million books across 1000+ topics, we’ve got you covered! Learn more here.
Do you support text-to-speech?
Look out for the read-aloud symbol on your next book to see if you can listen to it. The read-aloud tool reads text aloud for you, highlighting the text as it is being read. You can pause it, speed it up and slow it down. Learn more here.
Is Clean Code in Python an online PDF/ePUB?
Yes, you can access Clean Code in Python by Mariano Anaya in PDF and/or ePUB format, as well as other popular books in Computer Science & Programming in Python. We have over one million books available in our catalogue for you to explore.




Getting More Out of Our Objects with Descriptors

This chapter introduces a new concept that is more advanced in Python development since it features descriptors. Moreover, descriptors are not something programmers of other languages are familiar with, so there are no easy analogies or parallelisms to make.
Descriptors are another distinctive feature of Python that take object-oriented programming to another level, and their potential allows users to build more powerful and reusable abstractions. Most of the time, the full potential of descriptors is observed in libraries or frameworks.
In this chapter, we will achieve the following goals that relate to descriptors:
  • Understand what descriptors are, how they work, and how to implement them effectively
  • Analyze the two types of descriptors (data and non-data descriptors) in terms of their conceptual differences and implementation details
  • Reuse code effectively through descriptors
  • Analyze examples of good uses of descriptors, and how to take advantage of them for our API libraries

A first look at descriptors

First, we will explore the main idea behind descriptors to understand their mechanics and internal workings. Once this is clear, it will be easier to assimilate how the different types of descriptors work, which we will explore in the next section.
Once we have a general understanding of the idea behind descriptors, we will look at an example where their use gives us a cleaner and more Pythonic implementation.

The machinery behind descriptors

The way descriptors work is not all that complicated, but the problem with them is that there are a lot of caveats to take into consideration, so the implementation details are of the utmost importance here.
To implement descriptors, we need at least two classes. For this generic example, the client class will take advantage of the functionality we want to implement in the descriptor (this is generally just a domain model class, a regular abstraction we create for our solution), and the descriptor class will implement the logic of the descriptor itself.
A descriptor is, therefore, just an object that is an instance of a class that implements the descriptor protocol. This means that the interface of this class must contain at least one of the following magic methods (part of the descriptor protocol as of Python 3.6+):
  • __get__
  • __set__
  • __delete__
  • __set_name__
For the purposes of this initial high-level introduction, the following naming conventions will be used:
The domain-level abstraction that will take advantage of the functionality to be implemented by the descriptor. This class is said to be a client of the descriptor.
This class contains a class attribute (named descriptor by this convention), which is an instance of DescriptorClass.
The class that implements the descriptor itself. This class should implement some of the aforementioned magic methods that entail the descriptor protocol.
An instance of ClientClass.
client = ClientClass().
An instance of DescriptorClass.
descriptor = DescriptorClass().
This object is a class attribute that is placed in ClientClass.
Table 6.1: Descriptor naming conventions used in this chapter
This relationship is illustrated in Figure 6.1:
Picture 1
Figure 6.1: The relationship between ClientClass and DescriptorClass
A very important observation to keep in mind is that for this protocol to work, the descriptor object has to be defined as a class attribute. Creating this object as an instance attribute will not work, so it must be in the body of the class, and not in the __init__ method.
Always place the descriptor object as a class attribute!
On a slightly more critical note, readers can also note that it is possible to implement the descriptor protocol partially—not all methods must always be defined; instead, we can implement only those we need, as we will see shortly.
So, now we have the structure in place—we know what elements are set and how they interact. We need a class for the descriptor, another class that will consume the logic of the descriptor, which, in turn, will have a descriptor object (an instance of DescriptorClass) as a class attribute, and instances of ClientClass that will follow the descriptor protocol when we call for the attribute named descriptor. But now what? How does all of this fit into place at runtime?
Normally, when we have a regular class and we access its attributes, we simply obtain the objects as we expect them, and even their properties, as in the following example:
>>> class Attribute: ... value = 42 ... >>> class Client: ... attribute = Attribute() ... >>> Client().attribute <__main__.Attribute object at 0x...> >>> Client().attribute.value 42 
But, in the case of descriptors, something different happens. When an object is defined as a class attribute (and this one is a descriptor), when a client requests this attribute, instead of getting the object itself (as we would expect from the previous example), we get the result of having called the __get__ magic method.
Let's start with some simple code that only logs information about the context, and returns the same client object:
class DescriptorClass: def __get__(self, instance, owner): if instance is None: return self "Call: %s.__get__(%r, %r)", self.__class__.__name__, instance, owner ) return instance class ClientClass: descriptor = Descriptor...

Table of contents