100% found this document useful (1 vote)
6 views

Python Descriptors: Understanding and Using the Descriptor Protocol 1st Edition Jacob Zimmerman download

The document is a comprehensive guide to Python descriptors, detailing the descriptor protocol and its applications in Python programming. It covers the methods involved in creating and using descriptors, their advantages and disadvantages, and provides examples and use cases. Additionally, it includes information about the author and technical reviewers, acknowledgments, and references for further reading.

Uploaded by

peacobeauxn6
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
6 views

Python Descriptors: Understanding and Using the Descriptor Protocol 1st Edition Jacob Zimmerman download

The document is a comprehensive guide to Python descriptors, detailing the descriptor protocol and its applications in Python programming. It covers the methods involved in creating and using descriptors, their advantages and disadvantages, and provides examples and use cases. Additionally, it includes information about the author and technical reviewers, acknowledgments, and references for further reading.

Uploaded by

peacobeauxn6
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 58

Python Descriptors: Understanding and Using the

Descriptor Protocol 1st Edition Jacob Zimmerman


download

https://textbookfull.com/product/python-descriptors-
understanding-and-using-the-descriptor-protocol-1st-edition-
jacob-zimmerman/

Download more ebook from https://textbookfull.com


We believe these products will be a great fit for you. Click
the link to download now, or visit textbookfull.com
to discover even more!

Python Descriptors 1st Edition Jacob Zimmerman

https://textbookfull.com/product/python-descriptors-1st-edition-
jacob-zimmerman/

Using Asyncio in Python Understanding Python s


Asynchronous Programming Features Caleb Hattingh

https://textbookfull.com/product/using-asyncio-in-python-
understanding-python-s-asynchronous-programming-features-caleb-
hattingh/

Introduction to Computation and Programming Using


Python with Application to Understanding Data Guttag

https://textbookfull.com/product/introduction-to-computation-and-
programming-using-python-with-application-to-understanding-data-
guttag/

Introduction to Computation and Programming Using


Python With Application to Understanding Data Second
Edition John V. Guttag

https://textbookfull.com/product/introduction-to-computation-and-
programming-using-python-with-application-to-understanding-data-
second-edition-john-v-guttag/
Supervised Learning with Python Concepts and Practical
Implementation Using Python 1st Edition Vaibhav Verdhan

https://textbookfull.com/product/supervised-learning-with-python-
concepts-and-practical-implementation-using-python-1st-edition-
vaibhav-verdhan/

Supervised Learning with Python: Concepts and Practical


Implementation Using Python Vaibhav Verdhan

https://textbookfull.com/product/supervised-learning-with-python-
concepts-and-practical-implementation-using-python-vaibhav-
verdhan/

Chemical and Biomedical Engineering Calculations Using


Python 1st Edition Jeffrey J. Heys

https://textbookfull.com/product/chemical-and-biomedical-
engineering-calculations-using-python-1st-edition-jeffrey-j-heys/

Computational Nuclear Engineering and Radiological


Science Using Python 1st Edition Ryan Mcclarren

https://textbookfull.com/product/computational-nuclear-
engineering-and-radiological-science-using-python-1st-edition-
ryan-mcclarren/

Introduction To Computing And Problem Solving Using


Python 1st Edition E. Balaguruswamy

https://textbookfull.com/product/introduction-to-computing-and-
problem-solving-using-python-1st-edition-e-balaguruswamy/
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

ISBN-13 (pbk): 978-1-4842-3726-7 ISBN-13 (electronic): 978-1-4842-3727-4


https://doi.org/10.1007/978-1-4842-3727-4
Library of Congress Control Number: 2018960194
Copyright © 2018 by Jacob Zimmerman
This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or
part of the material is concerned, specifically the rights of translation, reprinting, reuse of
illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way,
and transmission or information storage and retrieval, electronic adaptation, computer software,
or by similar or dissimilar methodology now known or hereafter developed.
Trademarked names, logos, and images may appear in this book. Rather than use a trademark
symbol with every occurrence of a trademarked name, logo, or image we use the names, logos,
and images only in an editorial fashion and to the benefit of the trademark owner, with no
intention of infringement of the trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if
they are not identified as such, is not to be taken as an expression of opinion as to whether or not
they are subject to proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of
publication, neither the authors nor the editors nor the publisher can accept any legal
responsibility for any errors or omissions that may be made. The publisher makes no warranty,
express or implied, with respect to the material contained herein.
Managing Director, Apress Media LLC: Welmoed Spahr
Acquisitions Editor: Steve Anglin
Development Editor: Matthew Moodie
Coordinating Editor: Mark Powers
Cover designed by eStudioCalamar
Cover image designed by Freepik (www.freepik.com)
Distributed to the book trade worldwide by Springer Science+Business Media New York, 233
Spring Street, 6th Floor, New York, NY 10013. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail
orders-ny@springer-sbm.com, or visit www.springeronline.com. Apress Media, LLC is a
California LLC and the sole member (owner) is Springer Science + Business Media Finance Inc
(SSBM Finance Inc). SSBM Finance Inc is a Delaware corporation.
For information on translations, please e-mail editorial@apress.com; for reprint, paperback, or
audio rights, please email bookpermissions@springernature.com.
Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook
versions and licenses are also available for most titles. For more information, reference our Print
and eBook Bulk Sales web page at http://www.apress.com/bulk-sales.
Any source code or other supplementary material referenced by the author in this book is
available to readers on GitHub via the book’s product page, located at www.apress.com/
9781484237267. For more detailed information, please visit http://www.apress.com/
source-code.
Printed on acid-free paper
Table of Contents
About the Author��������������������������������������������������������������������������������vii

About the Technical Reviewer�������������������������������������������������������������ix


Acknowledgments�������������������������������������������������������������������������������xi
Introduction���������������������������������������������������������������������������������������xiii

Part I: About Descriptors�������������������������������������������������������������1


Chapter 1: What Is a Descriptor?����������������������������������������������������������3
Data Descriptors versus Non-Data Descriptors����������������������������������������������������4
The Use of Descriptors by Python�������������������������������������������������������������������������4
Summary��������������������������������������������������������������������������������������������������������������5

Chapter 2: The Descriptor Protocol������������������������������������������������������7


