Full Download (Ebook) Python Descriptors: Understanding and Using the Descriptor Protocol by Jacob Zimmerman ISBN 9781484237267, 1484237269 PDF DOCX
Full Download (Ebook) Python Descriptors: Understanding and Using the Descriptor Protocol by Jacob Zimmerman ISBN 9781484237267, 1484237269 PDF DOCX
com
https://ebooknice.com/product/python-descriptors-
understanding-and-using-the-descriptor-protocol-7210836
DOWLOAD EBOOK
ebooknice.com
https://ebooknice.com/product/python-descriptors-5684810
ebooknice.com
https://ebooknice.com/product/sip-understanding-the-session-
initiation-protocol-1378072
ebooknice.com
https://ebooknice.com/product/sip-understanding-the-session-
initiation-protocol-977908
ebooknice.com
(Ebook) Using Asyncio in Python: Understanding Python's
Asynchronous Programming Features by Caleb Hattingh ISBN
9781492075332, 1492075337, B084D653HW
https://ebooknice.com/product/using-asyncio-in-python-understanding-
python-s-asynchronous-programming-features-10698978
ebooknice.com
ebooknice.com
ebooknice.com
Python
Descriptors
Understanding and Using the
Descriptor Protocol
—
Second Edition
—
Jacob Zimmerman
Python Descriptors
Understanding and Using
the Descriptor Protocol
Second Edition
Jacob Zimmerman
Python Descriptors: Understanding and Using the Descriptor Protocol
Jacob Zimmerman
New York, USA
iii
Table of Contents
iv
Table of Contents
Chapter 9: Writing__delete__()�����������������������������������������������������������67
Summary������������������������������������������������������������������������������������������������������������68
v
Table of Contents
Bibliography���������������������������������������������������������������������������������������93
Index���������������������������������������������������������������������������������������������������95
vi
About the Author
Jacob Zimmerman is a blogger, gamer (tabletop more so than video
games), and programmer who was born and raised in Wisconsin. He has a
twin brother who could also be considered to have all those traits.
Jacob has his own programming blog that focuses on Java, Kotlin,
and Python programming, called “Programming Ideas with Jake”. He also
writes for a gaming blog with his brother-in-law called the “Ramblings of
Jacob and Delos”.
His brother writes a JavaScript blog called JoeZimJS and works with
his best friend on a gaming YouTube channel called “Bork & Zim Gaming,”
which Jacob helps out with on occasion.
Programming Ideas with Jake
http://programmingideaswithjake.wordpress.com/
Ramblings of Jacob and Delos
http://www.ramblingsofjacobanddelos.com/
JoeZimJS
http://www.joezimjs.com
vii
About the Technical Reviewer
Michael Thomas has worked in software development for more than 20
years as an individual contributor, team lead, program manager, and vice
president of engineering. Michael has more than 10 years of experience
working with mobile devices. His current focus is in the medical sector,
using mobile devices to accelerate information transfer between patients
and health care providers.
ix
Acknowledgments
In order to be sure that I got everything right—it would really suck for a
“comprehensive guide” to be missing a big chunk of functionality or to get
anything wrong—I enlisted the help of some Python experts on the first
edition. In return for their help, I let them introduce themselves to you
here. That’s not all I did in return, but it’s all you’re going to see :)
Emanuel Barry is a self-taught Python programmer who loves pushing
the language to its limits as well as exploring its darkest corners. He has to
do a lot of proofreading and editing for a local non-for-profit organization,
and decided to combine his love of Python and knowledge sharing with
his background in proofreading to help make this book even better. He can
often be found in the shadows of the mailing lists or the issue tracker, as
well as the Python IRC channel, as Vgr.
Chris Angelico has played around with Python since the late 90s, getting
more serious with the language in the mid 2000s. As a PEP Editor and active
participant in the various mailing lists, he keeps well up to date with what’s
new and upcoming in the language and also shares that knowledge with
fledgling students in the Thinkful tutoring/mentoring program. When not
coding in Python, he is often found wordsmithing for a Dungeons & Dragons
campaign, or exploring the linguistic delights of Alice in Wonderland and
similar works. If you find a subtle Alice reference in this text, blame him!
https://github.com/Rosuav
xi
Visit https://ebooknice.com to
discover a wide range of
eBooks across various genres.
Enjoy exclusive deals and
discounts to enhance your
reading experience. Start your
digital reading journey today!
Introduction
Python is a remarkable language with many surprisingly powerful features
baked into it. Generators, metaclasses, and decorators are some of those,
but this book is all about descriptors.
Code Samples
All code samples are written in Python 3, since that is the most recent
version, but all the ideas and principles taught in this book apply to Python
2 as well, as long as you’re using new style classes.
Note Superscript letters like the one at the end of the previous line
are in reference to the bibliography at the back of the book, which
includes URLs to the referenced site.
xiii
Introduction
xiv
PART I
About Descriptors
Part I is a deep explanation of what descriptors are, how they work, and
how they’re used. It gives enough information that you should be able to
look at any descriptor and understand how it works and why it works that
way, assuming the writer of the code made the code legible enough.
Creating your own descriptors isn’t difficult once you have the
information from Part I, but little to no guidance is given to help with
it. Instead, Part II covers that with a bunch of options for creating new
descriptors, as well as tips for avoiding common mistakes.
CHAPTER 1
What Is a Descriptor?
Put very simply, a descriptor is a class that can be used to call a method
with simple attribute access, but there’s obviously more to it than that. It’s
difficult to explain beyond that without digging a little into how descriptors
implemented. So, here’s a high-level view of the descriptor protocol.
A descriptor implements at least one of these three methods:
__get__(), __set__(), or __delete__(). Each of those methods has a list
of parameters needed, which will be discussed a little later, and each is
called by a different sort of access of the attribute the descriptor represents.
Doing simple a.x access will call the __get__() method of x; setting the
attribute using a.x = value will call the __set__() method of x; and using
del a.x will call, as expected, the __delete__() method of x.
4
Chapter 1 What Is a Descriptor?
Summary
As you have seen, descriptors occupy a large part of the Python language, as
they can replace attribute access with method calls, and even restrict which
types of attribute access is allowed. Now that you have a broad idea of how
descriptors are implemented as well as their use by the language, we will
dig a little deeper yet, gaining a better understanding of how they work.
5
CHAPTER 2
The Descriptor
Protocol
In order to get a better idea of what descriptors are good for, let’s finish
showing the full descriptor protocol. It’s time to see the full signatures of
the protocol’s methods and what the parameters are.
that it’s being called from the class level. But, if instance is not None, then it
tells the descriptor which instance it’s being called from. So an a.x call will
be effectively translated to type(a).__dict__['x'].__get__(a, type(a)).
Notice that it still receives the instance’s class. Notice also that the call still
starts with type(a), not just a, because descriptors are stored on classes.
In order to be able to apply per-instance as well as per-class functionality,
descriptors are given instance and owner (the class of the instance). How
this translation and application happens will be discussed later.
Remember—and this applies to __set__() and __delete__() as
well—self is an instance of the descriptor itself. It is not the instance that
the descriptor is being called from; the instance parameter is the instance
the descriptor is being called from. This may sound confusing at first, but
don’t worry if you don’t understand for now—everything will be explained
further.
The __get__() method is the only one that bothers to get the class
separately. That’s because it’s the only method on non-data descriptors,
which are generally made at a class level. The built-in decorator
classmethod is implemented using descriptors and the __get__()
method. In that case, it will use the owner parameter alone.
8
Chapter 2 The Descriptor Protocol
The last parameter is value, which is the value the attribute is being
assigned.
One thing to note: when setting an attribute that is currently a
descriptor from the class level, it will replace the descriptor with whatever
is being set. For example, A.x = someValue does not get translated to
anything; someValue replaces the descriptor object stored in x. To act on
the class, see the following note.
9
Chapter 2 The Descriptor Protocol
Summary
That’s the sum total of the descriptor protocol. Having a basic idea of how
it works, you’ll now get a high-level view of the types of things that can be
done with descriptors.
10
Visit https://ebooknice.com to
discover a wide range of
eBooks across various genres.
Enjoy exclusive deals and
discounts to enhance your
reading experience. Start your
digital reading journey today!
CHAPTER 3
E ncapsulation
One of the most useful aspects of descriptors is that they encapsulate
data so well. With descriptors, you can access an attribute the simple way
using attribute access notation (a.x) while having more complex actions
happen in the background. For example, a Circle class might have radius,
diameter, circumference, and area all available as if they were attributes,
but since they’re all linked, you only need to store one (we’ll use the radius
for the example) and calculate the others based on it. But from the outside,
they all look like attributes stored on the object.
Lazy Instantiation
You can use descriptors to define a really simple syntax for lazily
instantiating an attribute. There will be code provided for a nice lazy
attribute implementation later in the book.
In the Circle example, the non-radius attributes, after having their
caches invalidated, don’t need to calculate their values right away; they
could wait until they’re needed. That’s laziness.
Validation
Many descriptors are written simply to make sure that data being passed
in conforms to the class’ or attribute’s invariants. Such descriptors can
usually be designed as handy decorators, too.
Again with the Circle example: all of those attributes should be
positive, so all the descriptors could also make sure the value being set is
positive.
Triggering Actions
Descriptors can be used to trigger certain actions when the attribute is
accessed. For example, the observer pattern can be implemented in a
per-attribute sense to trigger calls to the observer whenever an attribute is
changed.
12
Chapter 3 What Are Descriptors Good For?
Last Circle example: all the “attributes” are based on the radius
calculated lazily. In order to keep from having to calculate them every
time, you could cache the result. Then, whenever one of them changes,
it could trigger invalidating all the others’ caches.
Encapsulation
Wait… encapsulation was a pro. How can it also be a con? The problem
is that you can hide incredible amounts of complexity behind something
that just looks like attribute use. With getters and setters, the user at least
sees that there’s a function being called, and plenty can happen in a single
function call. But the user won’t necessarily expect that what is seemingly
attribute access is causing something else to happen, too. Most of the time,
this isn’t a problem, but it can get in the user’s way of trying to debug any
problems, since clearly that code can’t be a problem.
13
Chapter 3 What Are Descriptors Good For?
Additional Objects
Because descriptors add another layer of indirection/abstraction to the
mix, they also add at least one additional object in memory, along with at
least one additional call stack level. In most cases, it’ll be more than one of
each. This adds bloat that could at least be partially mitigated using getters
and setters.
Summary
Descriptors are awesome, allowing for a variety of nice features that are
good at hiding their complexity from users of your code, but you should
definitely be aware that the power comes with cost.
14
CHAPTER 4
Descriptors in the
Standard Library
There are three basic, well-known descriptors that come with Python:
property, classmethod, and staticmethod. There’s also a fourth one that
you use all the time, but are less likely to know is a descriptor.
Of all the descriptors being shown in this chapter, it’s possible that
you only knew of property as a descriptor. Plenty of people even learn
the basics of descriptors from it, but a lot of people don’t know that
classmethod and staticmethod are descriptors. They feel like super
magical constructs built into the language that no one could reproduce in
pure Python. Once someone has an understanding of descriptors, though,
their basic implementation becomes relatively obvious. In fact, example
code will be provided for all three in simplified, pure Python code.
Lastly, it will be shown that all methods are actually implemented
with descriptors. Normal methods are actually done “magically,” since the
descriptor creation is implicit, but it’s still not entirely magical because it’s
done using a language construct the anyone could create.
What I find really interesting is that the first three are all function
decorators, which are another really awesome feature of Python that
deserves its own book, even though they’re way simpler.
class property:
def __init__(self, fget=None, fset=None, fdel=None):
self.fget = fget
self.fset = fset
self.fdel = fdel
16
Chapter 4 Descriptors in the Standard Library
As you can now see, the property class has almost no real functionality
of its own; it simply delegates to the functions given to it. When a function
is not provided for a certain method to delegate to, property assumes that
it is a forbidden action and raises an AttributeError with an appropriate
message.
A nice thing about the property class is that it largely just accepts
methods. Even its constructor, which can be given all three methods at
once, is capable of being called with just one, or even none. Because of
this, the constructor and other methods can be used as decorators in a
very convenient syntax. Check out the documentation2 to learn more
about it.
Omitted from this code example is the doc functionality, where it sets
its own __doc__ property based on what is passed in through __init__()’s
doc parameter or using __doc__ from fget if nothing is given. Also omitted
is the code that sets other attributes on property, such as __name__, in
order to help it appear even more like a simple attribute. They did not
seem important enough to worry about, since the focus was more on the
main functionality.
17
Chapter 4 Descriptors in the Standard Library
class classmethod:
def __init__(self, func):
self.func = func
18
Chapter 4 Descriptors in the Standard Library
class staticmethod:
def __init__(self, func):
self.func = func
Regular Methods
Remember that it was stated earlier that regular methods implicitly use
descriptors as well. In fact, all functions can be used as methods. This is
because functions are non-data descriptors as well as callables.
Here is a Python implementation that roughly shows how a function
looks.
class function:
def __call__(self, *args, **kwargs):
# do something
19
Exploring the Variety of Random
Documents with Different Content
INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.
Please check the Project Gutenberg web pages for current donation
methods and addresses. Donations are accepted in a number of
other ways including checks, online payments and credit card
donations. To donate, please visit: www.gutenberg.org/donate.
Most people start at our website which has the main PG search
facility: www.gutenberg.org.
Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.
ebooknice.com