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 :meth:`__set__` or :meth:`__delete__`, 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 attribute lookup ``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 and
316    # the bound instance.
317    >>> d.f.__func__
318    <function D.f at 0x1012e5ae8>
319    >>> d.f.__self__
320    <__main__.D object at 0x1012e1f98>
321
322
323Static Methods and Class Methods
324--------------------------------
325
326Non-data descriptors provide a simple mechanism for variations on the usual
327patterns of binding functions into methods.
328
329To recap, functions have a :meth:`__get__` method so that they can be converted
330to a method when accessed as attributes.  The non-data descriptor transforms an
331``obj.f(*args)`` call into ``f(obj, *args)``.  Calling ``klass.f(*args)``
332becomes ``f(*args)``.
333
334This chart summarizes the binding and its two most useful variants:
335
336      +-----------------+----------------------+------------------+
337      | Transformation  | Called from an       | Called from a    |
338      |                 | Object               | Class            |
339      +=================+======================+==================+
340      | function        | f(obj, \*args)       | f(\*args)        |
341      +-----------------+----------------------+------------------+
342      | staticmethod    | f(\*args)            | f(\*args)        |
343      +-----------------+----------------------+------------------+
344      | classmethod     | f(type(obj), \*args) | f(klass, \*args) |
345      +-----------------+----------------------+------------------+
346
347Static methods return the underlying function without changes.  Calling either
348``c.f`` or ``C.f`` is the equivalent of a direct lookup into
349``object.__getattribute__(c, "f")`` or ``object.__getattribute__(C, "f")``. As a
350result, the function becomes identically accessible from either an object or a
351class.
352
353Good candidates for static methods are methods that do not reference the
354``self`` variable.
355
356For instance, a statistics package may include a container class for
357experimental data.  The class provides normal methods for computing the average,
358mean, median, and other descriptive statistics that depend on the data. However,
359there may be useful functions which are conceptually related but do not depend
360on the data.  For instance, ``erf(x)`` is handy conversion routine that comes up
361in statistical work but does not directly depend on a particular dataset.
362It can be called either from an object or the class:  ``s.erf(1.5) --> .9332`` or
363``Sample.erf(1.5) --> .9332``.
364
365Since staticmethods return the underlying function with no changes, the example
366calls are unexciting::
367
368    >>> class E(object):
369    ...     def f(x):
370    ...         print(x)
371    ...     f = staticmethod(f)
372    ...
373    >>> E.f(3)
374    3
375    >>> E().f(3)
376    3
377
378Using the non-data descriptor protocol, a pure Python version of
379:func:`staticmethod` would look like this::
380
381    class StaticMethod(object):
382        "Emulate PyStaticMethod_Type() in Objects/funcobject.c"
383
384        def __init__(self, f):
385            self.f = f
386
387        def __get__(self, obj, objtype=None):
388            return self.f
389
390Unlike static methods, class methods prepend the class reference to the
391argument list before calling the function.  This format is the same
392for whether the caller is an object or a class::
393
394    >>> class E(object):
395    ...     def f(klass, x):
396    ...         return klass.__name__, x
397    ...     f = classmethod(f)
398    ...
399    >>> print(E.f(3))
400    ('E', 3)
401    >>> print(E().f(3))
402    ('E', 3)
403
404
405This behavior is useful whenever the function only needs to have a class
406reference and does not care about any underlying data.  One use for classmethods
407is to create alternate class constructors.  In Python 2.3, the classmethod
408:func:`dict.fromkeys` creates a new dictionary from a list of keys.  The pure
409Python equivalent is::
410
411    class Dict(object):
412        . . .
413        def fromkeys(klass, iterable, value=None):
414            "Emulate dict_fromkeys() in Objects/dictobject.c"
415            d = klass()
416            for key in iterable:
417                d[key] = value
418            return d
419        fromkeys = classmethod(fromkeys)
420
421Now a new dictionary of unique keys can be constructed like this::
422
423    >>> Dict.fromkeys('abracadabra')
424    {'a': None, 'r': None, 'b': None, 'c': None, 'd': None}
425
426Using the non-data descriptor protocol, a pure Python version of
427:func:`classmethod` would look like this::
428
429    class ClassMethod(object):
430        "Emulate PyClassMethod_Type() in Objects/funcobject.c"
431
432        def __init__(self, f):
433            self.f = f
434
435        def __get__(self, obj, klass=None):
436            if klass is None:
437                klass = type(obj)
438            def newfunc(*args):
439                return self.f(klass, *args)
440            return newfunc
441
442