blob: 0b513f9c95f95ba33263c926452867a41cded4e8 [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
95descriptors, and assigns lowest priority to :meth:`__getattr__` if provided. The
Georg Brandl60203b42010-10-06 10:11:56 +000096full C implementation can be found in :c:func:`PyObject_GenericGetAttr()` in
Georg Brandl45cceeb2010-05-19 21:39:51 +000097`Objects/object.c <http://svn.python.org/view/python/trunk/Objects/object.c?view=markup>`_\.
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
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``
122and then returns ``A.__dict__['m'].__get__(obj, A)``. If not a descriptor,
123``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
Georg Brandl45cceeb2010-05-19 21:39:51 +0000127`Objects/typeobject.c <http://svn.python.org/view/python/trunk/Objects/typeobject.c?view=markup>`_
128and a pure Python equivalent can be found in `Guido's Tutorial`_.
129
130.. _`Guido's Tutorial`: http://www.python.org/2.2.3/descrintro.html#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 and unbound 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 self.__doc__ = doc
214
215 def __get__(self, obj, objtype=None):
216 if obj is None:
217 return self
218 if self.fget is None:
219 raise AttributeError, "unreadable attribute"
220 return self.fget(obj)
221
222 def __set__(self, obj, value):
223 if self.fset is None:
224 raise AttributeError, "can't set attribute"
225 self.fset(obj, value)
226
227 def __delete__(self, obj):
228 if self.fdel is None:
229 raise AttributeError, "can't delete attribute"
230 self.fdel(obj)
231
232The :func:`property` builtin helps whenever a user interface has granted
233attribute access and then subsequent changes require the intervention of a
234method.
235
236For instance, a spreadsheet class may grant access to a cell value through
237``Cell('b10').value``. Subsequent improvements to the program require the cell
238to be recalculated on every access; however, the programmer does not want to
239affect existing client code accessing the attribute directly. The solution is
240to wrap access to the value attribute in a property data descriptor::
241
242 class Cell(object):
243 . . .
244 def getvalue(self, obj):
245 "Recalculate cell before returning value"
246 self.recalc()
247 return obj._value
248 value = property(getvalue)
249
250
251Functions and Methods
252---------------------
253
254Python's object oriented features are built upon a function based environment.
255Using non-data descriptors, the two are merged seamlessly.
256
257Class dictionaries store methods as functions. In a class definition, methods
258are written using :keyword:`def` and :keyword:`lambda`, the usual tools for
259creating functions. The only difference from regular functions is that the
260first argument is reserved for the object instance. By Python convention, the
261instance reference is called *self* but may be called *this* or any other
262variable name.
263
264To support method calls, functions include the :meth:`__get__` method for
265binding methods during attribute access. This means that all functions are
266non-data descriptors which return bound or unbound methods depending whether
267they are invoked from an object or a class. In pure python, it works like
268this::
269
270 class Function(object):
271 . . .
272 def __get__(self, obj, objtype=None):
273 "Simulate func_descr_get() in Objects/funcobject.c"
274 return types.MethodType(self, obj, objtype)
275
276Running the interpreter shows how the function descriptor works in practice::
277
278 >>> class D(object):
279 def f(self, x):
280 return x
281
282 >>> d = D()
283 >>> D.__dict__['f'] # Stored internally as a function
284 <function f at 0x00C45070>
285 >>> D.f # Get from a class becomes an unbound method
286 <unbound method D.f>
287 >>> d.f # Get from an instance becomes a bound method
288 <bound method D.f of <__main__.D object at 0x00B18C90>>
289
290The output suggests that bound and unbound methods are two different types.
Georg Brandl6faee4e2010-09-21 14:48:28 +0000291While they could have been implemented that way, the actual C implementation of
Georg Brandl60203b42010-10-06 10:11:56 +0000292:c:type:`PyMethod_Type` in
Georg Brandl45cceeb2010-05-19 21:39:51 +0000293`Objects/classobject.c <http://svn.python.org/view/python/trunk/Objects/classobject.c?view=markup>`_
294is a single object with two different representations depending on whether the
295:attr:`im_self` field is set or is *NULL* (the C equivalent of *None*).
296
297Likewise, the effects of calling a method object depend on the :attr:`im_self`
298field. If set (meaning bound), the original function (stored in the
299:attr:`im_func` field) is called as expected with the first argument set to the
300instance. If unbound, all of the arguments are passed unchanged to the original
301function. The actual C implementation of :func:`instancemethod_call()` is only
302slightly more complex in that it includes some type checking.
303
304
305Static Methods and Class Methods
306--------------------------------
307
308Non-data descriptors provide a simple mechanism for variations on the usual
309patterns of binding functions into methods.
310
311To recap, functions have a :meth:`__get__` method so that they can be converted
312to a method when accessed as attributes. The non-data descriptor transforms a
313``obj.f(*args)`` call into ``f(obj, *args)``. Calling ``klass.f(*args)``
314becomes ``f(*args)``.
315
316This chart summarizes the binding and its two most useful variants:
317
318 +-----------------+----------------------+------------------+
319 | Transformation | Called from an | Called from a |
320 | | Object | Class |
321 +=================+======================+==================+
322 | function | f(obj, \*args) | f(\*args) |
323 +-----------------+----------------------+------------------+
324 | staticmethod | f(\*args) | f(\*args) |
325 +-----------------+----------------------+------------------+
326 | classmethod | f(type(obj), \*args) | f(klass, \*args) |
327 +-----------------+----------------------+------------------+
328
329Static methods return the underlying function without changes. Calling either
330``c.f`` or ``C.f`` is the equivalent of a direct lookup into
331``object.__getattribute__(c, "f")`` or ``object.__getattribute__(C, "f")``. As a
332result, the function becomes identically accessible from either an object or a
333class.
334
335Good candidates for static methods are methods that do not reference the
336``self`` variable.
337
338For instance, a statistics package may include a container class for
339experimental data. The class provides normal methods for computing the average,
340mean, median, and other descriptive statistics that depend on the data. However,
341there may be useful functions which are conceptually related but do not depend
342on the data. For instance, ``erf(x)`` is handy conversion routine that comes up
343in statistical work but does not directly depend on a particular dataset.
344It can be called either from an object or the class: ``s.erf(1.5) --> .9332`` or
345``Sample.erf(1.5) --> .9332``.
346
347Since staticmethods return the underlying function with no changes, the example
348calls are unexciting::
349
350 >>> class E(object):
351 def f(x):
352 print(x)
353 f = staticmethod(f)
354
355 >>> print(E.f(3))
356 3
357 >>> print(E().f(3))
358 3
359
360Using the non-data descriptor protocol, a pure Python version of
361:func:`staticmethod` would look like this::
362
363 class StaticMethod(object):
364 "Emulate PyStaticMethod_Type() in Objects/funcobject.c"
365
366 def __init__(self, f):
367 self.f = f
368
369 def __get__(self, obj, objtype=None):
370 return self.f
371
372Unlike static methods, class methods prepend the class reference to the
373argument list before calling the function. This format is the same
374for whether the caller is an object or a class::
375
376 >>> class E(object):
377 def f(klass, x):
378 return klass.__name__, x
379 f = classmethod(f)
380
381 >>> print(E.f(3))
382 ('E', 3)
383 >>> print(E().f(3))
384 ('E', 3)
385
386
387This behavior is useful whenever the function only needs to have a class
388reference and does not care about any underlying data. One use for classmethods
389is to create alternate class constructors. In Python 2.3, the classmethod
390:func:`dict.fromkeys` creates a new dictionary from a list of keys. The pure
391Python equivalent is::
392
393 class Dict:
394 . . .
395 def fromkeys(klass, iterable, value=None):
396 "Emulate dict_fromkeys() in Objects/dictobject.c"
397 d = klass()
398 for key in iterable:
399 d[key] = value
400 return d
401 fromkeys = classmethod(fromkeys)
402
403Now a new dictionary of unique keys can be constructed like this::
404
405 >>> Dict.fromkeys('abracadabra')
406 {'a': None, 'r': None, 'b': None, 'c': None, 'd': None}
407
408Using the non-data descriptor protocol, a pure Python version of
409:func:`classmethod` would look like this::
410
411 class ClassMethod(object):
412 "Emulate PyClassMethod_Type() in Objects/funcobject.c"
413
414 def __init__(self, f):
415 self.f = f
416
417 def __get__(self, obj, klass=None):
418 if klass is None:
419 klass = type(obj)
420 def newfunc(*args):
421 return self.f(klass, *args)
422 return newfunc
423