The __get__(self, instance, owner) Method����������������������������������������������������������7
The __set__(self, instance, value) Method��������������������������������������������������������� 8
The __delete__(self, instance) Method�����������������������������������������������������������������9
Summary������������������������������������������������������������������������������������������������������������10

Chapter 3: What Are Descriptors Good For?���������������������������������������11


Pros of Python Descriptors���������������������������������������������������������������������������������11
Encapsulation������������������������������������������������������������������������������������������������11
Reuse of Read/Write Patterns�����������������������������������������������������������������������12
Writing for the Class Level�����������������������������������������������������������������������������13

iii
Table of Contents

Cons of Python Descriptors���������������������������������������������������������������������������������13


Encapsulation������������������������������������������������������������������������������������������������13
Can Be Difficult To Write��������������������������������������������������������������������������������14
Additional Objects�����������������������������������������������������������������������������������������14
Summary������������������������������������������������������������������������������������������������������������14

Chapter 4: Descriptors in the Standard Library����������������������������������15


The property Class����������������������������������������������������������������������������������������������16
The classmethod Descriptor�������������������������������������������������������������������������������18
The staticmethod Descriptor�������������������������������������������������������������������������������19
Regular Methods�������������������������������������������������������������������������������������������������19
Summary������������������������������������������������������������������������������������������������������������20

Chapter 5: Attribute Access and Descriptors�������������������������������������21


Instance Access��������������������������������������������������������������������������������������������������22
Set and Delete Calls��������������������������������������������������������������������������������������������27
The Reasoning Behind Data versus Non-Data Descriptors��������������������������������28
Summary������������������������������������������������������������������������������������������������������������28

Part II: Making Descriptors�������������������������������������������������������29


Chapter 6: Which Methods Are Needed?��������������������������������������������31
When __get__() Is Called Without an instance Argument����������������������������������32
Raise Exception or Return self����������������������������������������������������������������������32
“Unbound” Attributes������������������������������������������������������������������������������������33
Summary������������������������������������������������������������������������������������������������������������37

Chapter 7: Storing the Attributes�������������������������������������������������������39


Class-Level Storage��������������������������������������������������������������������������������������������39
Storing Data on the Descriptor����������������������������������������������������������������������������40
Storing on the Instance Dictionary����������������������������������������������������������������46

iv
Table of Contents

Asking for the Location����������������������������������������������������������������������������������48


Indirectly Asking for the Location�����������������������������������������������������������������������50
Name Mangling���������������������������������������������������������������������������������������������51
Store the Original and the Mangled���������������������������������������������������������������54
Summary������������������������������������������������������������������������������������������������������������57

Chapter 8: Read-Only Descriptors������������������������������������������������������59


Set-Once Descriptors������������������������������������������������������������������������������������������60
Secret-Set Descriptors����������������������������������������������������������������������������������������61
Forced-Set Descriptors���������������������������������������������������������������������������������������62
Class Constants��������������������������������������������������������������������������������������������������63
Summary������������������������������������������������������������������������������������������������������������65

Chapter 9: Writing__delete__()�����������������������������������������������������������67
Summary������������������������������������������������������������������������������������������������������������68

Chapter 10: Descriptors Are Classes Too��������������������������������������������69


Inheritance����������������������������������������������������������������������������������������������������������69
More Methods�����������������������������������������������������������������������������������������������������70
Optional/Default Parameters�������������������������������������������������������������������������������70
Descriptors on Descriptors���������������������������������������������������������������������������������70
Passing an Instance Around��������������������������������������������������������������������������������71
Descriptors Just Abstract Method Calls��������������������������������������������������������������72
Summary������������������������������������������������������������������������������������������������������������72

Chapter 11: Reusing the Wheel����������������������������������������������������������73


Storage Solutions������������������������������������������������������������������������������������������������73
Read-Only Solutions��������������������������������������������������������������������������������������������76
Simple Unbound Attributes���������������������������������������������������������������������������������78
Summary������������������������������������������������������������������������������������������������������������80

v
Table of Contents

Chapter 12: Instance-Level Descriptors���������������������������������������������81


Properties in Other Languages���������������������������������������������������������������������������81
Back to Python����������������������������������������������������������������������������������������������������82
Attempt 1�������������������������������������������������������������������������������������������������������82
Attempt 2�������������������������������������������������������������������������������������������������������83
Attempt 3�������������������������������������������������������������������������������������������������������85
Attempt 4�������������������������������������������������������������������������������������������������������85
Example��������������������������������������������������������������������������������������������������������������87
Go Nuts���������������������������������������������������������������������������������������������������������������88

Chapter 13: Other Uses of Descriptors In the World���������������������������89


SQLAlchemy��������������������������������������������������������������������������������������������������������89
Jigna�������������������������������������������������������������������������������������������������������������������90
Elk�����������������������������������������������������������������������������������������������������������������������90
Validators������������������������������������������������������������������������������������������������������������91
Summary������������������������������������������������������������������������������������������������������������91

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

Kevin Mackay is a software engineer who has been programming in


Python since 2010 and is currently working at BBC, improving the Taster
platform. He is enthusiastic about open source software and occasionally
contributes to the 3D graphics application, Blender. He can be found on the
Python IRC channel as yakca or hiking on a mountain somewhere in Scotland.

xi
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.

The Descriptor Tools Library


Written alongside this book was a library, called descriptor-tools, which
can be installed with pip. It contains the fruition of a lot of the ideas and
helpers to make it easier to implement them all. It’s an open source project
with a public GitHub repository.1

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

Conventions in This Book


When the text mentions “class” and “instance” in a general sense, they
refer to a class that has a descriptor attribute and to instances of such
classes, respectively. All other classes and instances will be referred to
more specifically.

New in the 2nd Edition


The 2nd edition is an update including new features of Python as well as
new ideas to learn. One of the new things is incredibly important if this
book wants to maintain the status of “comprehensive” guide that it strives
for. This important addition is about the addition of __set_name__() to the
descriptor protocol in Python 3.6. You can read about this in Chapter 7,
“Storing the Attributes”.
Another addition is an idea that was inspired by looking into the
__set_name__() addition to the protocol, which you’ll see just after the
section on that addition. Also, I added a chapter on creating instance-level
descriptors, which were added to descriptor-tools well before this edition
really got started.
The next thing is actually a change, not an addition. Since writing
the first book, I found out about the built-in function vars(). Calling
vars(obj) is equivalent to obj.__dict__, but is more Pythonic. Kind of
like calling len(obj) instead of obj.__len__(). So the code examples
have been updated to use vars(). Any remaining references to __dict__
are purposeful.
Pretty much everything else new in this edition is just cleaning up the
language to be more legible.

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.

