1======================
2Descriptor HowTo Guide
3======================
4
5:Author: Raymond Hettinger
6:Contact: <python at rcn dot com>
7
8.. Contents::
9
10Abstract
11--------
12
13Defines descriptors, summarizes the protocol, and shows how descriptors are
14called.  Examines a custom descriptor and several built-in Python descriptors
15including functions, properties, static methods, and class methods.  Shows how
16each works by giving a pure Python equivalent and a sample application.
17
18Learning about descriptors not only provides access to a larger toolset, it
19creates a deeper understanding of how Python works and an appreciation for the
20elegance of its design.
21
22
23Definition and Introduction
24---------------------------
25
26In general, a descriptor is an object attribute with "binding behavior", one
27whose attribute access has been overridden by methods in the descriptor
28protocol.  Those methods are :meth:`__get__`, :meth:`__set__`, and
29:meth:`__delete__`.  If any of those methods are defined for an object, it is
30said to be a descriptor.
31
32The default behavior for attribute access is to get, set, or delete the
33attribute from an object's dictionary.  For instance, ``a.x`` has a lookup chain
34starting with ``a.__dict__['x']``, then ``type(a).__dict__['x']``, and
35continuing through the base classes of ``type(a)`` excluding metaclasses. If the
36looked-up value is an object defining one of the descriptor methods, then Python
37may override the default behavior and invoke the descriptor method instead.
38Where this occurs in the precedence chain depends on which descriptor methods
39were defined.
40
41Descriptors are a powerful, general purpose protocol.  They are the mechanism
42behind properties, methods, static methods, class methods, and :func:`super()`.
43They are used throughout Python itself to implement the new style classes
44introduced in version 2.2.  Descriptors simplify the underlying C-code and offer
45a flexible set of new tools for everyday Python programs.
46
47
48Descriptor Protocol
49-------------------
50
51``descr.__get__(self, obj, type=None) -> value``
52
53``descr.__set__(self, obj, value) -> None``
54
55``descr.__delete__(self, obj) -> None``
56
57That is all there is to it.  Define any of these methods and an object is
58considered a descriptor and can override default behavior upon being looked up
59as an attribute.
60
61If an object defines both :meth:`__get__` and :meth:`__set__`, it is considered
62a data descriptor.  Descriptors that only define :meth:`__get__` are called
63non-data descriptors (they are typically used for methods but other uses are
64possible).
65
66Data and non-data descriptors differ in how overrides are calculated with
67respect to entries in an instance's dictionary.  If an instance's dictionary
68has an entry with the same name as a data descriptor, the data descriptor
69takes precedence.  If an instance's dictionary has an entry with the same
70name as a non-data descriptor, the dictionary entry takes precedence.
71
72To make a read-only data descriptor, define both :meth:`__get__` and
73:meth:`__set__` with the :meth:`__set__` raising an :exc:`AttributeError` when
74called.  Defining the :meth:`__set__` method with an exception raising
75placeholder is enough to make it a data descriptor.
76
77
78Invoking Descriptors
79--------------------
80
81A descriptor can be called directly by its method name.  For example,
82``d.__get__(obj)``.
83
84Alternatively, it is more common for a descriptor to be invoked automatically
85upon attribute access.  For example, ``obj.d`` looks up ``d`` in the dictionary
86of ``obj``.  If ``d`` defines the method :meth:`__get__`, then ``d.__get__(obj)``
87is invoked according to the precedence rules listed below.
88
89The details of invocation depend on whether ``obj`` is an object or a class.
90
91For objects, the machinery is in :meth:`object.__getattribute__` which
92transforms ``b.x`` into ``type(b).__dict__['x'].__get__(b, type(b))``.  The
93implementation works through a precedence chain that gives data descriptors
94priority over instance variables, instance variables priority over non-data
95descriptors, and assigns lowest priority to :meth:`__getattr__` if provided.
96The full C implementation can be found in :c:func:`PyObject_GenericGetAttr()` in
97:source:`Objects/object.c`.
98
99For classes, the machinery is in :meth:`type.__getattribute__` which transforms
100``B.x`` into ``B.__dict__['x'].__get__(None, B)``.  In pure Python, it looks
101like::
102
103    def __getattribute__(self, key):
104        "Emulate type_getattro() in Objects/typeobject.c"
105        v = object.__getattribute__(self, key)
106        if hasattr(v, '__get__'):
107            return v.__get__(None, self)
108        return v
109
110The important points to remember are:
111
112* descriptors are invoked by the :meth:`__getattribute__` method
113* overriding :meth:`__getattribute__` prevents automatic descriptor calls
114* :meth:`object.__getattribute__` and :meth:`type.__getattribute__` make
115  different calls to :meth:`__get__`.
116* data descriptors always override instance dictionaries.
117* non-data descriptors may be overridden by instance dictionaries.
118
119The object returned by ``super()`` also has a custom :meth:`__getattribute__`
120method for invoking descriptors.  The call ``super(B, obj).m()`` searches
121``obj.__class__.__mro__`` for the base class ``A`` immediately following ``B``
122and then returns ``A.__dict__['m'].__get__(obj, B)``.  If not a descriptor,
123``m`` is returned unchanged.  If not in the dictionary, ``m`` reverts to a
124search using :meth:`object.__getattribute__`.
125
126The implementation details are in :c:func:`super_getattro()` in
127:source:`Objects/typeobject.c`.  and a pure Python equivalent can be found in
128`Guido's Tutorial`_.
129
130.. _`Guido's Tutorial`: https://www.python.org/download/releases/2.2.3/descrintro/#cooperation
131
132The details above show that the mechanism for descriptors is embedded in the
133:meth:`__getattribute__()` methods for :class:`object`, :class:`type`, and
134:func:`super`.  Classes inherit this machinery when they derive from
135:class:`object` or if they have a meta-class providing similar functionality.
136Likewise, classes can turn-off descriptor invocation by overriding
137:meth:`__getattribute__()`.
138
139
140Descriptor Example
141------------------
142
143The following code creates a class whose objects are data descriptors which
144print a message for each get or set.  Overriding :meth:`__getattribute__` is
145alternate approach that could do this for every attribute.  However, this
146descriptor is useful for monitoring just a few chosen attributes::
147
148    class RevealAccess(object):
149        """A data descriptor that sets and returns values
150           normally and prints a message logging their access.
151        """
152
153        def __init__(self, initval=None, name='var'):
154            self.val = initval
155            self.name = name
156
157        def __get__(self, obj, objtype):
158            print('Retrieving', self.name)
159            return self.val
160
161        def __set__(self, obj, val):
162            print('Updating', self.name)
163            self.val = val
164
165    >>> class MyClass(object):
166    ...     x = RevealAccess(10, 'var "x"')
167    ...     y = 5
168    ...
169    >>> m = MyClass()
170    >>> m.x
171    Retrieving var "x"
172    10
173    >>> m.x = 20
174    Updating var "x"
175    >>> m.x
176    Retrieving var "x"
177    20
178    >>> m.y
179    5
180
181The protocol is simple and offers exciting possibilities.  Several use cases are
182so common that they have been packaged into individual function calls.
183Properties, bound methods, static methods, and class methods are all
184based on the descriptor protocol.
185
186
187Properties
188----------
189
190Calling :func:`property` is a succinct way of building a data descriptor that
191triggers function calls upon access to an attribute.  Its signature is::
192
193    property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
194
195The documentation shows a typical use to define a managed attribute ``x``::
196
197    class C(object):
198        def getx(self): return self.__x
199        def setx(self, value): self.__x = value
200        def delx(self): del self.__x
201        x = property(getx, setx, delx, "I'm the 'x' property.")
202
203To see how :func:`property` is implemented in terms of the descriptor protocol,
204here is a pure Python equivalent::
205
206    class Property(object):
207        "Emulate PyProperty_Type() in Objects/descrobject.c"
208
209        def __init__(self, fget=None, fset=None, fdel=None, doc=None):
210            self.fget = fget
211            self.fset = fset
212            self.fdel = fdel
213            if doc is None and fget is not None:
214                doc = fget.__doc__
215            self.__doc__ = doc
216
217        def __get__(self, obj, objtype=None):
218            if obj is None:
219                return self
220            if self.fget is None:
221                raise AttributeError("unreadable attribute")
222            return self.fget(obj)
223
224        def __set__(self, obj, value):
225            if self.fset is None:
226                raise AttributeError("can't set attribute")
227            self.fset(obj, value)
228
229        def __delete__(self, obj):
230            if self.fdel is None:
231                raise AttributeError("can't delete attribute")
232            self.fdel(obj)
233
234        def getter(self, fget):
235            return type(self)(fget, self.fset, self.fdel, self.__doc__)
236
237        def setter(self, fset):
238            return type(self)(self.fget, fset, self.fdel, self.__doc__)
239
240        def deleter(self, fdel):
241            return type(self)(self.fget, self.fset, fdel, self.__doc__)
242
243The :func:`property` builtin helps whenever a user interface has granted
244attribute access and then subsequent changes require the intervention of a
245method.
246
247For instance, a spreadsheet class may grant access to a cell value through
248``Cell('b10').value``. Subsequent improvements to the program require the cell
249to be recalculated on every access; however, the programmer does not want to
250affect existing client code accessing the attribute directly.  The solution is
251to wrap access to the value attribute in a property data descriptor::
252
253    class Cell(object):
254        . . .
255        def getvalue(self):
256            "Recalculate the cell before returning value"
257            self.recalc()
258            return self._value
259        value = property(getvalue)
260
261
262Functions and Methods
263---------------------
264
265Python's object oriented features are built upon a function based environment.
266Using non-data descriptors, the two are merged seamlessly.
267
268Class dictionaries store methods as functions.  In a class definition, methods
269are written using :keyword:`def` or :keyword:`lambda`, the usual tools for
270creating functions.  Methods only differ from regular functions in that the
271first argument is reserved for the object instance.  By Python convention, the
272instance reference is called *self* but may be called *this* or any other
273variable name.
274
275To support method calls, functions include the :meth:`__get__` method for
276binding methods during attribute access.  This means that all functions are
277non-data descriptors which return bound methods when they are invoked from an
278object.  In pure Python, it works like this::
279
280    class Function(object):
281        . . .
282        def __get__(self, obj, objtype=None):
283            "Simulate func_descr_get() in Objects/funcobject.c"
284            if obj is None:
285                return self
286            return types.MethodType(self, obj)
287
288Running the interpreter shows how the function descriptor works in practice::
289
290    >>> class D(object):
291    ...     def f(self, x):
292    ...         return x
293    ...
294    >>> d = D()
295
296    # Access through the class dictionary does not invoke __get__.
297    # It just returns the underlying function object.
298    >>> D.__dict__['f']
299    <function D.f at 0x00C45070>
300
301    # Dotted access from a class calls __get__() which just returns
302    # the underlying function unchanged.
303    >>> D.f
304    <function D.f at 0x00C45070>
305
306    # The function has a __qualname__ attribute to support introspection
307    >>> D.f.__qualname__
308    'D.f'
309
310    # Dotted access from an instance calls __get__() which returns the
311    # function wrapped in a bound method object
312    >>> d.f
313    <bound method D.f of <__main__.D object at 0x00B18C90>>
314
315    # Internally, the bound method stores the underlying function,
316    # the bound instance, and the class of the bound instance.
317    >>> d.f.__func__
318    <function D.f at 0x1012e5ae8>
319    >>> d.f.__self__
320    <__main__.D object at 0x1012e1f98>
321    >>> d.f.__class__
322    <class 'method'>
323
324
325Static Methods and Class Methods
326--------------------------------
327
328Non-data descriptors provide a simple mechanism for variations on the usual
329patterns of binding functions into methods.
330
331To recap, functions have a :meth:`__get__` method so that they can be converted
332to a method when accessed as attributes.  The non-data descriptor transforms an
333``obj.f(*args)`` call into ``f(obj, *args)``.  Calling ``klass.f(*args)``
334becomes ``f(*args)``.
335
336This chart summarizes the binding and its two most useful variants:
337
338      +-----------------+----------------------+------------------+
339      | Transformation  | Called from an       | Called from a    |
340      |                 | Object               | Class            |
341      +=================+======================+==================+
342      | function        | f(obj, \*args)       | f(\*args)        |
343      +-----------------+----------------------+------------------+
344      | staticmethod    | f(\*args)            | f(\*args)        |
345      +-----------------+----------------------+------------------+
346      | classmethod     | f(type(obj), \*args) | f(klass, \*args) |
347      +-----------------+----------------------+------------------+
348
349Static methods return the underlying function without changes.  Calling either
350``c.f`` or ``C.f`` is the equivalent of a direct lookup into
351``object.__getattribute__(c, "f")`` or ``object.__getattribute__(C, "f")``. As a
352result, the function becomes identically accessible from either an object or a
353class.
354
355Good candidates for static methods are methods that do not reference the
356``self`` variable.
357
358For instance, a statistics package may include a container class for
359experimental data.  The class provides normal methods for computing the average,
360mean, median, and other descriptive statistics that depend on the data. However,
361there may be useful functions which are conceptually related but do not depend
362on the data.  For instance, ``erf(x)`` is handy conversion routine that comes up
363in statistical work but does not directly depend on a particular dataset.
364It can be called either from an object or the class:  ``s.erf(1.5) --> .9332`` or
365``Sample.erf(1.5) --> .9332``.
366
367Since staticmethods return the underlying function with no changes, the example
368calls are unexciting::
369
370    >>> class E(object):
371    ...     def f(x):
372    ...         print(x)
373    ...     f = staticmethod(f)
374    ...
375    >>> E.f(3)
376    3
377    >>> E().f(3)
378    3
379
380Using the non-data descriptor protocol, a pure Python version of
381:func:`staticmethod` would look like this::
382
383    class StaticMethod(object):
384        "Emulate PyStaticMethod_Type() in Objects/funcobject.c"
385
386        def __init__(self, f):
387            self.f = f
388
389        def __get__(self, obj, objtype=None):
390            return self.f
391
392Unlike static methods, class methods prepend the class reference to the
393argument list before calling the function.  This format is the same
394for whether the caller is an object or a class::
395
396    >>> class E(object):
397    ...     def f(klass, x):
398    ...         return klass.__name__, x
399    ...     f = classmethod(f)
400    ...
401    >>> print(E.f(3))
402    ('E', 3)
403    >>> print(E().f(3))
404    ('E', 3)
405
406
407This behavior is useful whenever the function only needs to have a class
408reference and does not care about any underlying data.  One use for classmethods
409is to create alternate class constructors.  In Python 2.3, the classmethod
410:func:`dict.fromkeys` creates a new dictionary from a list of keys.  The pure
411Python equivalent is::
412
413    class Dict(object):
414        . . .
415        def fromkeys(klass, iterable, value=None):
416            "Emulate dict_fromkeys() in Objects/dictobject.c"
417            d = klass()
418            for key in iterable:
419                d[key] = value
420            return d
421        fromkeys = classmethod(fromkeys)
422
423Now a new dictionary of unique keys can be constructed like this::
424
425    >>> Dict.fromkeys('abracadabra')
426    {'a': None, 'r': None, 'b': None, 'c': None, 'd': None}
427
428Using the non-data descriptor protocol, a pure Python version of
429:func:`classmethod` would look like this::
430
431    class ClassMethod(object):
432        "Emulate PyClassMethod_Type() in Objects/funcobject.c"
433
434        def __init__(self, f):
435            self.f = f
436
437        def __get__(self, obj, klass=None):
438            if klass is None:
439                klass = type(obj)
440            def newfunc(*args):
441                return self.f(klass, *args)
442            return newfunc
443
444