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