Note Since version 3.6, there’s another method that descriptors


can take advantage of, called __set_name__(), but using just
that method doesn’t make it a descriptor the way any of the other
three will. This method will be mostly ignored for a while, since it
doesn’t have as big a role into how descriptors work. It will only be
mentioned where most relevant.

As stated, only one of the methods needs to be implemented in


order to be considered a descriptor, but any number of them can be
implemented. And, depending on descriptor type and on which methods

© Jacob Zimmerman 2018 3


J. Zimmerman, Python Descriptors, https://doi.org/10.1007/978-1-4842-3727-4_1
Chapter 1 What Is a Descriptor?

are implemented, not implementing certain methods can restrict certain


types of attribute access or provide interesting alternative behaviors for
them. There are two types of descriptors based on which sets of these
methods are implemented: data and non-data.

 ata Descriptors versus Non-Data


D
Descriptors
A data descriptor implements at least __set__() or __delete__(), but
can include both. Data descriptors also often include __get__() since it’s
rare to want to set something without also being able to get it too. You can
get the value, even if the descriptor doesn’t include __get__(), but it’s
either roundabout or the descriptor writes it to the instance. That will be
discussed more later.
A non-data descriptor only implements __get__(). If it adds a __set__()
or __delete__() method, it becomes a data descriptor.
Unfortunately, the PyPy interpreter (up to version 2.4.0) gets this a little
bit wrong. It doesn’t take __delete__() into consideration until it knows
that it’s a data descriptor, and PyPy doesn’t believe something is a data
descriptor unless __set__() is implemented. Luckily, since a huge majority
of data descriptors implement __set__(), this rarely becomes a problem.
It may seem like the distinction is pointless, but it is not. It comes into
play upon attribute lookup. This will be discussed more later, but basically,
the distinction is the types of uses it provides.

The Use of Descriptors by Python


It is worth noting that descriptors are an inherent part of how Python
works. Python is known to be a multi-paradigm language, and as such
supports paradigms such as functional programming, imperative

4
Chapter 1 What Is a Descriptor?

programming, and object-oriented programming. This book does not


attempt to go into depth about the different paradigms; only the object-­
oriented programming paradigm will be observed. Descriptors are used
implicitly in Python for the language’s object-oriented mechanisms. As will
be explained shortly, methods are implemented using descriptors. As you
may guess from reading this, it is thanks to descriptors that object-oriented
programming is possible in Python. Descriptors are very powerful and
advanced, and this book aims to teach Python programmers how to use
them fully.

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.

The __get__(self, instance, owner) Method


This method is clearly the method for retrieving whatever data or object the
descriptor is meant to maintain. Obviously, self is a parameter, since it’s a
method. Also, it receives instance and/or owner. We’ll start with owner.
owner is the class that the descriptor is accessed from, or else the
class of the instance it’s being accessed from. When you make the call
A.x (A being a class), and x is a descriptor object with __get__(), it’s called
with an owner with the instance set to None. So the lookup gets effectively
transformed into A.__dict__['x'].__get__(None, A). This lets the
descriptor know that __get__() is being called from a class, not an instance.
owner is also often written to have a default value of None, but that’s largely
an optimization that only built-in descriptors take advantage of.
Now, onto the last parameters. instance is the instance that the
descriptor is being accessed from, if it is being accessed from an instance.
As previously stated, if None is passed into instance, the descriptor knows

© Jacob Zimmerman 2018 7


J. Zimmerman, Python Descriptors, https://doi.org/10.1007/978-1-4842-3727-4_2
Chapter 2 The Descriptor Protocol

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.

The __set__(self, instance, value) Method


As mentioned, __set__() does not have an owner parameter that accepts
a class. __set__() does not need it, since data descriptors are generally
designed for storing per-instance data. Even if the data is being stored on a
per-class level, it should be stored internally without needing to reference
the class.
self should be self-explanatory now; the next parameter is instance.
This is the same as it is in the __get__() method. In this case, though,
your initial call is a.x = someValue, which is then translated into
type(a).__dict__['x'].__set__(a, someValue).

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.

The __delete__(self, instance) Method


After having learned about the __get__() and __set__() methods,
__delete__() should be easy to figure out. self and instance are the
same as in the other methods, but this method is invoked when del a.x is
called and is translated to type(a).__dict__['x'].__delete__(a).
Do not accidentally name it __del__(), as that won’t work as intended.
__del__() would be the destructor of the descriptor instance, not of the
attribute stored within.
It must be noted that, again, that __delete__() does not work from the
class level, just like __set__(). Using del from the class level will remove
the descriptor from the class’ dictionary rather than calling the descriptor’s
__delete__() method.

Note If you want a descriptor’s __set__() or __delete__()


methods to work from the class level, that means that the descriptor
must be created on the class’ metaclass. When doing so, everything
that refers to owner is referring to the metaclass, while a reference
to instance refers to the class. After all, classes are just instances
of metaclasses. The section on metadescriptors will explain that in
greater detail.

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
CHAPTER 3

What Are Descriptors


Good For?
Nothing is perfect in this world, and Python’s descriptors are no exception.
Descriptors allow you to do some pretty cool things, but those cool things
come at a cost. Here, we discuss the good and the bad.

Pros of Python Descriptors


Obviously we’re going to go over the good things about descriptors.
Would there be an entire book about them if they couldn’t be considered a
good thing?

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.

© Jacob Zimmerman 2018 11


J. Zimmerman, Python Descriptors, https://doi.org/10.1007/978-1-4842-3727-4_3
Chapter 3 What Are Descriptors Good For?

Reuse of Read/Write Patterns


Using specialized descriptors, you can reuse code that you used with
reading and/or writing of attributes. These can be used for repetitious
attributes within the same class or attribute types shared by other classes
as well. Some examples of reusable patterns are described in the following
sections.

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.

