blob: 5e85a9aa6594e458a7ef8470f2248f0133827d6b [file] [log] [blame]
Georg Brandl45cceeb2010-05-19 21:39:51 +00001======================
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
Florent Xiclunaaa6c1d22011-12-12 18:54:29 +010039were defined.
Georg Brandl45cceeb2010-05-19 21:39:51 +000040
41Descriptors are a powerful, general purpose protocol. They are the mechanism
42behind properties, methods, static methods, class methods, and :func:`super()`.
Ezio Melotti222e61e2011-07-31 22:49:18 +030043They are used throughout Python itself to implement the new style classes
Georg Brandl45cceeb2010-05-19 21:39:51 +000044introduced 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.
Georg Brandl45cceeb2010-05-19 21:39:51 +000090
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
Benjamin Peterson57fb11b2014-10-06 21:10:25 -040095descriptors, 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`.
Georg Brandl45cceeb2010-05-19 21:39:51 +000098
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__'):
Serhiy Storchakadba90392016-05-10 12:01:23 +0300107 return v.__get__(None, self)
Georg Brandl45cceeb2010-05-19 21:39:51 +0000108 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
Georg Brandl45cceeb2010-05-19 21:39:51 +0000114* :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``
Benjamin Peterson910a6652013-10-18 12:57:55 -0400122and then returns ``A.__dict__['m'].__get__(obj, B)``. If not a descriptor,
Georg Brandl45cceeb2010-05-19 21:39:51 +0000123``m`` is returned unchanged. If not in the dictionary, ``m`` reverts to a
124search using :meth:`object.__getattribute__`.
125
Florent Xiclunaaa6c1d22011-12-12 18:54:29 +0100126The implementation details are in :c:func:`super_getattro()` in
Benjamin Peterson57fb11b2014-10-06 21:10:25 -0400127:source:`Objects/typeobject.c`. and a pure Python equivalent can be found in
128`Guido's Tutorial`_.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000129
Georg Brandl9bdcb3b2014-10-29 09:37:43 +0100130.. _`Guido's Tutorial`: https://www.python.org/download/releases/2.2.3/descrintro/#cooperation
Georg Brandl45cceeb2010-05-19 21:39:51 +0000131
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):
Serhiy Storchakadba90392016-05-10 12:01:23 +0300166 ... x = RevealAccess(10, 'var "x"')
167 ... y = 5
168 ...
Georg Brandl45cceeb2010-05-19 21:39:51 +0000169 >>> 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.
Raymond Hettinger0d4497b2017-09-25 01:05:49 -0700183Properties, bound methods, static methods, and class methods are all
Georg Brandl45cceeb2010-05-19 21:39:51 +0000184based 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
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700213 if doc is None and fget is not None:
214 doc = fget.__doc__
Georg Brandl45cceeb2010-05-19 21:39:51 +0000215 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:
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700221 raise AttributeError("unreadable attribute")
Georg Brandl45cceeb2010-05-19 21:39:51 +0000222 return self.fget(obj)
223
224 def __set__(self, obj, value):
225 if self.fset is None:
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700226 raise AttributeError("can't set attribute")
Georg Brandl45cceeb2010-05-19 21:39:51 +0000227 self.fset(obj, value)
228
229 def __delete__(self, obj):
230 if self.fdel is None:
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700231 raise AttributeError("can't delete attribute")
Georg Brandl45cceeb2010-05-19 21:39:51 +0000232 self.fdel(obj)
233
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700234 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
Georg Brandl45cceeb2010-05-19 21:39:51 +0000243The :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 . . .
_ = NaNb066edf2017-06-23 11:54:35 +0800255 def getvalue(self):
256 "Recalculate the cell before returning value"
Georg Brandl45cceeb2010-05-19 21:39:51 +0000257 self.recalc()
_ = NaNb066edf2017-06-23 11:54:35 +0800258 return self._value
Georg Brandl45cceeb2010-05-19 21:39:51 +0000259 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
Raymond Hettinger0d4497b2017-09-25 01:05:49 -0700269are written using :keyword:`def` or :keyword:`lambda`, the usual tools for
270creating functions. Methods only differ from regular functions in that the
Georg Brandl45cceeb2010-05-19 21:39:51 +0000271first 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
Raymond Hettinger0d4497b2017-09-25 01:05:49 -0700277non-data descriptors which return bound methods when they are invoked from an
278object. In pure python, it works like this::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000279
280 class Function(object):
281 . . .
282 def __get__(self, obj, objtype=None):
283 "Simulate func_descr_get() in Objects/funcobject.c"
Raymond Hettinger0d4497b2017-09-25 01:05:49 -0700284 if obj is None:
285 return self
Mariano Anaya1bced562017-06-05 04:46:50 +0200286 return types.MethodType(self, obj)
Georg Brandl45cceeb2010-05-19 21:39:51 +0000287
288Running the interpreter shows how the function descriptor works in practice::
289
290 >>> class D(object):
Serhiy Storchakadba90392016-05-10 12:01:23 +0300291 ... def f(self, x):
292 ... return x
293 ...
Georg Brandl45cceeb2010-05-19 21:39:51 +0000294 >>> d = D()
Raymond Hettinger0d4497b2017-09-25 01:05:49 -0700295
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
Georg Brandl45cceeb2010-05-19 21:39:51 +0000313 <bound method D.f of <__main__.D object at 0x00B18C90>>
314
Raymond Hettinger0d4497b2017-09-25 01:05:49 -0700315 # 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'>
Georg Brandl45cceeb2010-05-19 21:39:51 +0000323
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
Serhiy Storchakad65c9492015-11-02 14:10:23 +0200332to a method when accessed as attributes. The non-data descriptor transforms an
Georg Brandl45cceeb2010-05-19 21:39:51 +0000333``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):
Serhiy Storchakadba90392016-05-10 12:01:23 +0300371 ... def f(x):
372 ... print(x)
373 ... f = staticmethod(f)
374 ...
Georg Brandl45cceeb2010-05-19 21:39:51 +0000375 >>> print(E.f(3))
376 3
377 >>> print(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):
Serhiy Storchakadba90392016-05-10 12:01:23 +0300384 "Emulate PyStaticMethod_Type() in Objects/funcobject.c"
Georg Brandl45cceeb2010-05-19 21:39:51 +0000385
Serhiy Storchakadba90392016-05-10 12:01:23 +0300386 def __init__(self, f):
387 self.f = f
Georg Brandl45cceeb2010-05-19 21:39:51 +0000388
Serhiy Storchakadba90392016-05-10 12:01:23 +0300389 def __get__(self, obj, objtype=None):
390 return self.f
Georg Brandl45cceeb2010-05-19 21:39:51 +0000391
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):
Serhiy Storchakadba90392016-05-10 12:01:23 +0300397 ... def f(klass, x):
398 ... return klass.__name__, x
399 ... f = classmethod(f)
400 ...
Georg Brandl45cceeb2010-05-19 21:39:51 +0000401 >>> 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
Raymond Hettinger686aae42013-03-10 09:50:37 -0700413 class Dict(object):
Georg Brandl45cceeb2010-05-19 21:39:51 +0000414 . . .
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):
Serhiy Storchakadba90392016-05-10 12:01:23 +0300432 "Emulate PyClassMethod_Type() in Objects/funcobject.c"
Georg Brandl45cceeb2010-05-19 21:39:51 +0000433
Serhiy Storchakadba90392016-05-10 12:01:23 +0300434 def __init__(self, f):
435 self.f = f
Georg Brandl45cceeb2010-05-19 21:39:51 +0000436
Serhiy Storchakadba90392016-05-10 12:01:23 +0300437 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
Georg Brandl45cceeb2010-05-19 21:39:51 +0000443