blob: e94f0ef88416edbf1d0219610cda375bb9e1ea9f [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,
Raymond Hettingerc272d402020-11-15 17:44:28 -080019 adding one feature at a time. Start here if you're new to descriptors.
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070020
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
Raymond Hettingerc272d402020-11-15 17:44:28 -080045The :class:`Ten` class is a descriptor that always returns the constant ``10``
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -080046from its :meth:`__get__` method:
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070047
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -080048.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070049
50 class Ten:
51 def __get__(self, obj, objtype=None):
52 return 10
53
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -080054To use the descriptor, it must be stored as a class variable in another class:
55
56.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070057
58 class A:
59 x = 5 # Regular class attribute
Raymond Hettinger148c76b2020-11-01 09:10:06 -080060 y = Ten() # Descriptor instance
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070061
62An interactive session shows the difference between normal attribute lookup
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -080063and descriptor lookup:
64
65.. doctest::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070066
67 >>> a = A() # Make an instance of class A
68 >>> a.x # Normal attribute lookup
69 5
70 >>> a.y # Descriptor lookup
71 10
72
Raymond Hettingerc272d402020-11-15 17:44:28 -080073In the ``a.x`` attribute lookup, the dot operator finds the key ``x`` and the
74value ``5`` in the class dictionary. In the ``a.y`` lookup, the dot operator
75finds a descriptor instance, recognized by its ``__get__`` method, and calls
76that method which returns ``10``.
77
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070078Note that the value ``10`` is not stored in either the class dictionary or the
79instance dictionary. Instead, the value ``10`` is computed on demand.
80
81This example shows how a simple descriptor works, but it isn't very useful.
82For retrieving constants, normal attribute lookup would be better.
83
84In the next section, we'll create something more useful, a dynamic lookup.
85
86
87Dynamic lookups
88---------------
89
Raymond Hettingerc272d402020-11-15 17:44:28 -080090Interesting descriptors typically run computations instead of returning
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -080091constants:
92
93.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070094
Raymond Hettinger8d3d7312020-10-23 12:55:39 -070095 import os
96
97 class DirectorySize:
98
99 def __get__(self, obj, objtype=None):
100 return len(os.listdir(obj.dirname))
101
102 class Directory:
103
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800104 size = DirectorySize() # Descriptor instance
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700105
106 def __init__(self, dirname):
107 self.dirname = dirname # Regular instance attribute
108
109An interactive session shows that the lookup is dynamic — it computes
110different, updated answers each time::
111
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700112 >>> s = Directory('songs')
Raymond Hettingerc272d402020-11-15 17:44:28 -0800113 >>> g = Directory('games')
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700114 >>> s.size # The songs directory has twenty files
115 20
Raymond Hettingerc272d402020-11-15 17:44:28 -0800116 >>> g.size # The games directory has three files
117 3
118 >>> open('games/newfile').close() # Add a fourth file to the directory
119 >>> g.size # File count is automatically updated
120 4
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700121
122Besides showing how descriptors can run computations, this example also
123reveals the purpose of the parameters to :meth:`__get__`. The *self*
124parameter is *size*, an instance of *DirectorySize*. The *obj* parameter is
Raymond Hettinger80318772020-11-06 01:30:17 -0800125either *g* or *s*, an instance of *Directory*. It is the *obj* parameter that
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700126lets the :meth:`__get__` method learn the target directory. The *objtype*
127parameter is the class *Directory*.
128
129
130Managed attributes
131------------------
132
133A popular use for descriptors is managing access to instance data. The
134descriptor is assigned to a public attribute in the class dictionary while the
135actual data is stored as a private attribute in the instance dictionary. The
136descriptor's :meth:`__get__` and :meth:`__set__` methods are triggered when
137the public attribute is accessed.
138
139In the following example, *age* is the public attribute and *_age* is the
140private attribute. When the public attribute is accessed, the descriptor logs
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800141the lookup or update:
142
143.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700144
145 import logging
146
147 logging.basicConfig(level=logging.INFO)
148
149 class LoggedAgeAccess:
150
151 def __get__(self, obj, objtype=None):
152 value = obj._age
153 logging.info('Accessing %r giving %r', 'age', value)
154 return value
155
156 def __set__(self, obj, value):
157 logging.info('Updating %r to %r', 'age', value)
158 obj._age = value
159
160 class Person:
161
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800162 age = LoggedAgeAccess() # Descriptor instance
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700163
164 def __init__(self, name, age):
165 self.name = name # Regular instance attribute
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800166 self.age = age # Calls __set__()
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700167
168 def birthday(self):
169 self.age += 1 # Calls both __get__() and __set__()
170
171
172An interactive session shows that all access to the managed attribute *age* is
173logged, but that the regular attribute *name* is not logged::
174
175 >>> mary = Person('Mary M', 30) # The initial age update is logged
176 INFO:root:Updating 'age' to 30
177 >>> dave = Person('David D', 40)
178 INFO:root:Updating 'age' to 40
179
180 >>> vars(mary) # The actual data is in a private attribute
181 {'name': 'Mary M', '_age': 30}
182 >>> vars(dave)
183 {'name': 'David D', '_age': 40}
184
185 >>> mary.age # Access the data and log the lookup
186 INFO:root:Accessing 'age' giving 30
187 30
188 >>> mary.birthday() # Updates are logged as well
189 INFO:root:Accessing 'age' giving 30
190 INFO:root:Updating 'age' to 31
191
192 >>> dave.name # Regular attribute lookup isn't logged
193 'David D'
194 >>> dave.age # Only the managed attribute is logged
195 INFO:root:Accessing 'age' giving 40
196 40
197
Raymond Hettinger80318772020-11-06 01:30:17 -0800198One major issue with this example is that the private name *_age* is hardwired in
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700199the *LoggedAgeAccess* class. That means that each instance can only have one
200logged attribute and that its name is unchangeable. In the next example,
201we'll fix that problem.
202
203
Raymond Hettingere9208f02020-11-01 20:15:50 -0800204Customized names
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700205----------------
206
Raymond Hettinger80318772020-11-06 01:30:17 -0800207When a class uses descriptors, it can inform each descriptor about which
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700208variable name was used.
209
210In this example, the :class:`Person` class has two descriptor instances,
211*name* and *age*. When the :class:`Person` class is defined, it makes a
212callback to :meth:`__set_name__` in *LoggedAccess* so that the field names can
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800213be recorded, giving each descriptor its own *public_name* and *private_name*:
214
215.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700216
217 import logging
218
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700219 logging.basicConfig(level=logging.INFO)
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700220
221 class LoggedAccess:
222
223 def __set_name__(self, owner, name):
224 self.public_name = name
Raymond Hettingerc272d402020-11-15 17:44:28 -0800225 self.private_name = '_' + name
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700226
227 def __get__(self, obj, objtype=None):
228 value = getattr(obj, self.private_name)
229 logging.info('Accessing %r giving %r', self.public_name, value)
230 return value
231
232 def __set__(self, obj, value):
233 logging.info('Updating %r to %r', self.public_name, value)
234 setattr(obj, self.private_name, value)
235
236 class Person:
237
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800238 name = LoggedAccess() # First descriptor instance
239 age = LoggedAccess() # Second descriptor instance
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700240
241 def __init__(self, name, age):
242 self.name = name # Calls the first descriptor
243 self.age = age # Calls the second descriptor
244
245 def birthday(self):
246 self.age += 1
247
248An interactive session shows that the :class:`Person` class has called
249:meth:`__set_name__` so that the field names would be recorded. Here
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800250we call :func:`vars` to look up the descriptor without triggering it:
251
252.. doctest::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700253
254 >>> vars(vars(Person)['name'])
255 {'public_name': 'name', 'private_name': '_name'}
256 >>> vars(vars(Person)['age'])
257 {'public_name': 'age', 'private_name': '_age'}
258
259The new class now logs access to both *name* and *age*::
260
261 >>> pete = Person('Peter P', 10)
262 INFO:root:Updating 'name' to 'Peter P'
263 INFO:root:Updating 'age' to 10
264 >>> kate = Person('Catherine C', 20)
265 INFO:root:Updating 'name' to 'Catherine C'
266 INFO:root:Updating 'age' to 20
267
268The two *Person* instances contain only the private names::
269
270 >>> vars(pete)
271 {'_name': 'Peter P', '_age': 10}
272 >>> vars(kate)
273 {'_name': 'Catherine C', '_age': 20}
274
275
276Closing thoughts
277----------------
278
279A :term:`descriptor` is what we call any object that defines :meth:`__get__`,
280:meth:`__set__`, or :meth:`__delete__`.
281
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700282Optionally, descriptors can have a :meth:`__set_name__` method. This is only
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700283used in cases where a descriptor needs to know either the class where it was
Raymond Hettingerc272d402020-11-15 17:44:28 -0800284created or the name of class variable it was assigned to. (This method, if
285present, is called even if the class is not a descriptor.)
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700286
Raymond Hettingerc272d402020-11-15 17:44:28 -0800287Descriptors get invoked by the dot "operator" during attribute lookup. If a
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700288descriptor is accessed indirectly with ``vars(some_class)[descriptor_name]``,
289the descriptor instance is returned without invoking it.
290
291Descriptors only work when used as class variables. When put in instances,
292they have no effect.
293
294The main motivation for descriptors is to provide a hook allowing objects
Raymond Hettingerc272d402020-11-15 17:44:28 -0800295stored in class variables to control what happens during attribute lookup.
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700296
297Traditionally, the calling class controls what happens during lookup.
298Descriptors invert that relationship and allow the data being looked-up to
299have a say in the matter.
300
301Descriptors are used throughout the language. It is how functions turn into
302bound methods. Common tools like :func:`classmethod`, :func:`staticmethod`,
303:func:`property`, and :func:`functools.cached_property` are all implemented as
304descriptors.
305
306
307Complete Practical Example
308^^^^^^^^^^^^^^^^^^^^^^^^^^
309
310In this example, we create a practical and powerful tool for locating
311notoriously hard to find data corruption bugs.
312
313
314Validator class
315---------------
316
317A validator is a descriptor for managed attribute access. Prior to storing
318any data, it verifies that the new value meets various type and range
319restrictions. If those restrictions aren't met, it raises an exception to
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700320prevent data corruption at its source.
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700321
322This :class:`Validator` class is both an :term:`abstract base class` and a
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800323managed attribute descriptor:
324
325.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700326
327 from abc import ABC, abstractmethod
328
329 class Validator(ABC):
330
331 def __set_name__(self, owner, name):
Raymond Hettingerc272d402020-11-15 17:44:28 -0800332 self.private_name = '_' + name
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700333
334 def __get__(self, obj, objtype=None):
335 return getattr(obj, self.private_name)
336
337 def __set__(self, obj, value):
338 self.validate(value)
339 setattr(obj, self.private_name, value)
340
341 @abstractmethod
342 def validate(self, value):
343 pass
344
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700345Custom validators need to inherit from :class:`Validator` and must supply a
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700346:meth:`validate` method to test various restrictions as needed.
347
348
349Custom validators
350-----------------
351
352Here are three practical data validation utilities:
353
3541) :class:`OneOf` verifies that a value is one of a restricted set of options.
355
3562) :class:`Number` verifies that a value is either an :class:`int` or
357 :class:`float`. Optionally, it verifies that a value is between a given
358 minimum or maximum.
359
3603) :class:`String` verifies that a value is a :class:`str`. Optionally, it
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700361 validates a given minimum or maximum length. It can validate a
362 user-defined `predicate
363 <https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)>`_ as well.
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700364
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800365.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700366
367 class OneOf(Validator):
368
369 def __init__(self, *options):
370 self.options = set(options)
371
372 def validate(self, value):
373 if value not in self.options:
374 raise ValueError(f'Expected {value!r} to be one of {self.options!r}')
375
376 class Number(Validator):
377
378 def __init__(self, minvalue=None, maxvalue=None):
379 self.minvalue = minvalue
380 self.maxvalue = maxvalue
381
382 def validate(self, value):
383 if not isinstance(value, (int, float)):
384 raise TypeError(f'Expected {value!r} to be an int or float')
385 if self.minvalue is not None and value < self.minvalue:
386 raise ValueError(
387 f'Expected {value!r} to be at least {self.minvalue!r}'
388 )
389 if self.maxvalue is not None and value > self.maxvalue:
390 raise ValueError(
391 f'Expected {value!r} to be no more than {self.maxvalue!r}'
392 )
393
394 class String(Validator):
395
396 def __init__(self, minsize=None, maxsize=None, predicate=None):
397 self.minsize = minsize
398 self.maxsize = maxsize
399 self.predicate = predicate
400
401 def validate(self, value):
402 if not isinstance(value, str):
403 raise TypeError(f'Expected {value!r} to be an str')
404 if self.minsize is not None and len(value) < self.minsize:
405 raise ValueError(
406 f'Expected {value!r} to be no smaller than {self.minsize!r}'
407 )
408 if self.maxsize is not None and len(value) > self.maxsize:
409 raise ValueError(
410 f'Expected {value!r} to be no bigger than {self.maxsize!r}'
411 )
412 if self.predicate is not None and not self.predicate(value):
413 raise ValueError(
414 f'Expected {self.predicate} to be true for {value!r}'
415 )
416
417
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800418Practical application
419---------------------
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700420
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800421Here's how the data validators can be used in a real class:
422
423.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700424
425 class Component:
426
427 name = String(minsize=3, maxsize=10, predicate=str.isupper)
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700428 kind = OneOf('wood', 'metal', 'plastic')
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700429 quantity = Number(minvalue=0)
430
431 def __init__(self, name, kind, quantity):
432 self.name = name
433 self.kind = kind
434 self.quantity = quantity
435
436The descriptors prevent invalid instances from being created::
437
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800438 >>> Component('Widget', 'metal', 5) # Blocked: 'Widget' is not all uppercase
439 Traceback (most recent call last):
440 ...
441 ValueError: Expected <method 'isupper' of 'str' objects> to be true for 'Widget'
442
443 >>> Component('WIDGET', 'metle', 5) # Blocked: 'metle' is misspelled
444 Traceback (most recent call last):
445 ...
446 ValueError: Expected 'metle' to be one of {'metal', 'plastic', 'wood'}
447
448 >>> Component('WIDGET', 'metal', -5) # Blocked: -5 is negative
449 Traceback (most recent call last):
450 ...
451 ValueError: Expected -5 to be at least 0
452 >>> Component('WIDGET', 'metal', 'V') # Blocked: 'V' isn't a number
453 Traceback (most recent call last):
454 ...
455 TypeError: Expected 'V' to be an int or float
456
457 >>> c = Component('WIDGET', 'metal', 5) # Allowed: The inputs are valid
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700458
459
460Technical Tutorial
461^^^^^^^^^^^^^^^^^^
462
463What follows is a more technical tutorial for the mechanics and details of how
464descriptors work.
465
466
Georg Brandl45cceeb2010-05-19 21:39:51 +0000467Abstract
468--------
469
470Defines descriptors, summarizes the protocol, and shows how descriptors are
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700471called. Provides an example showing how object relational mappings work.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000472
473Learning about descriptors not only provides access to a larger toolset, it
Raymond Hettingerc272d402020-11-15 17:44:28 -0800474creates a deeper understanding of how Python works.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000475
476
Raymond Hettingere9208f02020-11-01 20:15:50 -0800477Definition and introduction
Georg Brandl45cceeb2010-05-19 21:39:51 +0000478---------------------------
479
Raymond Hettingerc272d402020-11-15 17:44:28 -0800480In general, a descriptor is an attribute value that has one of the methods in
481the descriptor protocol. Those methods are :meth:`__get__`, :meth:`__set__`,
482and :meth:`__delete__`. If any of those methods are defined for an the
483attribute, it is said to be a :term:`descriptor`.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000484
485The default behavior for attribute access is to get, set, or delete the
486attribute from an object's dictionary. For instance, ``a.x`` has a lookup chain
487starting with ``a.__dict__['x']``, then ``type(a).__dict__['x']``, and
Raymond Hettingerc272d402020-11-15 17:44:28 -0800488continuing through the method resolution order of ``type(a)``. If the
Georg Brandl45cceeb2010-05-19 21:39:51 +0000489looked-up value is an object defining one of the descriptor methods, then Python
490may override the default behavior and invoke the descriptor method instead.
491Where this occurs in the precedence chain depends on which descriptor methods
Florent Xiclunaaa6c1d22011-12-12 18:54:29 +0100492were defined.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000493
494Descriptors are a powerful, general purpose protocol. They are the mechanism
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700495behind properties, methods, static methods, class methods, and
496:func:`super()`. They are used throughout Python itself. Descriptors
497simplify the underlying C code and offer a flexible set of new tools for
498everyday Python programs.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000499
500
Raymond Hettingere9208f02020-11-01 20:15:50 -0800501Descriptor protocol
Georg Brandl45cceeb2010-05-19 21:39:51 +0000502-------------------
503
NotAFile28ea4c22018-09-10 23:35:38 +0200504``descr.__get__(self, obj, type=None) -> value``
Georg Brandl45cceeb2010-05-19 21:39:51 +0000505
NotAFile28ea4c22018-09-10 23:35:38 +0200506``descr.__set__(self, obj, value) -> None``
Georg Brandl45cceeb2010-05-19 21:39:51 +0000507
NotAFile28ea4c22018-09-10 23:35:38 +0200508``descr.__delete__(self, obj) -> None``
Georg Brandl45cceeb2010-05-19 21:39:51 +0000509
510That is all there is to it. Define any of these methods and an object is
511considered a descriptor and can override default behavior upon being looked up
512as an attribute.
513
Aaron Hall, MBA4054b172018-05-20 19:46:42 -0400514If an object defines :meth:`__set__` or :meth:`__delete__`, it is considered
Georg Brandl45cceeb2010-05-19 21:39:51 +0000515a data descriptor. Descriptors that only define :meth:`__get__` are called
Raymond Hettingerc272d402020-11-15 17:44:28 -0800516non-data descriptors (they are often used for methods but other uses are
Georg Brandl45cceeb2010-05-19 21:39:51 +0000517possible).
518
519Data and non-data descriptors differ in how overrides are calculated with
520respect to entries in an instance's dictionary. If an instance's dictionary
521has an entry with the same name as a data descriptor, the data descriptor
522takes precedence. If an instance's dictionary has an entry with the same
523name as a non-data descriptor, the dictionary entry takes precedence.
524
525To make a read-only data descriptor, define both :meth:`__get__` and
526:meth:`__set__` with the :meth:`__set__` raising an :exc:`AttributeError` when
527called. Defining the :meth:`__set__` method with an exception raising
528placeholder is enough to make it a data descriptor.
529
530
Raymond Hettingere9208f02020-11-01 20:15:50 -0800531Overview of descriptor invocation
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800532---------------------------------
Georg Brandl45cceeb2010-05-19 21:39:51 +0000533
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800534A descriptor can be called directly with ``desc.__get__(obj)`` or
535``desc.__get__(None, cls)``.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000536
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700537But it is more common for a descriptor to be invoked automatically from
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800538attribute access.
539
540The expression ``obj.x`` looks up the attribute ``x`` in the chain of
Raymond Hettingerc272d402020-11-15 17:44:28 -0800541namespaces for ``obj``. If the search finds a descriptor outside of the
542instance ``__dict__``, its :meth:`__get__` method is invoked according to the
543precedence rules listed below.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000544
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700545The details of invocation depend on whether ``obj`` is an object, class, or
546instance of super.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000547
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700548
Raymond Hettingere9208f02020-11-01 20:15:50 -0800549Invocation from an instance
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800550---------------------------
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700551
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800552Instance lookup scans through a chain of namespaces giving data descriptors
553the highest priority, followed by instance variables, then non-data
554descriptors, then class variables, and lastly :meth:`__getattr__` if it is
555provided.
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700556
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800557If a descriptor is found for ``a.x``, then it is invoked with:
558``desc.__get__(a, type(a))``.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000559
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800560The logic for a dotted lookup is in :meth:`object.__getattribute__`. Here is
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800561a pure Python equivalent:
562
563.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000564
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800565 def object_getattribute(obj, name):
566 "Emulate PyObject_GenericGetAttr() in Objects/object.c"
567 null = object()
568 objtype = type(obj)
Raymond Hettingerc272d402020-11-15 17:44:28 -0800569 cls_var = getattr(objtype, name, null)
570 descr_get = getattr(type(cls_var), '__get__', null)
571 if descr_get is not null:
572 if (hasattr(type(cls_var), '__set__')
573 or hasattr(type(cls_var), '__delete__')):
574 return descr_get(cls_var, obj, objtype) # data descriptor
575 if hasattr(obj, '__dict__') and name in vars(obj):
576 return vars(obj)[name] # instance variable
577 if descr_get is not null:
578 return descr_get(cls_var, obj, objtype) # non-data descriptor
579 if cls_var is not null:
580 return cls_var # class variable
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800581 raise AttributeError(name)
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700582
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800583
584.. testcode::
585 :hide:
586
587 # Test the fidelity of object_getattribute() by comparing it with the
588 # normal object.__getattribute__(). The former will be accessed by
589 # square brackets and the latter by the dot operator.
590
591 class Object:
592
593 def __getitem__(obj, name):
594 try:
595 return object_getattribute(obj, name)
596 except AttributeError:
597 if not hasattr(type(obj), '__getattr__'):
598 raise
599 return type(obj).__getattr__(obj, name) # __getattr__
600
601 class DualOperator(Object):
602
603 x = 10
604
605 def __init__(self, z):
606 self.z = z
607
608 @property
609 def p2(self):
610 return 2 * self.x
611
612 @property
613 def p3(self):
614 return 3 * self.x
615
616 def m5(self, y):
617 return 5 * y
618
619 def m7(self, y):
620 return 7 * y
621
622 def __getattr__(self, name):
623 return ('getattr_hook', self, name)
624
625 class DualOperatorWithSlots:
626
627 __getitem__ = Object.__getitem__
628
629 __slots__ = ['z']
630
631 x = 15
632
633 def __init__(self, z):
634 self.z = z
635
636 @property
637 def p2(self):
638 return 2 * self.x
639
640 def m5(self, y):
641 return 5 * y
642
643 def __getattr__(self, name):
644 return ('getattr_hook', self, name)
645
646
647.. doctest::
648 :hide:
649
650 >>> a = DualOperator(11)
651 >>> vars(a).update(p3 = '_p3', m7 = '_m7')
652 >>> a.x == a['x'] == 10
653 True
654 >>> a.z == a['z'] == 11
655 True
656 >>> a.p2 == a['p2'] == 20
657 True
658 >>> a.p3 == a['p3'] == 30
659 True
660 >>> a.m5(100) == a.m5(100) == 500
661 True
662 >>> a.m7 == a['m7'] == '_m7'
663 True
664 >>> a.g == a['g'] == ('getattr_hook', a, 'g')
665 True
666
667 >>> b = DualOperatorWithSlots(22)
668 >>> b.x == b['x'] == 15
669 True
670 >>> b.z == b['z'] == 22
671 True
672 >>> b.p2 == b['p2'] == 30
673 True
674 >>> b.m5(200) == b['m5'](200) == 1000
675 True
676 >>> b.g == b['g'] == ('getattr_hook', b, 'g')
677 True
678
679
Raymond Hettingerc272d402020-11-15 17:44:28 -0800680Interestingly, attribute lookup doesn't call :meth:`object.__getattribute__`
681directly. Instead, both the dot operator and the :func:`getattr` function
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800682perform attribute lookup by way of a helper function:
683
684.. testcode::
Raymond Hettingerc272d402020-11-15 17:44:28 -0800685
686 def getattr_hook(obj, name):
687 "Emulate slot_tp_getattr_hook() in Objects/typeobject.c"
688 try:
689 return obj.__getattribute__(name)
690 except AttributeError:
691 if not hasattr(type(obj), '__getattr__'):
692 raise
693 return type(obj).__getattr__(obj, name) # __getattr__
694
695So if :meth:`__getattr__` exists, it is called whenever :meth:`__getattribute__`
696raises :exc:`AttributeError` (either directly or in one of the descriptor calls).
697
698Also, if a user calls :meth:`object.__getattribute__` directly, the
699:meth:`__getattr__` hook is bypassed entirely.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000700
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800701
Raymond Hettingere9208f02020-11-01 20:15:50 -0800702Invocation from a class
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800703-----------------------
704
705The logic for a dotted lookup such as ``A.x`` is in
706:meth:`type.__getattribute__`. The steps are similar to those for
707:meth:`object.__getattribute__` but the instance dictionary lookup is replaced
708by a search through the class's :term:`method resolution order`.
709
710If a descriptor is found, it is invoked with ``desc.__get__(None, A)``.
711
712The full C implementation can be found in :c:func:`type_getattro()` and
713:c:func:`_PyType_Lookup()` in :source:`Objects/typeobject.c`.
714
715
Raymond Hettingere9208f02020-11-01 20:15:50 -0800716Invocation from super
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800717---------------------
718
719The logic for super's dotted lookup is in the :meth:`__getattribute__` method for
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700720object returned by :class:`super()`.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000721
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800722A dotted lookup such as ``super(A, obj).m`` searches ``obj.__class__.__mro__``
723for the base class ``B`` immediately following ``A`` and then returns
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700724``B.__dict__['m'].__get__(obj, A)``. If not a descriptor, ``m`` is returned
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800725unchanged.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000726
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800727The full C implementation can be found in :c:func:`super_getattro()` in
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700728:source:`Objects/typeobject.c`. A pure Python equivalent can be found in
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800729`Guido's Tutorial
730<https://www.python.org/download/releases/2.2.3/descrintro/#cooperation>`_.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000731
Georg Brandl45cceeb2010-05-19 21:39:51 +0000732
Raymond Hettingere9208f02020-11-01 20:15:50 -0800733Summary of invocation logic
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800734---------------------------
735
736The mechanism for descriptors is embedded in the :meth:`__getattribute__()`
737methods for :class:`object`, :class:`type`, and :func:`super`.
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700738
739The important points to remember are:
740
741* Descriptors are invoked by the :meth:`__getattribute__` method.
742
743* Classes inherit this machinery from :class:`object`, :class:`type`, or
744 :func:`super`.
745
746* Overriding :meth:`__getattribute__` prevents automatic descriptor calls
747 because all the descriptor logic is in that method.
748
749* :meth:`object.__getattribute__` and :meth:`type.__getattribute__` make
750 different calls to :meth:`__get__`. The first includes the instance and may
751 include the class. The second puts in ``None`` for the instance and always
752 includes the class.
753
754* Data descriptors always override instance dictionaries.
755
756* Non-data descriptors may be overridden by instance dictionaries.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000757
758
Raymond Hettingere9208f02020-11-01 20:15:50 -0800759Automatic name notification
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700760---------------------------
761
762Sometimes it is desirable for a descriptor to know what class variable name it
763was assigned to. When a new class is created, the :class:`type` metaclass
764scans the dictionary of the new class. If any of the entries are descriptors
765and if they define :meth:`__set_name__`, that method is called with two
Raymond Hettinger80318772020-11-06 01:30:17 -0800766arguments. The *owner* is the class where the descriptor is used, and the
767*name* is the class variable the descriptor was assigned to.
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700768
769The implementation details are in :c:func:`type_new()` and
770:c:func:`set_names()` in :source:`Objects/typeobject.c`.
771
772Since the update logic is in :meth:`type.__new__`, notifications only take
773place at the time of class creation. If descriptors are added to the class
774afterwards, :meth:`__set_name__` will need to be called manually.
775
776
Raymond Hettingere9208f02020-11-01 20:15:50 -0800777ORM example
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700778-----------
Georg Brandl45cceeb2010-05-19 21:39:51 +0000779
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700780The following code is simplified skeleton showing how data descriptors could
781be used to implement an `object relational mapping
782<https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping>`_.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000783
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700784The essential idea is that the data is stored in an external database. The
785Python instances only hold keys to the database's tables. Descriptors take
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800786care of lookups or updates:
787
788.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000789
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700790 class Field:
791
792 def __set_name__(self, owner, name):
793 self.fetch = f'SELECT {name} FROM {owner.table} WHERE {owner.key}=?;'
794 self.store = f'UPDATE {owner.table} SET {name}=? WHERE {owner.key}=?;'
Georg Brandl45cceeb2010-05-19 21:39:51 +0000795
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700796 def __get__(self, obj, objtype=None):
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700797 return conn.execute(self.fetch, [obj.key]).fetchone()[0]
Georg Brandl45cceeb2010-05-19 21:39:51 +0000798
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700799 def __set__(self, obj, value):
800 conn.execute(self.store, [value, obj.key])
801 conn.commit()
Georg Brandl45cceeb2010-05-19 21:39:51 +0000802
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800803We can use the :class:`Field` class to define `models
804<https://en.wikipedia.org/wiki/Database_model>`_ that describe the schema for
805each table in a database:
806
807.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700808
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700809 class Movie:
810 table = 'Movies' # Table name
811 key = 'title' # Primary key
812 director = Field()
813 year = Field()
Georg Brandl45cceeb2010-05-19 21:39:51 +0000814
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700815 def __init__(self, key):
816 self.key = key
817
818 class Song:
819 table = 'Music'
820 key = 'title'
821 artist = Field()
822 year = Field()
823 genre = Field()
824
825 def __init__(self, key):
826 self.key = key
827
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800828To use the models, first connect to the database::
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700829
830 >>> import sqlite3
831 >>> conn = sqlite3.connect('entertainment.db')
832
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800833An interactive session shows how data is retrieved from the database and how
834it can be updated:
835
836.. testsetup::
837
838 song_data = [
839 ('Country Roads', 'John Denver', 1972),
840 ('Me and Bobby McGee', 'Janice Joplin', 1971),
841 ('Coal Miners Daughter', 'Loretta Lynn', 1970),
842 ]
843
844 movie_data = [
845 ('Star Wars', 'George Lucas', 1977),
846 ('Jaws', 'Steven Spielberg', 1975),
847 ('Aliens', 'James Cameron', 1986),
848 ]
849
850 import sqlite3
851
852 conn = sqlite3.connect(':memory:')
853 conn.execute('CREATE TABLE Music (title text, artist text, year integer);')
854 conn.execute('CREATE INDEX MusicNdx ON Music (title);')
855 conn.executemany('INSERT INTO Music VALUES (?, ?, ?);', song_data)
856 conn.execute('CREATE TABLE Movies (title text, director text, year integer);')
857 conn.execute('CREATE INDEX MovieNdx ON Music (title);')
858 conn.executemany('INSERT INTO Movies VALUES (?, ?, ?);', movie_data)
859 conn.commit()
860
861.. doctest::
862
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700863 >>> Movie('Star Wars').director
864 'George Lucas'
865 >>> jaws = Movie('Jaws')
866 >>> f'Released in {jaws.year} by {jaws.director}'
867 'Released in 1975 by Steven Spielberg'
868
869 >>> Song('Country Roads').artist
870 'John Denver'
871
872 >>> Movie('Star Wars').director = 'J.J. Abrams'
873 >>> Movie('Star Wars').director
874 'J.J. Abrams'
875
Raymond Hettingerc272d402020-11-15 17:44:28 -0800876
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700877Pure Python Equivalents
878^^^^^^^^^^^^^^^^^^^^^^^
879
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700880The descriptor protocol is simple and offers exciting possibilities. Several
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800881use cases are so common that they have been prepackaged into built-in tools.
Raymond Hettingere9208f02020-11-01 20:15:50 -0800882Properties, bound methods, static methods, class methods, and \_\_slots\_\_ are
883all based on the descriptor protocol.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000884
885
886Properties
887----------
888
889Calling :func:`property` is a succinct way of building a data descriptor that
Raymond Hettinger80318772020-11-06 01:30:17 -0800890triggers a function call upon access to an attribute. Its signature is::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000891
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700892 property(fget=None, fset=None, fdel=None, doc=None) -> property
Georg Brandl45cceeb2010-05-19 21:39:51 +0000893
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800894The documentation shows a typical use to define a managed attribute ``x``:
895
896.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000897
Serhiy Storchakae042a452019-06-10 13:35:52 +0300898 class C:
Georg Brandl45cceeb2010-05-19 21:39:51 +0000899 def getx(self): return self.__x
900 def setx(self, value): self.__x = value
901 def delx(self): del self.__x
902 x = property(getx, setx, delx, "I'm the 'x' property.")
903
904To see how :func:`property` is implemented in terms of the descriptor protocol,
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800905here is a pure Python equivalent:
906
907.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000908
Serhiy Storchakae042a452019-06-10 13:35:52 +0300909 class Property:
Georg Brandl45cceeb2010-05-19 21:39:51 +0000910 "Emulate PyProperty_Type() in Objects/descrobject.c"
911
912 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
913 self.fget = fget
914 self.fset = fset
915 self.fdel = fdel
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700916 if doc is None and fget is not None:
917 doc = fget.__doc__
Georg Brandl45cceeb2010-05-19 21:39:51 +0000918 self.__doc__ = doc
919
920 def __get__(self, obj, objtype=None):
921 if obj is None:
922 return self
923 if self.fget is None:
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700924 raise AttributeError("unreadable attribute")
Georg Brandl45cceeb2010-05-19 21:39:51 +0000925 return self.fget(obj)
926
927 def __set__(self, obj, value):
928 if self.fset is None:
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700929 raise AttributeError("can't set attribute")
Georg Brandl45cceeb2010-05-19 21:39:51 +0000930 self.fset(obj, value)
931
932 def __delete__(self, obj):
933 if self.fdel is None:
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700934 raise AttributeError("can't delete attribute")
Georg Brandl45cceeb2010-05-19 21:39:51 +0000935 self.fdel(obj)
936
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700937 def getter(self, fget):
938 return type(self)(fget, self.fset, self.fdel, self.__doc__)
939
940 def setter(self, fset):
941 return type(self)(self.fget, fset, self.fdel, self.__doc__)
942
943 def deleter(self, fdel):
944 return type(self)(self.fget, self.fset, fdel, self.__doc__)
945
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800946.. testcode::
947 :hide:
948
949 # Verify the Property() emulation
950
951 class CC:
952 def getx(self):
953 return self.__x
954 def setx(self, value):
955 self.__x = value
956 def delx(self):
957 del self.__x
958 x = Property(getx, setx, delx, "I'm the 'x' property.")
959
960 # Now do it again but use the decorator style
961
962 class CCC:
963 @Property
964 def x(self):
965 return self.__x
966 @x.setter
967 def x(self, value):
968 self.__x = value
969 @x.deleter
970 def x(self):
971 del self.__x
972
973
974.. doctest::
975 :hide:
976
977 >>> cc = CC()
978 >>> hasattr(cc, 'x')
979 False
980 >>> cc.x = 33
981 >>> cc.x
982 33
983 >>> del cc.x
984 >>> hasattr(cc, 'x')
985 False
986
987 >>> ccc = CCC()
988 >>> hasattr(ccc, 'x')
989 False
990 >>> ccc.x = 333
991 >>> ccc.x == 333
992 True
993 >>> del ccc.x
994 >>> hasattr(ccc, 'x')
995 False
996
Georg Brandl45cceeb2010-05-19 21:39:51 +0000997The :func:`property` builtin helps whenever a user interface has granted
998attribute access and then subsequent changes require the intervention of a
999method.
1000
1001For instance, a spreadsheet class may grant access to a cell value through
1002``Cell('b10').value``. Subsequent improvements to the program require the cell
1003to be recalculated on every access; however, the programmer does not want to
1004affect existing client code accessing the attribute directly. The solution is
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001005to wrap access to the value attribute in a property data descriptor:
1006
1007.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001008
Serhiy Storchakae042a452019-06-10 13:35:52 +03001009 class Cell:
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001010 ...
1011
1012 @property
1013 def value(self):
_ = NaNb066edf2017-06-23 11:54:35 +08001014 "Recalculate the cell before returning value"
Georg Brandl45cceeb2010-05-19 21:39:51 +00001015 self.recalc()
_ = NaNb066edf2017-06-23 11:54:35 +08001016 return self._value
Georg Brandl45cceeb2010-05-19 21:39:51 +00001017
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001018Either the built-in :func:`property` or our :func:`Property` equivalent would
1019work in this example.
1020
Georg Brandl45cceeb2010-05-19 21:39:51 +00001021
Raymond Hettingere9208f02020-11-01 20:15:50 -08001022Functions and methods
Georg Brandl45cceeb2010-05-19 21:39:51 +00001023---------------------
1024
1025Python's object oriented features are built upon a function based environment.
1026Using non-data descriptors, the two are merged seamlessly.
1027
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001028Functions stored in class dictionaries get turned into methods when invoked.
1029Methods only differ from regular functions in that the object instance is
1030prepended to the other arguments. By convention, the instance is called
1031*self* but could be called *this* or any other variable name.
Georg Brandl45cceeb2010-05-19 21:39:51 +00001032
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001033Methods can be created manually with :class:`types.MethodType` which is
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001034roughly equivalent to:
1035
1036.. testcode::
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001037
Raymond Hettingere6a7ea42020-10-25 07:12:50 -07001038 class MethodType:
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001039 "Emulate Py_MethodType in Objects/classobject.c"
1040
1041 def __init__(self, func, obj):
1042 self.__func__ = func
1043 self.__self__ = obj
1044
1045 def __call__(self, *args, **kwargs):
1046 func = self.__func__
1047 obj = self.__self__
1048 return func(obj, *args, **kwargs)
1049
1050To support automatic creation of methods, functions include the
1051:meth:`__get__` method for binding methods during attribute access. This
Raymond Hettinger80318772020-11-06 01:30:17 -08001052means that functions are non-data descriptors that return bound methods
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001053during dotted lookup from an instance. Here's how it works:
1054
1055.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001056
Serhiy Storchakae042a452019-06-10 13:35:52 +03001057 class Function:
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001058 ...
1059
Georg Brandl45cceeb2010-05-19 21:39:51 +00001060 def __get__(self, obj, objtype=None):
1061 "Simulate func_descr_get() in Objects/funcobject.c"
Raymond Hettinger0d4497b2017-09-25 01:05:49 -07001062 if obj is None:
1063 return self
Raymond Hettingere6a7ea42020-10-25 07:12:50 -07001064 return MethodType(self, obj)
Georg Brandl45cceeb2010-05-19 21:39:51 +00001065
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001066Running the following class in the interpreter shows how the function
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001067descriptor works in practice:
1068
1069.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001070
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001071 class D:
1072 def f(self, x):
1073 return x
Raymond Hettinger0d4497b2017-09-25 01:05:49 -07001074
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001075The function has a :term:`qualified name` attribute to support introspection:
1076
1077.. doctest::
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001078
1079 >>> D.f.__qualname__
1080 'D.f'
1081
1082Accessing the function through the class dictionary does not invoke
1083:meth:`__get__`. Instead, it just returns the underlying function object::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001084
Raymond Hettinger0d4497b2017-09-25 01:05:49 -07001085 >>> D.__dict__['f']
1086 <function D.f at 0x00C45070>
1087
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001088Dotted access from a class calls :meth:`__get__` which just returns the
1089underlying function unchanged::
1090
Raymond Hettinger0d4497b2017-09-25 01:05:49 -07001091 >>> D.f
1092 <function D.f at 0x00C45070>
1093
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001094The interesting behavior occurs during dotted access from an instance. The
1095dotted lookup calls :meth:`__get__` which returns a bound method object::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001096
1097 >>> d = D()
Raymond Hettinger0d4497b2017-09-25 01:05:49 -07001098 >>> d.f
Georg Brandl45cceeb2010-05-19 21:39:51 +00001099 <bound method D.f of <__main__.D object at 0x00B18C90>>
1100
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001101Internally, the bound method stores the underlying function and the bound
1102instance::
1103
Raymond Hettinger0d4497b2017-09-25 01:05:49 -07001104 >>> d.f.__func__
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001105 <function D.f at 0x00C45070>
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001106
Raymond Hettinger0d4497b2017-09-25 01:05:49 -07001107 >>> d.f.__self__
1108 <__main__.D object at 0x1012e1f98>
Georg Brandl45cceeb2010-05-19 21:39:51 +00001109
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001110If you have ever wondered where *self* comes from in regular methods or where
1111*cls* comes from in class methods, this is it!
1112
Georg Brandl45cceeb2010-05-19 21:39:51 +00001113
Raymond Hettingere9208f02020-11-01 20:15:50 -08001114Static methods
Raymond Hettingere6a7ea42020-10-25 07:12:50 -07001115--------------
Georg Brandl45cceeb2010-05-19 21:39:51 +00001116
1117Non-data descriptors provide a simple mechanism for variations on the usual
1118patterns of binding functions into methods.
1119
1120To recap, functions have a :meth:`__get__` method so that they can be converted
Serhiy Storchakad65c9492015-11-02 14:10:23 +02001121to a method when accessed as attributes. The non-data descriptor transforms an
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001122``obj.f(*args)`` call into ``f(obj, *args)``. Calling ``cls.f(*args)``
Georg Brandl45cceeb2010-05-19 21:39:51 +00001123becomes ``f(*args)``.
1124
1125This chart summarizes the binding and its two most useful variants:
1126
1127 +-----------------+----------------------+------------------+
1128 | Transformation | Called from an | Called from a |
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001129 | | object | class |
Georg Brandl45cceeb2010-05-19 21:39:51 +00001130 +=================+======================+==================+
1131 | function | f(obj, \*args) | f(\*args) |
1132 +-----------------+----------------------+------------------+
1133 | staticmethod | f(\*args) | f(\*args) |
1134 +-----------------+----------------------+------------------+
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001135 | classmethod | f(type(obj), \*args) | f(cls, \*args) |
Georg Brandl45cceeb2010-05-19 21:39:51 +00001136 +-----------------+----------------------+------------------+
1137
1138Static methods return the underlying function without changes. Calling either
1139``c.f`` or ``C.f`` is the equivalent of a direct lookup into
1140``object.__getattribute__(c, "f")`` or ``object.__getattribute__(C, "f")``. As a
1141result, the function becomes identically accessible from either an object or a
1142class.
1143
1144Good candidates for static methods are methods that do not reference the
1145``self`` variable.
1146
1147For instance, a statistics package may include a container class for
1148experimental data. The class provides normal methods for computing the average,
1149mean, median, and other descriptive statistics that depend on the data. However,
1150there may be useful functions which are conceptually related but do not depend
1151on the data. For instance, ``erf(x)`` is handy conversion routine that comes up
1152in statistical work but does not directly depend on a particular dataset.
1153It can be called either from an object or the class: ``s.erf(1.5) --> .9332`` or
1154``Sample.erf(1.5) --> .9332``.
1155
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001156Since static methods return the underlying function with no changes, the
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001157example calls are unexciting:
1158
1159.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001160
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001161 class E:
1162 @staticmethod
1163 def f(x):
1164 print(x)
1165
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001166.. doctest::
1167
Shubham Aggarwalabbdd1f2019-03-20 08:25:55 +05301168 >>> E.f(3)
Georg Brandl45cceeb2010-05-19 21:39:51 +00001169 3
Shubham Aggarwalabbdd1f2019-03-20 08:25:55 +05301170 >>> E().f(3)
Georg Brandl45cceeb2010-05-19 21:39:51 +00001171 3
1172
1173Using the non-data descriptor protocol, a pure Python version of
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001174:func:`staticmethod` would look like this:
1175
1176.. doctest::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001177
Serhiy Storchakae042a452019-06-10 13:35:52 +03001178 class StaticMethod:
Serhiy Storchakadba90392016-05-10 12:01:23 +03001179 "Emulate PyStaticMethod_Type() in Objects/funcobject.c"
Georg Brandl45cceeb2010-05-19 21:39:51 +00001180
Serhiy Storchakadba90392016-05-10 12:01:23 +03001181 def __init__(self, f):
1182 self.f = f
Georg Brandl45cceeb2010-05-19 21:39:51 +00001183
Serhiy Storchakadba90392016-05-10 12:01:23 +03001184 def __get__(self, obj, objtype=None):
1185 return self.f
Georg Brandl45cceeb2010-05-19 21:39:51 +00001186
Raymond Hettingere6a7ea42020-10-25 07:12:50 -07001187
Raymond Hettingere9208f02020-11-01 20:15:50 -08001188Class methods
Raymond Hettingere6a7ea42020-10-25 07:12:50 -07001189-------------
1190
Georg Brandl45cceeb2010-05-19 21:39:51 +00001191Unlike static methods, class methods prepend the class reference to the
1192argument list before calling the function. This format is the same
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001193for whether the caller is an object or a class:
1194
1195.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001196
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001197 class F:
1198 @classmethod
1199 def f(cls, x):
1200 return cls.__name__, x
1201
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001202.. doctest::
1203
1204 >>> F.f(3)
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001205 ('F', 3)
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001206 >>> F().f(3)
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001207 ('F', 3)
Georg Brandl45cceeb2010-05-19 21:39:51 +00001208
Raymond Hettingere6a7ea42020-10-25 07:12:50 -07001209This behavior is useful whenever the method only needs to have a class
1210reference and does rely on data stored in a specific instance. One use for
1211class methods is to create alternate class constructors. For example, the
1212classmethod :func:`dict.fromkeys` creates a new dictionary from a list of
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001213keys. The pure Python equivalent is:
Georg Brandl45cceeb2010-05-19 21:39:51 +00001214
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001215.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001216
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001217 class Dict(dict):
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001218 @classmethod
1219 def fromkeys(cls, iterable, value=None):
Georg Brandl45cceeb2010-05-19 21:39:51 +00001220 "Emulate dict_fromkeys() in Objects/dictobject.c"
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001221 d = cls()
Georg Brandl45cceeb2010-05-19 21:39:51 +00001222 for key in iterable:
1223 d[key] = value
1224 return d
Georg Brandl45cceeb2010-05-19 21:39:51 +00001225
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001226Now a new dictionary of unique keys can be constructed like this:
1227
1228.. doctest::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001229
1230 >>> Dict.fromkeys('abracadabra')
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001231 {'a': None, 'b': None, 'r': None, 'c': None, 'd': None}
Georg Brandl45cceeb2010-05-19 21:39:51 +00001232
1233Using the non-data descriptor protocol, a pure Python version of
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001234:func:`classmethod` would look like this:
1235
1236.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001237
Serhiy Storchakae042a452019-06-10 13:35:52 +03001238 class ClassMethod:
Serhiy Storchakadba90392016-05-10 12:01:23 +03001239 "Emulate PyClassMethod_Type() in Objects/funcobject.c"
Georg Brandl45cceeb2010-05-19 21:39:51 +00001240
Serhiy Storchakadba90392016-05-10 12:01:23 +03001241 def __init__(self, f):
1242 self.f = f
Georg Brandl45cceeb2010-05-19 21:39:51 +00001243
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001244 def __get__(self, obj, cls=None):
1245 if cls is None:
1246 cls = type(obj)
Raymond Hettinger8e5b0fd2020-10-23 18:37:27 -07001247 if hasattr(obj, '__get__'):
1248 return self.f.__get__(cls)
Raymond Hettingere6a7ea42020-10-25 07:12:50 -07001249 return MethodType(self.f, cls)
Raymond Hettinger8e5b0fd2020-10-23 18:37:27 -07001250
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001251.. testcode::
1252 :hide:
1253
1254 # Verify the emulation works
1255 class T:
1256 @ClassMethod
1257 def cm(cls, x, y):
1258 return (cls, x, y)
1259
1260.. doctest::
1261 :hide:
1262
1263 >>> T.cm(11, 22)
1264 (<class 'T'>, 11, 22)
1265
1266 # Also call it from an instance
1267 >>> t = T()
1268 >>> t.cm(11, 22)
1269 (<class 'T'>, 11, 22)
1270
Raymond Hettinger8e5b0fd2020-10-23 18:37:27 -07001271The code path for ``hasattr(obj, '__get__')`` was added in Python 3.9 and
1272makes it possible for :func:`classmethod` to support chained decorators.
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001273For example, a classmethod and property could be chained together:
1274
1275.. testcode::
Raymond Hettinger8e5b0fd2020-10-23 18:37:27 -07001276
1277 class G:
1278 @classmethod
1279 @property
1280 def __doc__(cls):
1281 return f'A doc for {cls.__name__!r}'
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001282
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001283.. doctest::
1284
1285 >>> G.__doc__
1286 "A doc for 'G'"
1287
1288
Raymond Hettingere9208f02020-11-01 20:15:50 -08001289Member objects and __slots__
1290----------------------------
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001291
1292When a class defines ``__slots__``, it replaces instance dictionaries with a
1293fixed-length array of slot values. From a user point of view that has
1294several effects:
1295
12961. Provides immediate detection of bugs due to misspelled attribute
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001297assignments. Only attribute names specified in ``__slots__`` are allowed:
1298
1299.. testcode::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001300
1301 class Vehicle:
1302 __slots__ = ('id_number', 'make', 'model')
1303
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001304.. doctest::
1305
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001306 >>> auto = Vehicle()
1307 >>> auto.id_nubmer = 'VYE483814LQEX'
1308 Traceback (most recent call last):
1309 ...
1310 AttributeError: 'Vehicle' object has no attribute 'id_nubmer'
1311
13122. Helps create immutable objects where descriptors manage access to private
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001313attributes stored in ``__slots__``:
1314
1315.. testcode::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001316
1317 class Immutable:
1318
Raymond Hettinger80318772020-11-06 01:30:17 -08001319 __slots__ = ('_dept', '_name') # Replace the instance dictionary
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001320
1321 def __init__(self, dept, name):
1322 self._dept = dept # Store to private attribute
1323 self._name = name # Store to private attribute
1324
1325 @property # Read-only descriptor
1326 def dept(self):
1327 return self._dept
1328
1329 @property
1330 def name(self): # Read-only descriptor
1331 return self._name
1332
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001333.. doctest::
1334
1335 >>> mark = Immutable('Botany', 'Mark Watney')
1336 >>> mark.dept
1337 'Botany'
1338 >>> mark.dept = 'Space Pirate'
1339 Traceback (most recent call last):
1340 ...
1341 AttributeError: can't set attribute
1342 >>> mark.location = 'Mars'
1343 Traceback (most recent call last):
1344 ...
1345 AttributeError: 'Immutable' object has no attribute 'location'
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001346
13473. Saves memory. On a 64-bit Linux build, an instance with two attributes
1348takes 48 bytes with ``__slots__`` and 152 bytes without. This `flyweight
1349design pattern <https://en.wikipedia.org/wiki/Flyweight_pattern>`_ likely only
1350matters when a large number of instances are going to be created.
1351
13524. Blocks tools like :func:`functools.cached_property` which require an
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001353instance dictionary to function correctly:
1354
1355.. testcode::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001356
1357 from functools import cached_property
1358
1359 class CP:
1360 __slots__ = () # Eliminates the instance dict
1361
1362 @cached_property # Requires an instance dict
1363 def pi(self):
1364 return 4 * sum((-1.0)**n / (2.0*n + 1.0)
1365 for n in reversed(range(100_000)))
1366
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001367.. doctest::
1368
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001369 >>> CP().pi
1370 Traceback (most recent call last):
1371 ...
1372 TypeError: No '__dict__' attribute on 'CP' instance to cache 'pi' property.
1373
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001374It is not possible to create an exact drop-in pure Python version of
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001375``__slots__`` because it requires direct access to C structures and control
1376over object memory allocation. However, we can build a mostly faithful
1377simulation where the actual C structure for slots is emulated by a private
1378``_slotvalues`` list. Reads and writes to that private structure are managed
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001379by member descriptors:
1380
1381.. testcode::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001382
Raymond Hettingerffae9322020-11-23 10:56:59 -08001383 null = object()
1384
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001385 class Member:
1386
1387 def __init__(self, name, clsname, offset):
1388 'Emulate PyMemberDef in Include/structmember.h'
1389 # Also see descr_new() in Objects/descrobject.c
1390 self.name = name
1391 self.clsname = clsname
1392 self.offset = offset
1393
1394 def __get__(self, obj, objtype=None):
1395 'Emulate member_get() in Objects/descrobject.c'
1396 # Also see PyMember_GetOne() in Python/structmember.c
Raymond Hettingerffae9322020-11-23 10:56:59 -08001397 value = obj._slotvalues[self.offset]
1398 if value is null:
1399 raise AttributeError(self.name)
1400 return value
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001401
1402 def __set__(self, obj, value):
1403 'Emulate member_set() in Objects/descrobject.c'
1404 obj._slotvalues[self.offset] = value
1405
Raymond Hettingerffae9322020-11-23 10:56:59 -08001406 def __delete__(self, obj):
1407 'Emulate member_delete() in Objects/descrobject.c'
1408 value = obj._slotvalues[self.offset]
1409 if value is null:
1410 raise AttributeError(self.name)
1411 obj._slotvalues[self.offset] = null
1412
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001413 def __repr__(self):
1414 'Emulate member_repr() in Objects/descrobject.c'
1415 return f'<Member {self.name!r} of {self.clsname!r}>'
1416
1417The :meth:`type.__new__` method takes care of adding member objects to class
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001418variables:
1419
1420.. testcode::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001421
1422 class Type(type):
1423 'Simulate how the type metaclass adds member objects for slots'
1424
1425 def __new__(mcls, clsname, bases, mapping):
1426 'Emuluate type_new() in Objects/typeobject.c'
1427 # type_new() calls PyTypeReady() which calls add_methods()
1428 slot_names = mapping.get('slot_names', [])
1429 for offset, name in enumerate(slot_names):
1430 mapping[name] = Member(name, clsname, offset)
1431 return type.__new__(mcls, clsname, bases, mapping)
1432
Raymond Hettingerffae9322020-11-23 10:56:59 -08001433The :meth:`object.__new__` method takes care of creating instances that have
1434slots instead of an instance dictionary. Here is a rough simulation in pure
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001435Python:
1436
1437.. testcode::
Raymond Hettingerffae9322020-11-23 10:56:59 -08001438
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001439 class Object:
1440 'Simulate how object.__new__() allocates memory for __slots__'
1441
1442 def __new__(cls, *args):
1443 'Emulate object_new() in Objects/typeobject.c'
1444 inst = super().__new__(cls)
1445 if hasattr(cls, 'slot_names'):
Raymond Hettingerffae9322020-11-23 10:56:59 -08001446 empty_slots = [null] * len(cls.slot_names)
1447 object.__setattr__(inst, '_slotvalues', empty_slots)
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001448 return inst
1449
Raymond Hettingerffae9322020-11-23 10:56:59 -08001450 def __setattr__(self, name, value):
1451 'Emulate _PyObject_GenericSetAttrWithDict() Objects/object.c'
1452 cls = type(self)
1453 if hasattr(cls, 'slot_names') and name not in cls.slot_names:
1454 raise AttributeError(
1455 f'{type(self).__name__!r} object has no attribute {name!r}'
1456 )
1457 super().__setattr__(name, value)
1458
1459 def __delattr__(self, name):
1460 'Emulate _PyObject_GenericSetAttrWithDict() Objects/object.c'
1461 cls = type(self)
1462 if hasattr(cls, 'slot_names') and name not in cls.slot_names:
1463 raise AttributeError(
1464 f'{type(self).__name__!r} object has no attribute {name!r}'
1465 )
1466 super().__delattr__(name)
1467
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001468To use the simulation in a real class, just inherit from :class:`Object` and
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001469set the :term:`metaclass` to :class:`Type`:
1470
1471.. testcode::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001472
1473 class H(Object, metaclass=Type):
Raymond Hettingerffae9322020-11-23 10:56:59 -08001474 'Instance variables stored in slots'
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001475
1476 slot_names = ['x', 'y']
1477
1478 def __init__(self, x, y):
1479 self.x = x
1480 self.y = y
1481
1482At this point, the metaclass has loaded member objects for *x* and *y*::
1483
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001484 >>> from pprint import pp
1485 >>> pp(dict(vars(H)))
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001486 {'__module__': '__main__',
Raymond Hettingerffae9322020-11-23 10:56:59 -08001487 '__doc__': 'Instance variables stored in slots',
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001488 'slot_names': ['x', 'y'],
1489 '__init__': <function H.__init__ at 0x7fb5d302f9d0>,
1490 'x': <Member 'x' of 'H'>,
Raymond Hettingerffae9322020-11-23 10:56:59 -08001491 'y': <Member 'y' of 'H'>}
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001492
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001493.. doctest::
1494 :hide:
1495
1496 # We test this separately because the preceding section is not
1497 # doctestable due to the hex memory address for the __init__ function
1498 >>> isinstance(vars(H)['x'], Member)
1499 True
1500 >>> isinstance(vars(H)['y'], Member)
1501 True
1502
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001503When instances are created, they have a ``slot_values`` list where the
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001504attributes are stored:
1505
1506.. doctest::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001507
1508 >>> h = H(10, 20)
1509 >>> vars(h)
1510 {'_slotvalues': [10, 20]}
1511 >>> h.x = 55
1512 >>> vars(h)
1513 {'_slotvalues': [55, 20]}
1514
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001515Misspelled or unassigned attributes will raise an exception:
1516
1517.. doctest::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001518
Raymond Hettingerffae9322020-11-23 10:56:59 -08001519 >>> h.xz
1520 Traceback (most recent call last):
1521 ...
1522 AttributeError: 'H' object has no attribute 'xz'
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001523
1524.. doctest::
1525 :hide:
1526
1527 # Examples for deleted attributes are not shown because this section
1528 # is already a bit lengthy. We still test that code here.
1529 >>> del h.x
1530 >>> hasattr(h, 'x')
1531 False
1532
1533 # Also test the code for uninitialized slots
1534 >>> class HU(Object, metaclass=Type):
1535 ... slot_names = ['x', 'y']
1536 ...
1537 >>> hu = HU()
1538 >>> hasattr(hu, 'x')
1539 False
1540 >>> hasattr(hu, 'y')
1541 False