Writing for the Class Level


Because descriptors are stored at the class scope instead of the instance
scope, it allows you to do more robust things at the class level. For instance,
descriptors make classmethod and staticmethod work, which will be
explained in the next chapter.

Cons of Python Descriptors


As great as descriptors are, they come at a cost, just like just about
everything else in programming.

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?

Can Be Difficult To Write


It can be easy for the mind to get all twisted up when it comes to thinking
about the fact that descriptors are stored at the class level, but are usually
for dealing with attributes at the instance level. Besides that, there are
a lot of considerations and common pitfalls to deal with when deciding
how to save the represented attribute, whether you decide to do it on the
descriptor or on the the object that the attribute is for. The descriptor-tools
library was created specifically because of this.

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.

© Jacob Zimmerman 2018 15


J. Zimmerman, Python Descriptors, https://doi.org/10.1007/978-1-4842-3727-4_4
Chapter 4 Descriptors in the Standard Library

The property Class


This book doesn’t include instructions for how to use the property class
and decorator; it is focused on understanding and creating descriptors.
The official documentation for using property can be found in Python’s
documentation2.
Of all the descriptors out there, property is likely the most versatile.
This is because it doesn’t really do anything on its own, but rather allows
the users to inject their wanted functionality into it by providing their own
getters, setters, and deleters.
To get a better idea of how it works, here is a simplified pure Python
implementation of property.

class property:
    def __init__(self, fget=None, fset=None, fdel=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel

    def __get__(self, instance, owner):


        if instance is None:
            return self
        elif self.fget is None:
            raise AttributeError("unreadable attribute")
        else:
            return self.fget(instance)

    def __set__(self, instance, value):


        if self.fset is None:
            raise AttributeError("can't set attribute")
        else:
            self.fset(instance, value)

16
Chapter 4 Descriptors in the Standard Library

    def __delete__(self, instance):


        if self.fdel is None:
            raise AttributeError("can't delete attribute")
        else:
            self.fdel(instance)

    def getter(self, fget):


        return type(self)(fget, self.fset, self.fdel)

    def setter(self, fset):


        return type(self)(self.fget, fset, self.fdel)

    def deleter(self, fdel):


        return type(self)(self.fget, self.fset, fdel)

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

The classmethod Descriptor


classmethod is another descriptor that can be used as a decorator, but,
unlike property, there’s no good reason not to use it as one. classmethod
is an interesting concept that doesn’t exist in many other languages
(if any). Python’s type system, which uses classes as objects, makes
classmethods easy and worthwhile to make.
Here’s the Python code for classmethod.

class classmethod:
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, owner):


        return functools.partial(self.func, owner)

That’s all there is to it. classmethod is a non-data descriptor, so it only


implements __get__(). This __get__() method completely ignores the
instance parameter because, as “class” in the name implies, the method
has nothing to do with an instance of the class and only deals with the
class itself. What’s really nice is the fact that this can still be called from an
instance without any issues.
Why does the __get__() method return a functools.partial object
with the owner passed in, though? To understand this, think about the
parameter list of a function marked as a classmethod. The first parameter
is the class parameter, usually named cls. This class parameter is filled in
the call to partial so that the returned function can be called with just the
arguments the user wants to explicitly provide. The true implementation
doesn’t use partial, but works similarly.
Again, the code that sets __name__, __doc__, etc. is omitted to show
only how the main functionality works.

18
Chapter 4 Descriptors in the Standard Library

The staticmethod Descriptor


A method marked with staticmethod is strange in that it’s a method that
is really just a function, but it is “attached” to a class. Being part of the class
doesn’t do anything other than show users that it is associated with that
class and giving it a more specific namespace. Also, interestingly, because
staticmethod and classmethod are implemented using descriptors,
they’re inherited by subclasses.
The implementation of staticmethod is even simpler than that of
classmethod; it just accepts a function and then returns it when __get__()
is called.

class staticmethod:
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, owner):


        return self.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
Other documents randomly have
different content
Madge gasped. That the creature was mad, at the best, she made
no doubt. But that conviction, in the present situation, was of small
assistance. What was she to do?

As she asked herself this question, with no slight sense of


helplessness, the gate clicked behind her. Some one entered the
garden.

It was Bruce Graham.


CHAPTER XI
UNDER THE SPELL

"Mr. Graham!" she exclaimed. "Really, I do believe that if I had


been asked what thing I most desired at this particular moment, I
should have answered--you!"

Graham's sombre features were chastened by a smile.

"That's very good of you."

"Look here!" Laying one hand against his arm, with the other she
pointed at the sitting-room window. His glance followed her finger-
tips.

"Who's that?"

"That's what I should very much like to ascertain."

"I don't quite follow you. Do you mean that you don't know who
she is?"

"I only know that I've been away all day, and that on my return I
find her there. How she got there I can't say--but she seems
determined to keep me out."

"You don't mean that! And have you no notion who the woman
is? She looks half mad."
"I should think she must be quite mad. It's the woman who
forced herself into the house the day before yesterday after you had
gone--that's all I know of her. This time she is not alone; she has a
man in there with her."

"A man! Not--Ballingall?"

"No, not Ballingall. At least, I only caught a glimpse of him--but


it's not the man who was watching you. From her behaviour the
woman must be perfectly insane."

"We'll soon make an end of her, insane or not."

Graham went to the window. The woman, completely unabashed,


had remained right in front of it, an observant spectator of their
proceedings. He spoke to her.

"Open the door at once!"

She repeated the gesture she had used to Madge--raising her


voice, at the same time, to a shrill scream.

"Go away! go away! This house is mine--mine! I don't want any


trespassers here."

Graham turned to Madge.

"Do you authorise me to gain an entry?"

"Certainly. I don't want to spend the night out here."

Permission was no sooner given than the thing was done.


Grasping the upper sash of the window with both his hands, Graham
brought it down with a run, tearing away the hasp from its fastening
as if it had been so much thread. It was a capital object-lesson of
the utility of such a safeguard against the wiles of a muscular
burglar. The upper sash being lowered, in another moment the lower
one was raised. Mr. Graham was in the room. The woman was
possibly too astonished by the unceremonious nature of his
proceedings to attempt any resistance, even had she felt disposed.

