blob: 8c2e8d562153db6dc445ab917a5cc088e59f4229 [file] [log] [blame]
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001.. _descriptorhowto:
2
Georg Brandl45cceeb2010-05-19 21:39:51 +00003======================
4Descriptor HowTo Guide
5======================
6
7:Author: Raymond Hettinger
8:Contact: <python at rcn dot com>
9
10.. Contents::
11
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070012
13:term:`Descriptors <descriptor>` let objects customize attribute lookup,
14storage, and deletion.
15
Raymond Hettingere6a7ea42020-10-25 07:12:50 -070016This guide has four major sections:
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070017
181) The "primer" gives a basic overview, moving gently from simple examples,
19 adding one feature at a time. It is a great place to start.
20
212) The second section shows a complete, practical descriptor example. If you
22 already know the basics, start there.
23
243) The third section provides a more technical tutorial that goes into the
25 detailed mechanics of how descriptors work. Most people don't need this
26 level of detail.
27
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700284) The last section has pure Python equivalents for built-in descriptors that
29 are written in C. Read this if you're curious about how functions turn
Raymond Hettingere9208f02020-11-01 20:15:50 -080030 into bound methods or about the implementation of common tools like
31 :func:`classmethod`, :func:`staticmethod`, :func:`property`, and
32 :term:`__slots__`.
Raymond Hettingere6a7ea42020-10-25 07:12:50 -070033
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070034
35Primer
36^^^^^^
37
Raymond Hettinger4a9c6372020-10-24 20:34:39 -070038In this primer, we start with the most basic possible example and then we'll
39add new capabilities one by one.
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070040
41
42Simple example: A descriptor that returns a constant
43----------------------------------------------------
44
45The :class:`Ten` class is a descriptor that always returns the constant ``10``::
46
47
48 class Ten:
49 def __get__(self, obj, objtype=None):
50 return 10
51
52To use the descriptor, it must be stored as a class variable in another class::
53
54 class A:
55 x = 5 # Regular class attribute
Raymond Hettinger148c76b2020-11-01 09:10:06 -080056 y = Ten() # Descriptor instance
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070057
58An interactive session shows the difference between normal attribute lookup
59and descriptor lookup::
60
61 >>> a = A() # Make an instance of class A
62 >>> a.x # Normal attribute lookup
63 5
64 >>> a.y # Descriptor lookup
65 10
66
67In the ``a.x`` attribute lookup, the dot operator finds the value ``5`` stored
68in the class dictionary. In the ``a.y`` descriptor lookup, the dot operator
69calls the descriptor's :meth:`__get__()` method. That method returns ``10``.
70Note that the value ``10`` is not stored in either the class dictionary or the
71instance dictionary. Instead, the value ``10`` is computed on demand.
72
73This example shows how a simple descriptor works, but it isn't very useful.
74For retrieving constants, normal attribute lookup would be better.
75
76In the next section, we'll create something more useful, a dynamic lookup.
77
78
79Dynamic lookups
80---------------
81
82Interesting descriptors typically run computations instead of doing lookups::
83
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070084 import os
85
86 class DirectorySize:
87
88 def __get__(self, obj, objtype=None):
89 return len(os.listdir(obj.dirname))
90
91 class Directory:
92
Raymond Hettinger148c76b2020-11-01 09:10:06 -080093 size = DirectorySize() # Descriptor instance
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070094
95 def __init__(self, dirname):
96 self.dirname = dirname # Regular instance attribute
97
98An interactive session shows that the lookup is dynamic — it computes
99different, updated answers each time::
100
101 >>> g = Directory('games')
102 >>> s = Directory('songs')
103 >>> g.size # The games directory has three files
104 3
105 >>> os.system('touch games/newfile') # Add a fourth file to the directory
106 0
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700107 >>> g.size # Automatically updated
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700108 4
109 >>> s.size # The songs directory has twenty files
110 20
111
112Besides showing how descriptors can run computations, this example also
113reveals the purpose of the parameters to :meth:`__get__`. The *self*
114parameter is *size*, an instance of *DirectorySize*. The *obj* parameter is
Raymond Hettinger80318772020-11-06 01:30:17 -0800115either *g* or *s*, an instance of *Directory*. It is the *obj* parameter that
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700116lets the :meth:`__get__` method learn the target directory. The *objtype*
117parameter is the class *Directory*.
118
119
120Managed attributes
121------------------
122
123A popular use for descriptors is managing access to instance data. The
124descriptor is assigned to a public attribute in the class dictionary while the
125actual data is stored as a private attribute in the instance dictionary. The
126descriptor's :meth:`__get__` and :meth:`__set__` methods are triggered when
127the public attribute is accessed.
128
129In the following example, *age* is the public attribute and *_age* is the
130private attribute. When the public attribute is accessed, the descriptor logs
131the lookup or update::
132
133 import logging
134
135 logging.basicConfig(level=logging.INFO)
136
137 class LoggedAgeAccess:
138
139 def __get__(self, obj, objtype=None):
140 value = obj._age
141 logging.info('Accessing %r giving %r', 'age', value)
142 return value
143
144 def __set__(self, obj, value):
145 logging.info('Updating %r to %r', 'age', value)
146 obj._age = value
147
148 class Person:
149
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800150 age = LoggedAgeAccess() # Descriptor instance
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700151
152 def __init__(self, name, age):
153 self.name = name # Regular instance attribute
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800154 self.age = age # Calls __set__()
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700155
156 def birthday(self):
157 self.age += 1 # Calls both __get__() and __set__()
158
159
160An interactive session shows that all access to the managed attribute *age* is
161logged, but that the regular attribute *name* is not logged::
162
163 >>> mary = Person('Mary M', 30) # The initial age update is logged
164 INFO:root:Updating 'age' to 30
165 >>> dave = Person('David D', 40)
166 INFO:root:Updating 'age' to 40
167
168 >>> vars(mary) # The actual data is in a private attribute
169 {'name': 'Mary M', '_age': 30}
170 >>> vars(dave)
171 {'name': 'David D', '_age': 40}
172
173 >>> mary.age # Access the data and log the lookup
174 INFO:root:Accessing 'age' giving 30
175 30
176 >>> mary.birthday() # Updates are logged as well
177 INFO:root:Accessing 'age' giving 30
178 INFO:root:Updating 'age' to 31
179
180 >>> dave.name # Regular attribute lookup isn't logged
181 'David D'
182 >>> dave.age # Only the managed attribute is logged
183 INFO:root:Accessing 'age' giving 40
184 40
185
Raymond Hettinger80318772020-11-06 01:30:17 -0800186One major issue with this example is that the private name *_age* is hardwired in
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700187the *LoggedAgeAccess* class. That means that each instance can only have one
188logged attribute and that its name is unchangeable. In the next example,
189we'll fix that problem.
190
191
Raymond Hettingere9208f02020-11-01 20:15:50 -0800192Customized names
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700193----------------
194
Raymond Hettinger80318772020-11-06 01:30:17 -0800195When a class uses descriptors, it can inform each descriptor about which
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700196variable name was used.
197
198In this example, the :class:`Person` class has two descriptor instances,
199*name* and *age*. When the :class:`Person` class is defined, it makes a
200callback to :meth:`__set_name__` in *LoggedAccess* so that the field names can
201be recorded, giving each descriptor its own *public_name* and *private_name*::
202
203 import logging
204
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700205 logging.basicConfig(level=logging.INFO)
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700206
207 class LoggedAccess:
208
209 def __set_name__(self, owner, name):
210 self.public_name = name
211 self.private_name = f'_{name}'
212
213 def __get__(self, obj, objtype=None):
214 value = getattr(obj, self.private_name)
215 logging.info('Accessing %r giving %r', self.public_name, value)
216 return value
217
218 def __set__(self, obj, value):
219 logging.info('Updating %r to %r', self.public_name, value)
220 setattr(obj, self.private_name, value)
221
222 class Person:
223
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800224 name = LoggedAccess() # First descriptor instance
225 age = LoggedAccess() # Second descriptor instance
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700226
227 def __init__(self, name, age):
228 self.name = name # Calls the first descriptor
229 self.age = age # Calls the second descriptor
230
231 def birthday(self):
232 self.age += 1
233
234An interactive session shows that the :class:`Person` class has called
235:meth:`__set_name__` so that the field names would be recorded. Here
Raymond Hettinger80318772020-11-06 01:30:17 -0800236we call :func:`vars` to look up the descriptor without triggering it::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700237
238 >>> vars(vars(Person)['name'])
239 {'public_name': 'name', 'private_name': '_name'}
240 >>> vars(vars(Person)['age'])
241 {'public_name': 'age', 'private_name': '_age'}
242
243The new class now logs access to both *name* and *age*::
244
245 >>> pete = Person('Peter P', 10)
246 INFO:root:Updating 'name' to 'Peter P'
247 INFO:root:Updating 'age' to 10
248 >>> kate = Person('Catherine C', 20)
249 INFO:root:Updating 'name' to 'Catherine C'
250 INFO:root:Updating 'age' to 20
251
252The two *Person* instances contain only the private names::
253
254 >>> vars(pete)
255 {'_name': 'Peter P', '_age': 10}
256 >>> vars(kate)
257 {'_name': 'Catherine C', '_age': 20}
258
259
260Closing thoughts
261----------------
262
263A :term:`descriptor` is what we call any object that defines :meth:`__get__`,
264:meth:`__set__`, or :meth:`__delete__`.
265
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700266Optionally, descriptors can have a :meth:`__set_name__` method. This is only
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700267used in cases where a descriptor needs to know either the class where it was
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700268created or the name of class variable it was assigned to.
269
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700270Descriptors get invoked by the dot operator during attribute lookup. If a
271descriptor is accessed indirectly with ``vars(some_class)[descriptor_name]``,
272the descriptor instance is returned without invoking it.
273
274Descriptors only work when used as class variables. When put in instances,
275they have no effect.
276
277The main motivation for descriptors is to provide a hook allowing objects
278stored in class variables to control what happens during dotted lookup.
279
280Traditionally, the calling class controls what happens during lookup.
281Descriptors invert that relationship and allow the data being looked-up to
282have a say in the matter.
283
284Descriptors are used throughout the language. It is how functions turn into
285bound methods. Common tools like :func:`classmethod`, :func:`staticmethod`,
286:func:`property`, and :func:`functools.cached_property` are all implemented as
287descriptors.
288
289
290Complete Practical Example
291^^^^^^^^^^^^^^^^^^^^^^^^^^
292
293In this example, we create a practical and powerful tool for locating
294notoriously hard to find data corruption bugs.
295
296
297Validator class
298---------------
299
300A validator is a descriptor for managed attribute access. Prior to storing
301any data, it verifies that the new value meets various type and range
302restrictions. If those restrictions aren't met, it raises an exception to
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700303prevent data corruption at its source.
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700304
305This :class:`Validator` class is both an :term:`abstract base class` and a
306managed attribute descriptor::
307
308 from abc import ABC, abstractmethod
309
310 class Validator(ABC):
311
312 def __set_name__(self, owner, name):
313 self.private_name = f'_{name}'
314
315 def __get__(self, obj, objtype=None):
316 return getattr(obj, self.private_name)
317
318 def __set__(self, obj, value):
319 self.validate(value)
320 setattr(obj, self.private_name, value)
321
322 @abstractmethod
323 def validate(self, value):
324 pass
325
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700326Custom validators need to inherit from :class:`Validator` and must supply a
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700327:meth:`validate` method to test various restrictions as needed.
328
329
330Custom validators
331-----------------
332
333Here are three practical data validation utilities:
334
3351) :class:`OneOf` verifies that a value is one of a restricted set of options.
336
3372) :class:`Number` verifies that a value is either an :class:`int` or
338 :class:`float`. Optionally, it verifies that a value is between a given
339 minimum or maximum.
340
3413) :class:`String` verifies that a value is a :class:`str`. Optionally, it
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700342 validates a given minimum or maximum length. It can validate a
343 user-defined `predicate
344 <https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)>`_ as well.
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700345
346::
347
348 class OneOf(Validator):
349
350 def __init__(self, *options):
351 self.options = set(options)
352
353 def validate(self, value):
354 if value not in self.options:
355 raise ValueError(f'Expected {value!r} to be one of {self.options!r}')
356
357 class Number(Validator):
358
359 def __init__(self, minvalue=None, maxvalue=None):
360 self.minvalue = minvalue
361 self.maxvalue = maxvalue
362
363 def validate(self, value):
364 if not isinstance(value, (int, float)):
365 raise TypeError(f'Expected {value!r} to be an int or float')
366 if self.minvalue is not None and value < self.minvalue:
367 raise ValueError(
368 f'Expected {value!r} to be at least {self.minvalue!r}'
369 )
370 if self.maxvalue is not None and value > self.maxvalue:
371 raise ValueError(
372 f'Expected {value!r} to be no more than {self.maxvalue!r}'
373 )
374
375 class String(Validator):
376
377 def __init__(self, minsize=None, maxsize=None, predicate=None):
378 self.minsize = minsize
379 self.maxsize = maxsize
380 self.predicate = predicate
381
382 def validate(self, value):
383 if not isinstance(value, str):
384 raise TypeError(f'Expected {value!r} to be an str')
385 if self.minsize is not None and len(value) < self.minsize:
386 raise ValueError(
387 f'Expected {value!r} to be no smaller than {self.minsize!r}'
388 )
389 if self.maxsize is not None and len(value) > self.maxsize:
390 raise ValueError(
391 f'Expected {value!r} to be no bigger than {self.maxsize!r}'
392 )
393 if self.predicate is not None and not self.predicate(value):
394 raise ValueError(
395 f'Expected {self.predicate} to be true for {value!r}'
396 )
397
398
399Practical use
400-------------
401
402Here's how the data validators can be used in a real class::
403
404 class Component:
405
406 name = String(minsize=3, maxsize=10, predicate=str.isupper)
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700407 kind = OneOf('wood', 'metal', 'plastic')
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700408 quantity = Number(minvalue=0)
409
410 def __init__(self, name, kind, quantity):
411 self.name = name
412 self.kind = kind
413 self.quantity = quantity
414
415The descriptors prevent invalid instances from being created::
416
417 Component('WIDGET', 'metal', 5) # Allowed.
418 Component('Widget', 'metal', 5) # Blocked: 'Widget' is not all uppercase
419 Component('WIDGET', 'metle', 5) # Blocked: 'metle' is misspelled
420 Component('WIDGET', 'metal', -5) # Blocked: -5 is negative
421 Component('WIDGET', 'metal', 'V') # Blocked: 'V' isn't a number
422
423
424Technical Tutorial
425^^^^^^^^^^^^^^^^^^
426
427What follows is a more technical tutorial for the mechanics and details of how
428descriptors work.
429
430
Georg Brandl45cceeb2010-05-19 21:39:51 +0000431Abstract
432--------
433
434Defines descriptors, summarizes the protocol, and shows how descriptors are
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700435called. Provides an example showing how object relational mappings work.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000436
437Learning about descriptors not only provides access to a larger toolset, it
438creates a deeper understanding of how Python works and an appreciation for the
439elegance of its design.
440
441
Raymond Hettingere9208f02020-11-01 20:15:50 -0800442Definition and introduction
Georg Brandl45cceeb2010-05-19 21:39:51 +0000443---------------------------
444
445In general, a descriptor is an object attribute with "binding behavior", one
446whose attribute access has been overridden by methods in the descriptor
447protocol. Those methods are :meth:`__get__`, :meth:`__set__`, and
448:meth:`__delete__`. If any of those methods are defined for an object, it is
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700449said to be a :term:`descriptor`.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000450
451The default behavior for attribute access is to get, set, or delete the
452attribute from an object's dictionary. For instance, ``a.x`` has a lookup chain
453starting with ``a.__dict__['x']``, then ``type(a).__dict__['x']``, and
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700454continuing through the base classes of ``type(a)``. If the
Georg Brandl45cceeb2010-05-19 21:39:51 +0000455looked-up value is an object defining one of the descriptor methods, then Python
456may override the default behavior and invoke the descriptor method instead.
457Where this occurs in the precedence chain depends on which descriptor methods
Florent Xiclunaaa6c1d22011-12-12 18:54:29 +0100458were defined.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000459
460Descriptors are a powerful, general purpose protocol. They are the mechanism
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700461behind properties, methods, static methods, class methods, and
462:func:`super()`. They are used throughout Python itself. Descriptors
463simplify the underlying C code and offer a flexible set of new tools for
464everyday Python programs.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000465
466
Raymond Hettingere9208f02020-11-01 20:15:50 -0800467Descriptor protocol
Georg Brandl45cceeb2010-05-19 21:39:51 +0000468-------------------
469
NotAFile28ea4c22018-09-10 23:35:38 +0200470``descr.__get__(self, obj, type=None) -> value``
Georg Brandl45cceeb2010-05-19 21:39:51 +0000471
NotAFile28ea4c22018-09-10 23:35:38 +0200472``descr.__set__(self, obj, value) -> None``
Georg Brandl45cceeb2010-05-19 21:39:51 +0000473
NotAFile28ea4c22018-09-10 23:35:38 +0200474``descr.__delete__(self, obj) -> None``
Georg Brandl45cceeb2010-05-19 21:39:51 +0000475
476That is all there is to it. Define any of these methods and an object is
477considered a descriptor and can override default behavior upon being looked up
478as an attribute.
479
Aaron Hall, MBA4054b172018-05-20 19:46:42 -0400480If an object defines :meth:`__set__` or :meth:`__delete__`, it is considered
Georg Brandl45cceeb2010-05-19 21:39:51 +0000481a data descriptor. Descriptors that only define :meth:`__get__` are called
482non-data descriptors (they are typically used for methods but other uses are
483possible).
484
485Data and non-data descriptors differ in how overrides are calculated with
486respect to entries in an instance's dictionary. If an instance's dictionary
487has an entry with the same name as a data descriptor, the data descriptor
488takes precedence. If an instance's dictionary has an entry with the same
489name as a non-data descriptor, the dictionary entry takes precedence.
490
491To make a read-only data descriptor, define both :meth:`__get__` and
492:meth:`__set__` with the :meth:`__set__` raising an :exc:`AttributeError` when
493called. Defining the :meth:`__set__` method with an exception raising
494placeholder is enough to make it a data descriptor.
495
496
Raymond Hettingere9208f02020-11-01 20:15:50 -0800497Overview of descriptor invocation
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800498---------------------------------
Georg Brandl45cceeb2010-05-19 21:39:51 +0000499
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800500A descriptor can be called directly with ``desc.__get__(obj)`` or
501``desc.__get__(None, cls)``.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000502
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700503But it is more common for a descriptor to be invoked automatically from
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800504attribute access.
505
506The expression ``obj.x`` looks up the attribute ``x`` in the chain of
507namespaces for ``obj``. If the search finds a descriptor, its :meth:`__get__`
508method is invoked according to the precedence rules listed below.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000509
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700510The details of invocation depend on whether ``obj`` is an object, class, or
511instance of super.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000512
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700513
Raymond Hettingere9208f02020-11-01 20:15:50 -0800514Invocation from an instance
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800515---------------------------
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700516
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800517Instance lookup scans through a chain of namespaces giving data descriptors
518the highest priority, followed by instance variables, then non-data
519descriptors, then class variables, and lastly :meth:`__getattr__` if it is
520provided.
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700521
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800522If a descriptor is found for ``a.x``, then it is invoked with:
523``desc.__get__(a, type(a))``.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000524
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800525The logic for a dotted lookup is in :meth:`object.__getattribute__`. Here is
526a pure Python equivalent::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000527
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800528 def object_getattribute(obj, name):
529 "Emulate PyObject_GenericGetAttr() in Objects/object.c"
530 null = object()
531 objtype = type(obj)
532 value = getattr(objtype, name, null)
533 if value is not null and hasattr(value, '__get__'):
534 if hasattr(value, '__set__') or hasattr(value, '__delete__'):
535 return value.__get__(obj, objtype) # data descriptor
536 try:
537 return vars(obj)[name] # instance variable
538 except (KeyError, TypeError):
539 pass
540 if hasattr(value, '__get__'):
541 return value.__get__(obj, objtype) # non-data descriptor
542 if value is not null:
543 return value # class variable
544 # Emulate slot_tp_getattr_hook() in Objects/typeobject.c
545 if hasattr(objtype, '__getattr__'):
546 return objtype.__getattr__(obj, name) # __getattr__ hook
547 raise AttributeError(name)
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700548
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800549The :exc:`TypeError` exception handler is needed because the instance dictionary
550doesn't exist when its class defines :term:`__slots__`.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000551
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800552
Raymond Hettingere9208f02020-11-01 20:15:50 -0800553Invocation from a class
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800554-----------------------
555
556The logic for a dotted lookup such as ``A.x`` is in
557:meth:`type.__getattribute__`. The steps are similar to those for
558:meth:`object.__getattribute__` but the instance dictionary lookup is replaced
559by a search through the class's :term:`method resolution order`.
560
561If a descriptor is found, it is invoked with ``desc.__get__(None, A)``.
562
563The full C implementation can be found in :c:func:`type_getattro()` and
564:c:func:`_PyType_Lookup()` in :source:`Objects/typeobject.c`.
565
566
Raymond Hettingere9208f02020-11-01 20:15:50 -0800567Invocation from super
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800568---------------------
569
570The logic for super's dotted lookup is in the :meth:`__getattribute__` method for
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700571object returned by :class:`super()`.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000572
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800573A dotted lookup such as ``super(A, obj).m`` searches ``obj.__class__.__mro__``
574for the base class ``B`` immediately following ``A`` and then returns
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700575``B.__dict__['m'].__get__(obj, A)``. If not a descriptor, ``m`` is returned
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800576unchanged.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000577
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800578The full C implementation can be found in :c:func:`super_getattro()` in
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700579:source:`Objects/typeobject.c`. A pure Python equivalent can be found in
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800580`Guido's Tutorial
581<https://www.python.org/download/releases/2.2.3/descrintro/#cooperation>`_.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000582
Georg Brandl45cceeb2010-05-19 21:39:51 +0000583
Raymond Hettingere9208f02020-11-01 20:15:50 -0800584Summary of invocation logic
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800585---------------------------
586
587The mechanism for descriptors is embedded in the :meth:`__getattribute__()`
588methods for :class:`object`, :class:`type`, and :func:`super`.
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700589
590The important points to remember are:
591
592* Descriptors are invoked by the :meth:`__getattribute__` method.
593
594* Classes inherit this machinery from :class:`object`, :class:`type`, or
595 :func:`super`.
596
597* Overriding :meth:`__getattribute__` prevents automatic descriptor calls
598 because all the descriptor logic is in that method.
599
600* :meth:`object.__getattribute__` and :meth:`type.__getattribute__` make
601 different calls to :meth:`__get__`. The first includes the instance and may
602 include the class. The second puts in ``None`` for the instance and always
603 includes the class.
604
605* Data descriptors always override instance dictionaries.
606
607* Non-data descriptors may be overridden by instance dictionaries.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000608
609
Raymond Hettingere9208f02020-11-01 20:15:50 -0800610Automatic name notification
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700611---------------------------
612
613Sometimes it is desirable for a descriptor to know what class variable name it
614was assigned to. When a new class is created, the :class:`type` metaclass
615scans the dictionary of the new class. If any of the entries are descriptors
616and if they define :meth:`__set_name__`, that method is called with two
Raymond Hettinger80318772020-11-06 01:30:17 -0800617arguments. The *owner* is the class where the descriptor is used, and the
618*name* is the class variable the descriptor was assigned to.
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700619
620The implementation details are in :c:func:`type_new()` and
621:c:func:`set_names()` in :source:`Objects/typeobject.c`.
622
623Since the update logic is in :meth:`type.__new__`, notifications only take
624place at the time of class creation. If descriptors are added to the class
625afterwards, :meth:`__set_name__` will need to be called manually.
626
627
Raymond Hettingere9208f02020-11-01 20:15:50 -0800628ORM example
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700629-----------
Georg Brandl45cceeb2010-05-19 21:39:51 +0000630
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700631The following code is simplified skeleton showing how data descriptors could
632be used to implement an `object relational mapping
633<https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping>`_.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000634
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700635The essential idea is that the data is stored in an external database. The
636Python instances only hold keys to the database's tables. Descriptors take
637care of lookups or updates::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000638
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700639 class Field:
640
641 def __set_name__(self, owner, name):
642 self.fetch = f'SELECT {name} FROM {owner.table} WHERE {owner.key}=?;'
643 self.store = f'UPDATE {owner.table} SET {name}=? WHERE {owner.key}=?;'
Georg Brandl45cceeb2010-05-19 21:39:51 +0000644
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700645 def __get__(self, obj, objtype=None):
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700646 return conn.execute(self.fetch, [obj.key]).fetchone()[0]
Georg Brandl45cceeb2010-05-19 21:39:51 +0000647
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700648 def __set__(self, obj, value):
649 conn.execute(self.store, [value, obj.key])
650 conn.commit()
Georg Brandl45cceeb2010-05-19 21:39:51 +0000651
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700652We can use the :class:`Field` class to define "models" that describe the schema
653for each table in a database::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700654
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700655 class Movie:
656 table = 'Movies' # Table name
657 key = 'title' # Primary key
658 director = Field()
659 year = Field()
Georg Brandl45cceeb2010-05-19 21:39:51 +0000660
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700661 def __init__(self, key):
662 self.key = key
663
664 class Song:
665 table = 'Music'
666 key = 'title'
667 artist = Field()
668 year = Field()
669 genre = Field()
670
671 def __init__(self, key):
672 self.key = key
673
674An interactive session shows how data is retrieved from the database and how
675it can be updated::
676
677 >>> import sqlite3
678 >>> conn = sqlite3.connect('entertainment.db')
679
680 >>> Movie('Star Wars').director
681 'George Lucas'
682 >>> jaws = Movie('Jaws')
683 >>> f'Released in {jaws.year} by {jaws.director}'
684 'Released in 1975 by Steven Spielberg'
685
686 >>> Song('Country Roads').artist
687 'John Denver'
688
689 >>> Movie('Star Wars').director = 'J.J. Abrams'
690 >>> Movie('Star Wars').director
691 'J.J. Abrams'
692
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700693Pure Python Equivalents
694^^^^^^^^^^^^^^^^^^^^^^^
695
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700696The descriptor protocol is simple and offers exciting possibilities. Several
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800697use cases are so common that they have been prepackaged into built-in tools.
Raymond Hettingere9208f02020-11-01 20:15:50 -0800698Properties, bound methods, static methods, class methods, and \_\_slots\_\_ are
699all based on the descriptor protocol.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000700
701
702Properties
703----------
704
705Calling :func:`property` is a succinct way of building a data descriptor that
Raymond Hettinger80318772020-11-06 01:30:17 -0800706triggers a function call upon access to an attribute. Its signature is::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000707
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700708 property(fget=None, fset=None, fdel=None, doc=None) -> property
Georg Brandl45cceeb2010-05-19 21:39:51 +0000709
710The documentation shows a typical use to define a managed attribute ``x``::
711
Serhiy Storchakae042a452019-06-10 13:35:52 +0300712 class C:
Georg Brandl45cceeb2010-05-19 21:39:51 +0000713 def getx(self): return self.__x
714 def setx(self, value): self.__x = value
715 def delx(self): del self.__x
716 x = property(getx, setx, delx, "I'm the 'x' property.")
717
718To see how :func:`property` is implemented in terms of the descriptor protocol,
719here is a pure Python equivalent::
720
Serhiy Storchakae042a452019-06-10 13:35:52 +0300721 class Property:
Georg Brandl45cceeb2010-05-19 21:39:51 +0000722 "Emulate PyProperty_Type() in Objects/descrobject.c"
723
724 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
725 self.fget = fget
726 self.fset = fset
727 self.fdel = fdel
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700728 if doc is None and fget is not None:
729 doc = fget.__doc__
Georg Brandl45cceeb2010-05-19 21:39:51 +0000730 self.__doc__ = doc
731
732 def __get__(self, obj, objtype=None):
733 if obj is None:
734 return self
735 if self.fget is None:
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700736 raise AttributeError("unreadable attribute")
Georg Brandl45cceeb2010-05-19 21:39:51 +0000737 return self.fget(obj)
738
739 def __set__(self, obj, value):
740 if self.fset is None:
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700741 raise AttributeError("can't set attribute")
Georg Brandl45cceeb2010-05-19 21:39:51 +0000742 self.fset(obj, value)
743
744 def __delete__(self, obj):
745 if self.fdel is None:
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700746 raise AttributeError("can't delete attribute")
Georg Brandl45cceeb2010-05-19 21:39:51 +0000747 self.fdel(obj)
748
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700749 def getter(self, fget):
750 return type(self)(fget, self.fset, self.fdel, self.__doc__)
751
752 def setter(self, fset):
753 return type(self)(self.fget, fset, self.fdel, self.__doc__)
754
755 def deleter(self, fdel):
756 return type(self)(self.fget, self.fset, fdel, self.__doc__)
757
Georg Brandl45cceeb2010-05-19 21:39:51 +0000758The :func:`property` builtin helps whenever a user interface has granted
759attribute access and then subsequent changes require the intervention of a
760method.
761
762For instance, a spreadsheet class may grant access to a cell value through
763``Cell('b10').value``. Subsequent improvements to the program require the cell
764to be recalculated on every access; however, the programmer does not want to
765affect existing client code accessing the attribute directly. The solution is
766to wrap access to the value attribute in a property data descriptor::
767
Serhiy Storchakae042a452019-06-10 13:35:52 +0300768 class Cell:
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700769 ...
770
771 @property
772 def value(self):
_ = NaNb066edf2017-06-23 11:54:35 +0800773 "Recalculate the cell before returning value"
Georg Brandl45cceeb2010-05-19 21:39:51 +0000774 self.recalc()
_ = NaNb066edf2017-06-23 11:54:35 +0800775 return self._value
Georg Brandl45cceeb2010-05-19 21:39:51 +0000776
777
Raymond Hettingere9208f02020-11-01 20:15:50 -0800778Functions and methods
Georg Brandl45cceeb2010-05-19 21:39:51 +0000779---------------------
780
781Python's object oriented features are built upon a function based environment.
782Using non-data descriptors, the two are merged seamlessly.
783
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700784Functions stored in class dictionaries get turned into methods when invoked.
785Methods only differ from regular functions in that the object instance is
786prepended to the other arguments. By convention, the instance is called
787*self* but could be called *this* or any other variable name.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000788
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700789Methods can be created manually with :class:`types.MethodType` which is
790roughly equivalent to::
791
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700792 class MethodType:
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700793 "Emulate Py_MethodType in Objects/classobject.c"
794
795 def __init__(self, func, obj):
796 self.__func__ = func
797 self.__self__ = obj
798
799 def __call__(self, *args, **kwargs):
800 func = self.__func__
801 obj = self.__self__
802 return func(obj, *args, **kwargs)
803
804To support automatic creation of methods, functions include the
805:meth:`__get__` method for binding methods during attribute access. This
Raymond Hettinger80318772020-11-06 01:30:17 -0800806means that functions are non-data descriptors that return bound methods
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700807during dotted lookup from an instance. Here's how it works::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000808
Serhiy Storchakae042a452019-06-10 13:35:52 +0300809 class Function:
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700810 ...
811
Georg Brandl45cceeb2010-05-19 21:39:51 +0000812 def __get__(self, obj, objtype=None):
813 "Simulate func_descr_get() in Objects/funcobject.c"
Raymond Hettinger0d4497b2017-09-25 01:05:49 -0700814 if obj is None:
815 return self
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700816 return MethodType(self, obj)
Georg Brandl45cceeb2010-05-19 21:39:51 +0000817
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700818Running the following class in the interpreter shows how the function
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700819descriptor works in practice::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000820
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700821 class D:
822 def f(self, x):
823 return x
Raymond Hettinger0d4497b2017-09-25 01:05:49 -0700824
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700825The function has a :term:`qualified name` attribute to support introspection::
826
827 >>> D.f.__qualname__
828 'D.f'
829
830Accessing the function through the class dictionary does not invoke
831:meth:`__get__`. Instead, it just returns the underlying function object::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700832
Raymond Hettinger0d4497b2017-09-25 01:05:49 -0700833 >>> D.__dict__['f']
834 <function D.f at 0x00C45070>
835
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700836Dotted access from a class calls :meth:`__get__` which just returns the
837underlying function unchanged::
838
Raymond Hettinger0d4497b2017-09-25 01:05:49 -0700839 >>> D.f
840 <function D.f at 0x00C45070>
841
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700842The interesting behavior occurs during dotted access from an instance. The
843dotted lookup calls :meth:`__get__` which returns a bound method object::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700844
845 >>> d = D()
Raymond Hettinger0d4497b2017-09-25 01:05:49 -0700846 >>> d.f
Georg Brandl45cceeb2010-05-19 21:39:51 +0000847 <bound method D.f of <__main__.D object at 0x00B18C90>>
848
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700849Internally, the bound method stores the underlying function and the bound
850instance::
851
Raymond Hettinger0d4497b2017-09-25 01:05:49 -0700852 >>> d.f.__func__
853 <function D.f at 0x1012e5ae8>
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700854
Raymond Hettinger0d4497b2017-09-25 01:05:49 -0700855 >>> d.f.__self__
856 <__main__.D object at 0x1012e1f98>
Georg Brandl45cceeb2010-05-19 21:39:51 +0000857
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700858If you have ever wondered where *self* comes from in regular methods or where
859*cls* comes from in class methods, this is it!
860
Georg Brandl45cceeb2010-05-19 21:39:51 +0000861
Raymond Hettingere9208f02020-11-01 20:15:50 -0800862Static methods
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700863--------------
Georg Brandl45cceeb2010-05-19 21:39:51 +0000864
865Non-data descriptors provide a simple mechanism for variations on the usual
866patterns of binding functions into methods.
867
868To recap, functions have a :meth:`__get__` method so that they can be converted
Serhiy Storchakad65c9492015-11-02 14:10:23 +0200869to a method when accessed as attributes. The non-data descriptor transforms an
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700870``obj.f(*args)`` call into ``f(obj, *args)``. Calling ``cls.f(*args)``
Georg Brandl45cceeb2010-05-19 21:39:51 +0000871becomes ``f(*args)``.
872
873This chart summarizes the binding and its two most useful variants:
874
875 +-----------------+----------------------+------------------+
876 | Transformation | Called from an | Called from a |
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700877 | | object | class |
Georg Brandl45cceeb2010-05-19 21:39:51 +0000878 +=================+======================+==================+
879 | function | f(obj, \*args) | f(\*args) |
880 +-----------------+----------------------+------------------+
881 | staticmethod | f(\*args) | f(\*args) |
882 +-----------------+----------------------+------------------+
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700883 | classmethod | f(type(obj), \*args) | f(cls, \*args) |
Georg Brandl45cceeb2010-05-19 21:39:51 +0000884 +-----------------+----------------------+------------------+
885
886Static methods return the underlying function without changes. Calling either
887``c.f`` or ``C.f`` is the equivalent of a direct lookup into
888``object.__getattribute__(c, "f")`` or ``object.__getattribute__(C, "f")``. As a
889result, the function becomes identically accessible from either an object or a
890class.
891
892Good candidates for static methods are methods that do not reference the
893``self`` variable.
894
895For instance, a statistics package may include a container class for
896experimental data. The class provides normal methods for computing the average,
897mean, median, and other descriptive statistics that depend on the data. However,
898there may be useful functions which are conceptually related but do not depend
899on the data. For instance, ``erf(x)`` is handy conversion routine that comes up
900in statistical work but does not directly depend on a particular dataset.
901It can be called either from an object or the class: ``s.erf(1.5) --> .9332`` or
902``Sample.erf(1.5) --> .9332``.
903
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700904Since static methods return the underlying function with no changes, the
905example calls are unexciting::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000906
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700907 class E:
908 @staticmethod
909 def f(x):
910 print(x)
911
Shubham Aggarwalabbdd1f2019-03-20 08:25:55 +0530912 >>> E.f(3)
Georg Brandl45cceeb2010-05-19 21:39:51 +0000913 3
Shubham Aggarwalabbdd1f2019-03-20 08:25:55 +0530914 >>> E().f(3)
Georg Brandl45cceeb2010-05-19 21:39:51 +0000915 3
916
917Using the non-data descriptor protocol, a pure Python version of
918:func:`staticmethod` would look like this::
919
Serhiy Storchakae042a452019-06-10 13:35:52 +0300920 class StaticMethod:
Serhiy Storchakadba90392016-05-10 12:01:23 +0300921 "Emulate PyStaticMethod_Type() in Objects/funcobject.c"
Georg Brandl45cceeb2010-05-19 21:39:51 +0000922
Serhiy Storchakadba90392016-05-10 12:01:23 +0300923 def __init__(self, f):
924 self.f = f
Georg Brandl45cceeb2010-05-19 21:39:51 +0000925
Serhiy Storchakadba90392016-05-10 12:01:23 +0300926 def __get__(self, obj, objtype=None):
927 return self.f
Georg Brandl45cceeb2010-05-19 21:39:51 +0000928
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700929
Raymond Hettingere9208f02020-11-01 20:15:50 -0800930Class methods
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700931-------------
932
Georg Brandl45cceeb2010-05-19 21:39:51 +0000933Unlike static methods, class methods prepend the class reference to the
934argument list before calling the function. This format is the same
935for whether the caller is an object or a class::
936
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700937 class F:
938 @classmethod
939 def f(cls, x):
940 return cls.__name__, x
941
942 >>> print(F.f(3))
943 ('F', 3)
944 >>> print(F().f(3))
945 ('F', 3)
Georg Brandl45cceeb2010-05-19 21:39:51 +0000946
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700947This behavior is useful whenever the method only needs to have a class
948reference and does rely on data stored in a specific instance. One use for
949class methods is to create alternate class constructors. For example, the
950classmethod :func:`dict.fromkeys` creates a new dictionary from a list of
951keys. The pure Python equivalent is::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000952
Serhiy Storchakae042a452019-06-10 13:35:52 +0300953 class Dict:
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700954 ...
955
956 @classmethod
957 def fromkeys(cls, iterable, value=None):
Georg Brandl45cceeb2010-05-19 21:39:51 +0000958 "Emulate dict_fromkeys() in Objects/dictobject.c"
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700959 d = cls()
Georg Brandl45cceeb2010-05-19 21:39:51 +0000960 for key in iterable:
961 d[key] = value
962 return d
Georg Brandl45cceeb2010-05-19 21:39:51 +0000963
964Now a new dictionary of unique keys can be constructed like this::
965
966 >>> Dict.fromkeys('abracadabra')
967 {'a': None, 'r': None, 'b': None, 'c': None, 'd': None}
968
969Using the non-data descriptor protocol, a pure Python version of
970:func:`classmethod` would look like this::
971
Serhiy Storchakae042a452019-06-10 13:35:52 +0300972 class ClassMethod:
Serhiy Storchakadba90392016-05-10 12:01:23 +0300973 "Emulate PyClassMethod_Type() in Objects/funcobject.c"
Georg Brandl45cceeb2010-05-19 21:39:51 +0000974
Serhiy Storchakadba90392016-05-10 12:01:23 +0300975 def __init__(self, f):
976 self.f = f
Georg Brandl45cceeb2010-05-19 21:39:51 +0000977
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700978 def __get__(self, obj, cls=None):
979 if cls is None:
980 cls = type(obj)
Raymond Hettinger8e5b0fd2020-10-23 18:37:27 -0700981 if hasattr(obj, '__get__'):
982 return self.f.__get__(cls)
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700983 return MethodType(self.f, cls)
Raymond Hettinger8e5b0fd2020-10-23 18:37:27 -0700984
985The code path for ``hasattr(obj, '__get__')`` was added in Python 3.9 and
986makes it possible for :func:`classmethod` to support chained decorators.
987For example, a classmethod and property could be chained together::
988
989 class G:
990 @classmethod
991 @property
992 def __doc__(cls):
993 return f'A doc for {cls.__name__!r}'
Raymond Hettinger74fa4642020-11-01 18:02:37 -0800994
Raymond Hettingere9208f02020-11-01 20:15:50 -0800995Member objects and __slots__
996----------------------------
Raymond Hettinger74fa4642020-11-01 18:02:37 -0800997
998When a class defines ``__slots__``, it replaces instance dictionaries with a
999fixed-length array of slot values. From a user point of view that has
1000several effects:
1001
10021. Provides immediate detection of bugs due to misspelled attribute
1003assignments. Only attribute names specified in ``__slots__`` are allowed::
1004
1005 class Vehicle:
1006 __slots__ = ('id_number', 'make', 'model')
1007
1008 >>> auto = Vehicle()
1009 >>> auto.id_nubmer = 'VYE483814LQEX'
1010 Traceback (most recent call last):
1011 ...
1012 AttributeError: 'Vehicle' object has no attribute 'id_nubmer'
1013
10142. Helps create immutable objects where descriptors manage access to private
1015attributes stored in ``__slots__``::
1016
1017 class Immutable:
1018
Raymond Hettinger80318772020-11-06 01:30:17 -08001019 __slots__ = ('_dept', '_name') # Replace the instance dictionary
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001020
1021 def __init__(self, dept, name):
1022 self._dept = dept # Store to private attribute
1023 self._name = name # Store to private attribute
1024
1025 @property # Read-only descriptor
1026 def dept(self):
1027 return self._dept
1028
1029 @property
1030 def name(self): # Read-only descriptor
1031 return self._name
1032
1033 mark = Immutable('Botany', 'Mark Watney') # Create an immutable instance
1034
10353. Saves memory. On a 64-bit Linux build, an instance with two attributes
1036takes 48 bytes with ``__slots__`` and 152 bytes without. This `flyweight
1037design pattern <https://en.wikipedia.org/wiki/Flyweight_pattern>`_ likely only
1038matters when a large number of instances are going to be created.
1039
10404. Blocks tools like :func:`functools.cached_property` which require an
1041instance dictionary to function correctly::
1042
1043 from functools import cached_property
1044
1045 class CP:
1046 __slots__ = () # Eliminates the instance dict
1047
1048 @cached_property # Requires an instance dict
1049 def pi(self):
1050 return 4 * sum((-1.0)**n / (2.0*n + 1.0)
1051 for n in reversed(range(100_000)))
1052
1053 >>> CP().pi
1054 Traceback (most recent call last):
1055 ...
1056 TypeError: No '__dict__' attribute on 'CP' instance to cache 'pi' property.
1057
1058It's not possible to create an exact drop-in pure Python version of
1059``__slots__`` because it requires direct access to C structures and control
1060over object memory allocation. However, we can build a mostly faithful
1061simulation where the actual C structure for slots is emulated by a private
1062``_slotvalues`` list. Reads and writes to that private structure are managed
1063by member descriptors::
1064
1065 class Member:
1066
1067 def __init__(self, name, clsname, offset):
1068 'Emulate PyMemberDef in Include/structmember.h'
1069 # Also see descr_new() in Objects/descrobject.c
1070 self.name = name
1071 self.clsname = clsname
1072 self.offset = offset
1073
1074 def __get__(self, obj, objtype=None):
1075 'Emulate member_get() in Objects/descrobject.c'
1076 # Also see PyMember_GetOne() in Python/structmember.c
1077 return obj._slotvalues[self.offset]
1078
1079 def __set__(self, obj, value):
1080 'Emulate member_set() in Objects/descrobject.c'
1081 obj._slotvalues[self.offset] = value
1082
1083 def __repr__(self):
1084 'Emulate member_repr() in Objects/descrobject.c'
1085 return f'<Member {self.name!r} of {self.clsname!r}>'
1086
1087The :meth:`type.__new__` method takes care of adding member objects to class
1088variables. The :meth:`object.__new__` method takes care of creating instances
Raymond Hettinger80318772020-11-06 01:30:17 -08001089that have slots instead of an instance dictionary. Here is a rough equivalent
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001090in pure Python::
1091
1092 class Type(type):
1093 'Simulate how the type metaclass adds member objects for slots'
1094
1095 def __new__(mcls, clsname, bases, mapping):
1096 'Emuluate type_new() in Objects/typeobject.c'
1097 # type_new() calls PyTypeReady() which calls add_methods()
1098 slot_names = mapping.get('slot_names', [])
1099 for offset, name in enumerate(slot_names):
1100 mapping[name] = Member(name, clsname, offset)
1101 return type.__new__(mcls, clsname, bases, mapping)
1102
1103 class Object:
1104 'Simulate how object.__new__() allocates memory for __slots__'
1105
1106 def __new__(cls, *args):
1107 'Emulate object_new() in Objects/typeobject.c'
1108 inst = super().__new__(cls)
1109 if hasattr(cls, 'slot_names'):
1110 inst._slotvalues = [None] * len(cls.slot_names)
1111 return inst
1112
1113To use the simulation in a real class, just inherit from :class:`Object` and
1114set the :term:`metaclass` to :class:`Type`::
1115
1116 class H(Object, metaclass=Type):
1117
1118 slot_names = ['x', 'y']
1119
1120 def __init__(self, x, y):
1121 self.x = x
1122 self.y = y
1123
1124At this point, the metaclass has loaded member objects for *x* and *y*::
1125
1126 >>> import pprint
1127 >>> pprint.pp(dict(vars(H)))
1128 {'__module__': '__main__',
1129 'slot_names': ['x', 'y'],
1130 '__init__': <function H.__init__ at 0x7fb5d302f9d0>,
1131 'x': <Member 'x' of 'H'>,
1132 'y': <Member 'y' of 'H'>,
1133 '__doc__': None}
1134
1135When instances are created, they have a ``slot_values`` list where the
1136attributes are stored::
1137
1138 >>> h = H(10, 20)
1139 >>> vars(h)
1140 {'_slotvalues': [10, 20]}
1141 >>> h.x = 55
1142 >>> vars(h)
1143 {'_slotvalues': [55, 20]}
1144
1145Unlike the real ``__slots__``, this simulation does have an instance
1146dictionary just to hold the ``_slotvalues`` array. So, unlike the real code,
1147this simulation doesn't block assignments to misspelled attributes::
1148
1149 >>> h.xz = 30 # For actual __slots__ this would raise an AttributeError