Graham addressed Miss Brodie through the window.

"Will you come this way? or shall I open the door?"

"If you wouldn't mind, I'd rather you opened the door."

He opened the door. Presently they were in the sitting-room, face


to face with the intruders. Graham took them to task--the woman
evincing no sign of discomposure.

"Who are you, and what is the meaning of your presence on


these premises?"

"This house is mine--mine! It's all of it mine! And who are you,
that you ask such a question--of a lady?"

She crossed her hands on her breast with an assumption of


dignity which, in a woman of her figure and scarecrow-like
appearance, was sufficiently ludicrous. Graham eyed her as if
subjecting her to a mental appraisement. Then he turned to the
man.

"And pray, sir, what explanation have you to offer of the felony
you are committing?"

This man was a little, undergrown fellow, with sharp hatchet-


shaped features, and bent and shrunken figure. He had on an old
grey suit of clothes, which was three or four sizes too large for him,
the trousers being turned up in a thick roll over the top of an oft-
patched pair of side-spring boots. There was about him none of the
assurance which marked the woman--the air of bravado which he
attempted to wear fitted him as ill as his garments.
"I ain't committed no felony, not likely. She asked me to come to
her house--so I come. She says to me, 'You come along o' me to my
house, and I'll give you a bit of something to eat.' Now didn't you?"

"Certainly. I suppose a gentleman is allowed to visit a lady if she


asks him."

The dreadful-looking woman, as she stood with her head thrown


back, and her nose in the air, presented a picture of something
which was meant for condescension, which was not without its
pathos.

"Of course!--ain't that what I'm saying? She come here, and she
took a key out of her pocket, and she put it in the keyhole, and she
opened the door, all quite regular, and she says, 'This here's my
house,' and she asked me to come in, so of course I come in."

"Do you mean to say that she gained entrance to this house by
means of a key which she took from her pocket?"

"Course! How do you suppose we came in?--through the window?


Not hardly, that's not my line, and so I tell you."

Graham returned to the woman.

"Be so good as to give me the key with which you obtained


admission to these premises."

The woman put her hand up to her neck, for the first time
showing signs of discomposure.

"The key?"

Starting back, she looked about her wildly, and broke into a series
of shrill exclamations.
"The key!--my key!--no!--no!--no!--It is all I have left--the only
thing I've got. I've kept it through everything--I've never parted from
it once. I won't give it you--no!"

She came closer to him; glaring at him with terrible eyes.

"It's my key--mine! I took it with me when I went that night. He


was sitting in here, and I came downstairs with the key in my
pocket, and I went--and he never knew. And I've kept it ever since,
because I've always said that one day when I went back I should
want my key to let me in: I hate to have to stand on the step while
they are letting me in."

Mr. Graham was regarding her intently, as if he was endeavouring


to read what stood with her in the place of a soul.

"Is your name Ossington?"

"Ossington? Ossington?" She touched the sides of her forehead


with the tips of her fingers, glancing about her affrightedly, as if
making an effort to recall her surroundings. Her voice dropped to a
whisper. "Who said Ossington? Who said it? Who asked if my name
was--Ossington?"

Mr. Graham addressed Miss Brodie.

"With your permission I should like to speak to this woman--after


the man has gone."

In his last words there was meaning.

"By all means, if you wish it. Get rid of him at once. At the best
the fellow is an impudent intruder, and the story he tells is a
ridiculously lame one. He must have been perfectly well aware that a
woman of this sort was not likely to possess a house of her own,
and that accepting what he calls her invitation he was committing
felony."
The fellow in question shook his head as if he felt himself ill-used.

"I call that hard--cruel hard. If the young lady was to think of it
for half a moment she'd see as it was cruel hard."

"The young lady declines to think of it. Have the goodness to take
yourself away, and consider yourself lucky that you are allowed to
escape scot free."

The man moved towards the door, endeavouring to bear himself


as if he were doing so of his own free will. He spoke to the woman.

"Ain't you coming with me?"

"Yes, I'm coming."

She hastened towards him. Graham interposed.

"Let him go. There are one or two things about which we should
like to speak to you, this young lady and I, after he has gone."

But she would have none of him. Shrinking back, she stared at
him, in silence, for a second or two; then began to shriek at him like
some wild creature.

"I won't stay!--I won't!--I shall go!--I shall! You tried to get my
key--my key! You touch it--you dare! You asked me if my name"--
she stopped, stared about as if in terror, gave a great sigh, "You
asked me if my name----"

She stopped again--and sighed again, the pupils of her eyes


dilating as she watched and listened for what was invisible and
inaudible to all but her. Graham moved forward, intending to soothe
her. Mistaking, apparently, his intention, she rushed at him with
outstretched arms, giving utterance to yell after yell. In a moment
she was past him and flying from the house.
Her male companion, who stood still in the doorway, pointed his
thumb over his shoulder with a grin.

"There you are, you see--drove her out of her seven senses! So
you have."

Much more leisurely, the man went after the woman.

For some reason, when Mr. Bruce Graham and Miss Brodie were
left alone, nothing was said about the recent visitors.

"If you'll sit down and wait," remarked Miss Brodie, "I'll go and
take my things off."

Having returned from performing those sacred offices, the topic


still remained untouched. Possibly that was because there were so
many things which needed doing. When one has been out all day,
and keeps no maid, when one returns there are things which must
be done. For instance, there was a fire to make. Miss Brodie
observed that there ought to have been two, one in the kitchen, and
one in the sitting-room; but declared that folks would have to be
content with one.

And that one Bruce Graham made.

She brought in the wood, and the coal, and the paper; and then
she went to fetch the matches. When she returned she caught him
in the act.

"What are you doing?" she demanded.

He was on his knees on the hearthrug, with some sticks in his


hand.

"Making a fire--on scientific principles. I'm a scientific expert at


this kind of thing. Women's methods are unscientific as a rule."
"Indeed." Her air was scornful. "Men always think they can make
fires. It's most surprising."

She commented on his methods--particularly when he took the


pieces of coal from the scuttle, and placed them in their places with
his fingers.

"That's right! Men always use their fingers to put coal on the fire--
if they can. It's an agreeable habit."

He continued calm.

"It's scientific, strictly scientific; and may be logically defended,


especially when a fire is being lighted. Heaping on coal with a shovel
is unscientific--in the highest degree."

He struck a match; presently the paper was in flames.

"Now you had better go and wash your hands. You'll have to do it
in the scullery; and by the time you're done, the fire will be out."

But the fire was not out. It was a complete success. The kettle
was put on, preparations were made for tea, and the table was laid,
Graham showing a talent for rendering assistance which was not
accorded the thanks it might have been. Madge was chilly.

"I should imagine you were rather a handy person to have about
the house."

"There are diversities of gifts; let us hope that each of us has at


least one."

"Exactly. But, unfortunately, I do not care to see a man, what is


called, 'making himself useful about the house'--if your gift lies in
that direction. I suppose it is because I am not enough of a New
Woman. Perhaps now you've given me your assistance in laying the
cloth, you will give me some music."
He was smoothing a corner of the cloth in question--and looked
down.

"It is you who are the teacher."

She flashed up at him.

"What do you mean by that?"

"It is true--is it not?"

"If you wish me to understand that you would rather not play,
have the goodness to say so plainly."

Whereupon he sat down--and played. And Madge listened.

When he stopped, she was looking away from him, toward the
fire. Tears were in her eyes.

"I suppose you are a genius?"

Her voice seemed a little strained. He shook his head.

"No--the music comes out of the ends of my fingers."

He went on playing. When he ceased, again she turned to him--


with passionate eyes.

"I never heard any one play like you before."

"It's because I'm in the mood."

He played on. It seemed to her that he spoke to her out of the


soul of music. She sat still and listened. Her heart-strings tightened,
her pulses throbbed, her cheeks burned; every nerve in her frame
was on the alert. Never had such things been said to her before. She
could have cried--and would have cried, if she had dared. The
message breathed to her by Bruce Graham's playing told of a world
of which she, unconsciously, had dreamed.

He played; and she sat and listened, in the firelight, till Ella came
home to tea.

And with Ella came Jack Martyn.


CHAPTER XII
TOM OSSINGTON'S LAWYER

It was while they were seated at table that Bruce Graham told
them of the result of his investigations. Although, for some reason,
the subject had not been mentioned when Madge and he had been
alone together, that young lady showed herself alert and eager
enough then. Nor, in that respect, was Ella behind her friend, while
Martyn concealed an interest which was probably equal to theirs
under ponderous attempts at jocularity.

It was Jack who brought him to the point.

"If the honourable and learned gentleman has sufficiently


refreshed himself with the cup that cheers, would he oblige the
company by mentioning if he has done anything in the matter of the
Hidden Treasure--with capitals please!--and, if so, what?"

"I have at least found that everything points to there being such a
hidden treasure--in spite of Jack's pretended scepticism."

"My pretended scepticism! Sir, I would have you know that I am


no sceptic; or, if I am, never was one more willing to be converted to
the faith."

Ella interposed.

"And, Mr. Graham, you really think there is a hidden treasure?"

"I think it extremely probable."


"Tell us all about it. What have you been doing? All day long I
have been dreaming in the City of what would happen if we did light
upon a secret hoard. It really would be too splendid for words."

The young lady looked the eagerness which the words suggested-
-like an imaginative child who pictures the materialisation of some
favourite tale of faerie.

"To begin with, I went to the house agents to learn for whom
they are acting."

"Well, and what did they say?"

"They were not particularly willing to say anything--as I expected.


They were apparently under the impression that I intended to take
the bread out of their mouths, by dealing with their principals direct.
But when I had succeeded in, at any rate, partly reassuring them,
they informed me they were acting for a firm of solicitors--Messrs.
Nicholls & Hawkins, 3, South Square, Gray's Inn."

"Well, and what did you do then?"

"I went to the solicitors."

"It is awfully good of you to take so much trouble. And what did
they say?"

"As it happened, I had some knowledge of the firm. My father


was on terms of friendship with their senior partner, so that when I
introduced myself to Mr. Nicholls as my father's son, the way was
smoothed for me. They have the reputation of being a steady-going,
old-fashioned firm, and I found them as open and above-board as
they very well could have been. When I mentioned my errand, Mr.
Nicholls was all alive at once."

"'Messrs. Palmer & Beading, of Wandsworth,' I began, 'inform me


that in letting Clover Cottage they are instructed by you. May I ask
who is the owner of the property?'

"When I said that, he sat up straight in his chair, and, as I


observed, became all alive--oh.

"'May I inquire, in return, why you ask the question?'

"'The question,' I admitted, 'is a little irregular; but I take it that


you will have no objection to give me an answer.'

"'Not the slightest. On the contrary, we shall be delighted if you


will help us to throw light into what is, at present, a very dark
corner; because, as a matter of fact, so far as we are concerned,
there is no owner.'

"'The late Thomas Ossington died intestate!'

"'So far as our knowledge goes.'

"'Leaving instructions that you should act on his behalf?'

"'Not a bit of it. So far as we're aware, he left no instructions of


any sort or kind. We have assumed a responsibility of which we
should be glad to be rid. Do you know the man's history?'

"'I know something of it--though I confess, candidly, that I should


like to know more. My own connection with the matter is a curious
one. At a later stage I will tell you exactly what it is. In the interim, I
assure you, on my word of honour, that any information you can
give me shall be used for the furtherance of justice, and for that
only.'

"'Very good; so long as right is done, all that we require is to be


relieved of a very awkward situation. You know that Ossington was--
peculiar?'

"'Not insane?'
"'Insane?--No; he was as sane as you are--every whit. But he was
a disappointed man. He was malformed--the muscles of one leg
were paralysed. As he grew older, the paralysis increased, until it
extended up the whole of one side, and, at last, it killed him. He
married a girl who acted as book-keeper at an hotel, at which he
was in the habit of stopping, at Ilfracombe. She turned out a regular
bad lot--finally running away with a man named Ballingall.'

"'Charles Ballingall?'

"'That's the man. Do you know him?'

"'I have acted for him professionally.'

"'Have you? Then let me inform you, without prejudice, that you
have acted for as rascally a scamp as ever trod the earth. Ossington
regarded him as a particular friend; and, as particular friends
sometimes have a knack of doing, he borrowed no end of money
from Ossington, ending by robbing him not only of his money, but of
his wife as well. The double blow almost broke Ossington's heart,
and during the remainder of his existence he lived the life of a
recluse. But, until then, we had acted for him continually. For
instance, we had acted for him in the purchase of Clover Cottage.'

"'Do you hold the deeds of the house?'

"'Not a deed. We hold nothing. All that we have are the various
letters which he wrote to us at various times, on business. We had
heard nothing of him for months, when one morning we received a
telegram asking us to go at once to Clover Cottage. I went myself--I
liked the man. He was, in his way, as fine a gentleman as I ever
met. He had been cruelly used by friend and fortune. I found him
dead--alone in the house there, with a maid and a doctor; dead--
killed, according to the medical testimony, by a paralytic affection of
the heart; but actually, as sure as you and I are alive, by the wicked
wanton usage of those he had held dear. Now here the queer part of
the thing comes in.
"'His last words had been an instruction to send for us; but that
was the only instruction he had given. I myself searched the house
from top to bottom, and, as you know, it is not a large one. I had it
searched by others--every nook and cranny. Not a scrap of writing
could be discovered--letter, note, or memorandum. Not a document
of any sort of kind. Nothing whatever to show of what he had died
possessed, or to whom it was to go.'

"'You had reasons to suppose that he had means?'

"'Every reason! We had every reason to believe him to be a man


of comfortable means. We ourselves had, on more than one
occasion, acted for him in matters involving thousands of pounds.
We applied to the National and Provincial Bank--where we were
aware he had an account. They informed us that he had closed the
account some two months previously, and that on that occasion they
had handed him over six thousand pounds in notes on the Bank of
England. They gave us a list of the numbers of the notes; and not
one of them has been presented for payment to this day.'

"'Is that so?'

"'It is. We furnished the Bank with a copy of the list, requesting
them to notify us should one of them come in: as yet not a single
one of them has made its appearance. Where are those notes?
Surely, if they were in the possession of any living person, ere this
some of them would have been presented. Where are the title deeds
of Clover Cottage--and of other properties, of which he was the
undoubted owner? He is the registered holder of ten thousand Great
Northern Railway Stock. Since his death, the dividends on it have
remained unclaimed. Where is the scrip? With the rest, has it
vanished into air? In a box in his bedroom were forty-seven pounds
in gold. That was all the cash the house contained. We buried him in
Wandsworth Cemetery; Hawkins, I, and the doctor were the only
mourners. We sold the furniture, paid the expenses, and the balance
stands to the credit of the estate. We advertised for next of kin,
without results. We advertised also for information as to the
whereabouts of any property of which he might have died
possessed--such as title-deeds, and anything of that kind. You
understand that there is a delicate question as to who is entitled to
collect the rents of other properties which we believe to have been
his freehold. But nothing came of that. Clover Cottage we placed in
the hands of Messrs. Parker and Beading, but only recently have
they succeeded in letting it--I believe to two single ladies.'

"'So I understand.'"

Jack struck in.

"You are the two single ladies. You," pointing to Ella, "are one of
them, and you," pointing to Madge, "are the other."

Ella was impatient.

"Jack, I do wish you wouldn't interrupt.--Mr. Graham, do go on.


It's like a romance. My curiosity is such that I feel as if I were all
pins and needles."

Bruce Graham continued.

"'And you, Mr. Nicholls,' I said, 'have you formed no theory of your
own upon the subject?'

"Old Nicholls leaned back in his chair. He put his hands into his
two pockets, and he looked at me out of the corners of his eyes.

"'I have--I have formed a decided theory. But, upon my word, I


don't know what right you have to ask me.'

"'I trust, before we part, to prove to your entire satisfaction that I


have every right. What's the nature of your theory?'

"'What's the nature of your right?'


"I laughed. I saw that he meant to understand more clearly
where we stood before he went any further.

"'I believe I am in a position to produce an owner for the


property--when found.'

"'When found?'

"'Precisely--when found. As yet it still remains to be found. I must


ask you not, at this moment, to press me for further details, and of
course you, on your part, are entitled to keep your theory to
yourself.'

"'I am entitled to keep my theory to myself, as you say. But I


know your father was an honest man, and as it happens, I know
something about you, and I believe you also are an honest man. So
as I am anxious, for many reasons, that this Ossington mystery
should be unravelled, you shall have my theory for what it's worth.'

"'He tilted his chair on to its hind-legs, watching me keenly all the
time.

"'Thomas Ossington was peculiar--not, in any sense of the word,


insane, but out of the common run. In particular he was secretive,
especially latterly, as perhaps was only natural. My theory is that,
distrusting banks and all such human institutions, he secreted his
cash, his title deeds, and everything he valued, in some hiding-place
of his own contriving, and that there it remains concealed unto this
hour.'"

The two girls rose simultaneously.

"Madge," cried Ella, "did you hear that? That's exactly what you
said."

In Madge's tones there was the ring of an assured conviction.


"I was sure of it--and I am sure of it; as sure as any one possibly
can be."

"May I ask," inquired Jack, with mock severity, "who is it who is


interrupting now? Will you let the gentleman go on?"

Graham went on.

"'But where,' I said, 'do you think he is likely to have found such a
hiding-place?'

"Old Nicholls looked at me, if possible, more shrewdly than ever.

"'At Clover Cottage. I knew the man. The salient events of his life
happened there. In his whimsical way he regarded it as part and
parcel of himself. I have heard him say so half a dozen times. His
heart was in the place. Whatever he did conceal, was concealed
within its four walls. Before the furniture was sold, I had it
overhauled by an expert--some of the things were pulled to pieces.
His verdict was that nothing was hidden there. Had I had my way I
would have dismantled the whole house--only Hawkins was against
me. He said very properly, that if the heir-at-law proved
cantankerous, I might be made to smart in damages to the tune of a
pretty penny. So I abstained. All the same, if the house was in the
market to-morrow, I'd be a purchaser at a good round sum--if all
rights of treasure trove went with it. You may tell the present
tenants'--here he looked at me in a fashion which took me a little
aback--'if you have the honour of their acquaintance, that we keep a
sharp eye on the property; that it is not to be tampered with to the
extent of one jot or tittle; and that not so much as one inch of paper
is to be taken off the wall except with our express permission.'"

Ella turned to Madge.

"What do you say to that?" she exclaimed. "That knocks on the


head all your notions of pulling the house to pieces."
Madge was defiant.

"Does it? It does nothing of the kind. Not after what I found in
this very room last night. In the face of that, I care nothing for Mr.
Nicholls, or for his threats either. What do you think yourself, Mr.
Graham?"

"If you will allow me, I will give you my own opinion when I have
told you of all that passed between Mr. Nicholls and myself. Indeed,
I am now coming to that very point."

"There you are, you see. You will not let the man finish, you really
won't. I never saw anything like you women for interrupting--never
in all my life."

This of course was Jack--who was, as usual, ignored.

Graham brought his story to an end.

"'There is one more question', I said, 'which I should like to ask


you, Mr. Nicholls. Do you know any one of the name of Edward John
Hurley?'

"'I ought to, seeing that some one of the name of Edward John
Hurley is in our office at this moment, and has been in our office for
something over a quarter of a century.'

"'Can I see him?'

"Mr. Nicholls touched a bell, and presently Mr. Hurley entered. I


felt that his presence on the spot was a stroke of luck for which I
had certainly been unprepared. He was a tall, thin, dignified looking
man, with grey hair. He wore spectacles. Taking them off, he wiped
them with his handkerchief before he replaced them on his nose to
look at me.
"'Do you remember, Mr. Hurley,' I began, 'the 22nd of October,
1892?'

"'The 22nd of October, 1892?' He repeated my words, then replied


to my question with another, 'May I inquire why you ask?'

"'I will put my question in another form. Do you remember


witnessing Mr. Thomas Ossington's attachment of his signature to a
certain document on the 22nd of October, 1892?'

"I had noticed that Mr. Nicholls and he had exchanged glances
when I first put my query. Now he looked at his principal evidently in
search of guidance.

"'Shall I answer this gentleman's question, sir?'

"'Certainly. Give him all the information you can.'

"This Mr. Hurley proceeded to do, with the utmost clearness.

"'I do remember the 22nd of October, 1892, and the whole of the
circumstances. I chanced to meet Mr. Ossington in Holborn as I was
leaving the office. He asked me if I would dine with him in his house
at Wandsworth. I went with him to dinner there and then. After
dinner he asked me if I would witness his signature. I expressed my
willingness. I witnessed it.'

"'Were you acquainted with the nature of the document he was


signing?'

"'I was not. I have often wondered what it was, especially in the
light of after events. The document, which was on a sheet of blue
foolscap, had evidently been prepared before my arrival: Mr.
Ossington, covering the writing with a piece of blotting-paper, signed
it, in the middle of the page, directly underneath, while I affixed my
signature, as witness, on the left-hand side.'
"'Was there another witness?'

"'There was, the servant girl.'

"'What was her name?'

"'I never heard it. I only know that he called her Louisa. I think I
should recognise her if I saw her again. She was a red-faced, light-
haired, strapping wench, about eighteen years of age.'

"'Should you recognise Ossington's signature--and your own--and


the document to which they were attached?'

"'Most decidedly; under any circumstances, at any time.'

"I thanked him for his frankness, and rose to go. Nicholls stopped
me.

"'One moment,' he said. 'Hurley informed us, at the time, of what


he has just now told you, and, like him, we have frequently
wondered what was the nature of the document he witnessed. As
you are evidently aware that such a paper existed once upon a time,
you are probably acquainted with its present whereabouts?'

"'I am. It will be produced in due course. When, I promise you,


you will see as curious a document as is to be found upon the
records.'

"Both Nicholls and Hurley endeavoured to induce me to be more


definite. But I was not to be persuaded. Thanking them for the
information they had given me, I came away."
CHAPTER XIII
AN INTERRUPTED TREASURE HUNT

"Well," inquired Martyn, when Graham? had finished, "what is the


situation now?"

"First of all," struck in Madge, "how about the will?"

"As regards the will, I do not hesitate to say that it is as sound


and valid a declaration of the testator's wishes as has been admitted
to probate--Mr. Hurley's testimony removes all doubt upon that
point. A man has a right to do what he will with his own--and that is
all Mr. Ossington has done."

"How does it effect our right of search?"

"That is another question. The will gives neither you nor any one
else a title for the destruction of property. It simply conveys to the
finder the possession of certain things which are not specifically
mentioned. But it authorises no one to look for those things, still less
to do damage while looking."

"Then is our search barred? Aren't we to look at all?"

"I don't say that. My advice is to put the legal aspect aside, and
to regard the common-sense one only. The will says that certain
things, when found, are to become the property of the finder, and
this house with them. You have reason to believe that those things
are concealed within this house. Then it is for you to consider
whether it is worth your while to run the risk of becoming
responsible for any damage you may do in case of your failure to
find those things. My opinion is, that it is worth your while to run
that risk--that it is worth any one's while to run that risk."

Madge stood up, with resolute lips, and sparkling eyes. She struck
her hand upon the table.

"I'm sure it is! I know it is!"

Bruce Graham also rose.

"I am willing to share the risk if it is shareable--or to assume the


whole of it, for the matter of that. I incline strongly to your belief,
Miss Brodie, that there is something hidden well worth the finding,
and that its hiding-place is within the walls of Clover Cottage."

Jack Martyn hammered his fist upon the table.

"Hear, hear!--bravo!--spoken like a man! 'Pon my word, I'm


beginning to think that there is something in it after all. A conviction
is creeping over me, slowly but surely, that in less time than no time
I shall be filling my pockets with the contents of Aladdin's Cave--and
as there is only a bent sixpence and two bad pennies in them at
present, there's plenty of room for more."

"The point is," said Ella, "where are you going to begin to look?"

"I am going to do what Mr. Nicholls wanted to do," declared


Madge--"tear the house to pieces."

"But, my dear, even if you set about the business in that drastic
fashion, you'll require method. How are you going to begin to take
the house to pieces--by taking the slates off the roof, and the
chimney-pots down?"

"And by taking the windows out of their frames, and the doors off
their hinges, and displaying the grates in the front garden! George!
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

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.

Let us accompany you on the journey of exploring knowledge and


personal growth!

textbookfull.com

You might also like