blob: bc741c738b98dac3b62d5cf9551e596cfe63dbcb [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
Raymond Hettinger85c84922020-11-25 01:54:24 -0800173logged, but that the regular attribute *name* is not logged:
174
175.. testcode::
176 :hide:
177
178 import logging, sys
179 logging.basicConfig(level=logging.INFO, stream=sys.stdout, force=True)
180
181.. doctest::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700182
183 >>> mary = Person('Mary M', 30) # The initial age update is logged
184 INFO:root:Updating 'age' to 30
185 >>> dave = Person('David D', 40)
186 INFO:root:Updating 'age' to 40
187
188 >>> vars(mary) # The actual data is in a private attribute
189 {'name': 'Mary M', '_age': 30}
190 >>> vars(dave)
191 {'name': 'David D', '_age': 40}
192
193 >>> mary.age # Access the data and log the lookup
194 INFO:root:Accessing 'age' giving 30
195 30
196 >>> mary.birthday() # Updates are logged as well
197 INFO:root:Accessing 'age' giving 30
198 INFO:root:Updating 'age' to 31
199
200 >>> dave.name # Regular attribute lookup isn't logged
201 'David D'
202 >>> dave.age # Only the managed attribute is logged
203 INFO:root:Accessing 'age' giving 40
204 40
205
Raymond Hettinger80318772020-11-06 01:30:17 -0800206One major issue with this example is that the private name *_age* is hardwired in
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700207the *LoggedAgeAccess* class. That means that each instance can only have one
208logged attribute and that its name is unchangeable. In the next example,
209we'll fix that problem.
210
211
Raymond Hettingere9208f02020-11-01 20:15:50 -0800212Customized names
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700213----------------
214
Raymond Hettinger80318772020-11-06 01:30:17 -0800215When a class uses descriptors, it can inform each descriptor about which
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700216variable name was used.
217
218In this example, the :class:`Person` class has two descriptor instances,
219*name* and *age*. When the :class:`Person` class is defined, it makes a
220callback to :meth:`__set_name__` in *LoggedAccess* so that the field names can
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800221be recorded, giving each descriptor its own *public_name* and *private_name*:
222
223.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700224
225 import logging
226
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700227 logging.basicConfig(level=logging.INFO)
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700228
229 class LoggedAccess:
230
231 def __set_name__(self, owner, name):
232 self.public_name = name
Raymond Hettingerc272d402020-11-15 17:44:28 -0800233 self.private_name = '_' + name
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700234
235 def __get__(self, obj, objtype=None):
236 value = getattr(obj, self.private_name)
237 logging.info('Accessing %r giving %r', self.public_name, value)
238 return value
239
240 def __set__(self, obj, value):
241 logging.info('Updating %r to %r', self.public_name, value)
242 setattr(obj, self.private_name, value)
243
244 class Person:
245
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800246 name = LoggedAccess() # First descriptor instance
247 age = LoggedAccess() # Second descriptor instance
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700248
249 def __init__(self, name, age):
250 self.name = name # Calls the first descriptor
251 self.age = age # Calls the second descriptor
252
253 def birthday(self):
254 self.age += 1
255
256An interactive session shows that the :class:`Person` class has called
257:meth:`__set_name__` so that the field names would be recorded. Here
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800258we call :func:`vars` to look up the descriptor without triggering it:
259
260.. doctest::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700261
262 >>> vars(vars(Person)['name'])
263 {'public_name': 'name', 'private_name': '_name'}
264 >>> vars(vars(Person)['age'])
265 {'public_name': 'age', 'private_name': '_age'}
266
Raymond Hettinger85c84922020-11-25 01:54:24 -0800267The new class now logs access to both *name* and *age*:
268
269.. testcode::
270 :hide:
271
272 import logging, sys
273 logging.basicConfig(level=logging.INFO, stream=sys.stdout, force=True)
274
275.. doctest::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700276
277 >>> pete = Person('Peter P', 10)
278 INFO:root:Updating 'name' to 'Peter P'
279 INFO:root:Updating 'age' to 10
280 >>> kate = Person('Catherine C', 20)
281 INFO:root:Updating 'name' to 'Catherine C'
282 INFO:root:Updating 'age' to 20
283
284The two *Person* instances contain only the private names::
285
286 >>> vars(pete)
287 {'_name': 'Peter P', '_age': 10}
288 >>> vars(kate)
289 {'_name': 'Catherine C', '_age': 20}
290
291
292Closing thoughts
293----------------
294
295A :term:`descriptor` is what we call any object that defines :meth:`__get__`,
296:meth:`__set__`, or :meth:`__delete__`.
297
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700298Optionally, descriptors can have a :meth:`__set_name__` method. This is only
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700299used in cases where a descriptor needs to know either the class where it was
Raymond Hettingerc272d402020-11-15 17:44:28 -0800300created or the name of class variable it was assigned to. (This method, if
301present, is called even if the class is not a descriptor.)
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700302
Raymond Hettingerc272d402020-11-15 17:44:28 -0800303Descriptors get invoked by the dot "operator" during attribute lookup. If a
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700304descriptor is accessed indirectly with ``vars(some_class)[descriptor_name]``,
305the descriptor instance is returned without invoking it.
306
307Descriptors only work when used as class variables. When put in instances,
308they have no effect.
309
310The main motivation for descriptors is to provide a hook allowing objects
Raymond Hettingerc272d402020-11-15 17:44:28 -0800311stored in class variables to control what happens during attribute lookup.
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700312
313Traditionally, the calling class controls what happens during lookup.
314Descriptors invert that relationship and allow the data being looked-up to
315have a say in the matter.
316
317Descriptors are used throughout the language. It is how functions turn into
318bound methods. Common tools like :func:`classmethod`, :func:`staticmethod`,
319:func:`property`, and :func:`functools.cached_property` are all implemented as
320descriptors.
321
322
323Complete Practical Example
324^^^^^^^^^^^^^^^^^^^^^^^^^^
325
326In this example, we create a practical and powerful tool for locating
327notoriously hard to find data corruption bugs.
328
329
330Validator class
331---------------
332
333A validator is a descriptor for managed attribute access. Prior to storing
334any data, it verifies that the new value meets various type and range
335restrictions. If those restrictions aren't met, it raises an exception to
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700336prevent data corruption at its source.
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700337
338This :class:`Validator` class is both an :term:`abstract base class` and a
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800339managed attribute descriptor:
340
341.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700342
343 from abc import ABC, abstractmethod
344
345 class Validator(ABC):
346
347 def __set_name__(self, owner, name):
Raymond Hettingerc272d402020-11-15 17:44:28 -0800348 self.private_name = '_' + name
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700349
350 def __get__(self, obj, objtype=None):
351 return getattr(obj, self.private_name)
352
353 def __set__(self, obj, value):
354 self.validate(value)
355 setattr(obj, self.private_name, value)
356
357 @abstractmethod
358 def validate(self, value):
359 pass
360
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700361Custom validators need to inherit from :class:`Validator` and must supply a
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700362:meth:`validate` method to test various restrictions as needed.
363
364
365Custom validators
366-----------------
367
368Here are three practical data validation utilities:
369
3701) :class:`OneOf` verifies that a value is one of a restricted set of options.
371
3722) :class:`Number` verifies that a value is either an :class:`int` or
373 :class:`float`. Optionally, it verifies that a value is between a given
374 minimum or maximum.
375
3763) :class:`String` verifies that a value is a :class:`str`. Optionally, it
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700377 validates a given minimum or maximum length. It can validate a
378 user-defined `predicate
379 <https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)>`_ as well.
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700380
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800381.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700382
383 class OneOf(Validator):
384
385 def __init__(self, *options):
386 self.options = set(options)
387
388 def validate(self, value):
389 if value not in self.options:
390 raise ValueError(f'Expected {value!r} to be one of {self.options!r}')
391
392 class Number(Validator):
393
394 def __init__(self, minvalue=None, maxvalue=None):
395 self.minvalue = minvalue
396 self.maxvalue = maxvalue
397
398 def validate(self, value):
399 if not isinstance(value, (int, float)):
400 raise TypeError(f'Expected {value!r} to be an int or float')
401 if self.minvalue is not None and value < self.minvalue:
402 raise ValueError(
403 f'Expected {value!r} to be at least {self.minvalue!r}'
404 )
405 if self.maxvalue is not None and value > self.maxvalue:
406 raise ValueError(
407 f'Expected {value!r} to be no more than {self.maxvalue!r}'
408 )
409
410 class String(Validator):
411
412 def __init__(self, minsize=None, maxsize=None, predicate=None):
413 self.minsize = minsize
414 self.maxsize = maxsize
415 self.predicate = predicate
416
417 def validate(self, value):
418 if not isinstance(value, str):
419 raise TypeError(f'Expected {value!r} to be an str')
420 if self.minsize is not None and len(value) < self.minsize:
421 raise ValueError(
422 f'Expected {value!r} to be no smaller than {self.minsize!r}'
423 )
424 if self.maxsize is not None and len(value) > self.maxsize:
425 raise ValueError(
426 f'Expected {value!r} to be no bigger than {self.maxsize!r}'
427 )
428 if self.predicate is not None and not self.predicate(value):
429 raise ValueError(
430 f'Expected {self.predicate} to be true for {value!r}'
431 )
432
433
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800434Practical application
435---------------------
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700436
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800437Here's how the data validators can be used in a real class:
438
439.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700440
441 class Component:
442
443 name = String(minsize=3, maxsize=10, predicate=str.isupper)
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700444 kind = OneOf('wood', 'metal', 'plastic')
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700445 quantity = Number(minvalue=0)
446
447 def __init__(self, name, kind, quantity):
448 self.name = name
449 self.kind = kind
450 self.quantity = quantity
451
Raymond Hettinger85c84922020-11-25 01:54:24 -0800452The descriptors prevent invalid instances from being created:
453
454.. doctest::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700455
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800456 >>> Component('Widget', 'metal', 5) # Blocked: 'Widget' is not all uppercase
457 Traceback (most recent call last):
458 ...
459 ValueError: Expected <method 'isupper' of 'str' objects> to be true for 'Widget'
460
461 >>> Component('WIDGET', 'metle', 5) # Blocked: 'metle' is misspelled
462 Traceback (most recent call last):
463 ...
464 ValueError: Expected 'metle' to be one of {'metal', 'plastic', 'wood'}
465
466 >>> Component('WIDGET', 'metal', -5) # Blocked: -5 is negative
467 Traceback (most recent call last):
468 ...
469 ValueError: Expected -5 to be at least 0
470 >>> Component('WIDGET', 'metal', 'V') # Blocked: 'V' isn't a number
471 Traceback (most recent call last):
472 ...
473 TypeError: Expected 'V' to be an int or float
474
475 >>> c = Component('WIDGET', 'metal', 5) # Allowed: The inputs are valid
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700476
477
478Technical Tutorial
479^^^^^^^^^^^^^^^^^^
480
481What follows is a more technical tutorial for the mechanics and details of how
482descriptors work.
483
484
Georg Brandl45cceeb2010-05-19 21:39:51 +0000485Abstract
486--------
487
488Defines descriptors, summarizes the protocol, and shows how descriptors are
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700489called. Provides an example showing how object relational mappings work.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000490
491Learning about descriptors not only provides access to a larger toolset, it
Raymond Hettingerc272d402020-11-15 17:44:28 -0800492creates a deeper understanding of how Python works.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000493
494
Raymond Hettingere9208f02020-11-01 20:15:50 -0800495Definition and introduction
Georg Brandl45cceeb2010-05-19 21:39:51 +0000496---------------------------
497
Raymond Hettingerc272d402020-11-15 17:44:28 -0800498In general, a descriptor is an attribute value that has one of the methods in
499the descriptor protocol. Those methods are :meth:`__get__`, :meth:`__set__`,
500and :meth:`__delete__`. If any of those methods are defined for an the
501attribute, it is said to be a :term:`descriptor`.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000502
503The default behavior for attribute access is to get, set, or delete the
504attribute from an object's dictionary. For instance, ``a.x`` has a lookup chain
505starting with ``a.__dict__['x']``, then ``type(a).__dict__['x']``, and
Raymond Hettingerc272d402020-11-15 17:44:28 -0800506continuing through the method resolution order of ``type(a)``. If the
Georg Brandl45cceeb2010-05-19 21:39:51 +0000507looked-up value is an object defining one of the descriptor methods, then Python
508may override the default behavior and invoke the descriptor method instead.
509Where this occurs in the precedence chain depends on which descriptor methods
Florent Xiclunaaa6c1d22011-12-12 18:54:29 +0100510were defined.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000511
512Descriptors are a powerful, general purpose protocol. They are the mechanism
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700513behind properties, methods, static methods, class methods, and
514:func:`super()`. They are used throughout Python itself. Descriptors
515simplify the underlying C code and offer a flexible set of new tools for
516everyday Python programs.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000517
518
Raymond Hettingere9208f02020-11-01 20:15:50 -0800519Descriptor protocol
Georg Brandl45cceeb2010-05-19 21:39:51 +0000520-------------------
521
NotAFile28ea4c22018-09-10 23:35:38 +0200522``descr.__get__(self, obj, type=None) -> value``
Georg Brandl45cceeb2010-05-19 21:39:51 +0000523
NotAFile28ea4c22018-09-10 23:35:38 +0200524``descr.__set__(self, obj, value) -> None``
Georg Brandl45cceeb2010-05-19 21:39:51 +0000525
NotAFile28ea4c22018-09-10 23:35:38 +0200526``descr.__delete__(self, obj) -> None``
Georg Brandl45cceeb2010-05-19 21:39:51 +0000527
528That is all there is to it. Define any of these methods and an object is
529considered a descriptor and can override default behavior upon being looked up
530as an attribute.
531
Aaron Hall, MBA4054b172018-05-20 19:46:42 -0400532If an object defines :meth:`__set__` or :meth:`__delete__`, it is considered
Georg Brandl45cceeb2010-05-19 21:39:51 +0000533a data descriptor. Descriptors that only define :meth:`__get__` are called
Raymond Hettingerc272d402020-11-15 17:44:28 -0800534non-data descriptors (they are often used for methods but other uses are
Georg Brandl45cceeb2010-05-19 21:39:51 +0000535possible).
536
537Data and non-data descriptors differ in how overrides are calculated with
538respect to entries in an instance's dictionary. If an instance's dictionary
539has an entry with the same name as a data descriptor, the data descriptor
540takes precedence. If an instance's dictionary has an entry with the same
541name as a non-data descriptor, the dictionary entry takes precedence.
542
543To make a read-only data descriptor, define both :meth:`__get__` and
544:meth:`__set__` with the :meth:`__set__` raising an :exc:`AttributeError` when
545called. Defining the :meth:`__set__` method with an exception raising
546placeholder is enough to make it a data descriptor.
547
548
Raymond Hettingere9208f02020-11-01 20:15:50 -0800549Overview of descriptor invocation
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800550---------------------------------
Georg Brandl45cceeb2010-05-19 21:39:51 +0000551
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800552A descriptor can be called directly with ``desc.__get__(obj)`` or
553``desc.__get__(None, cls)``.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000554
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700555But it is more common for a descriptor to be invoked automatically from
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800556attribute access.
557
558The expression ``obj.x`` looks up the attribute ``x`` in the chain of
Raymond Hettingerc272d402020-11-15 17:44:28 -0800559namespaces for ``obj``. If the search finds a descriptor outside of the
560instance ``__dict__``, its :meth:`__get__` method is invoked according to the
561precedence rules listed below.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000562
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700563The details of invocation depend on whether ``obj`` is an object, class, or
564instance of super.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000565
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700566
Raymond Hettingere9208f02020-11-01 20:15:50 -0800567Invocation from an instance
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800568---------------------------
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700569
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800570Instance lookup scans through a chain of namespaces giving data descriptors
571the highest priority, followed by instance variables, then non-data
572descriptors, then class variables, and lastly :meth:`__getattr__` if it is
573provided.
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700574
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800575If a descriptor is found for ``a.x``, then it is invoked with:
576``desc.__get__(a, type(a))``.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000577
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800578The logic for a dotted lookup is in :meth:`object.__getattribute__`. Here is
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800579a pure Python equivalent:
580
581.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000582
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800583 def object_getattribute(obj, name):
584 "Emulate PyObject_GenericGetAttr() in Objects/object.c"
585 null = object()
586 objtype = type(obj)
Raymond Hettingerc272d402020-11-15 17:44:28 -0800587 cls_var = getattr(objtype, name, null)
588 descr_get = getattr(type(cls_var), '__get__', null)
589 if descr_get is not null:
590 if (hasattr(type(cls_var), '__set__')
591 or hasattr(type(cls_var), '__delete__')):
592 return descr_get(cls_var, obj, objtype) # data descriptor
593 if hasattr(obj, '__dict__') and name in vars(obj):
594 return vars(obj)[name] # instance variable
595 if descr_get is not null:
596 return descr_get(cls_var, obj, objtype) # non-data descriptor
597 if cls_var is not null:
598 return cls_var # class variable
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800599 raise AttributeError(name)
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700600
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800601
602.. testcode::
603 :hide:
604
605 # Test the fidelity of object_getattribute() by comparing it with the
606 # normal object.__getattribute__(). The former will be accessed by
607 # square brackets and the latter by the dot operator.
608
609 class Object:
610
611 def __getitem__(obj, name):
612 try:
613 return object_getattribute(obj, name)
614 except AttributeError:
615 if not hasattr(type(obj), '__getattr__'):
616 raise
617 return type(obj).__getattr__(obj, name) # __getattr__
618
619 class DualOperator(Object):
620
621 x = 10
622
623 def __init__(self, z):
624 self.z = z
625
626 @property
627 def p2(self):
628 return 2 * self.x
629
630 @property
631 def p3(self):
632 return 3 * self.x
633
634 def m5(self, y):
635 return 5 * y
636
637 def m7(self, y):
638 return 7 * y
639
640 def __getattr__(self, name):
641 return ('getattr_hook', self, name)
642
643 class DualOperatorWithSlots:
644
645 __getitem__ = Object.__getitem__
646
647 __slots__ = ['z']
648
649 x = 15
650
651 def __init__(self, z):
652 self.z = z
653
654 @property
655 def p2(self):
656 return 2 * self.x
657
658 def m5(self, y):
659 return 5 * y
660
661 def __getattr__(self, name):
662 return ('getattr_hook', self, name)
663
664
665.. doctest::
666 :hide:
667
668 >>> a = DualOperator(11)
669 >>> vars(a).update(p3 = '_p3', m7 = '_m7')
670 >>> a.x == a['x'] == 10
671 True
672 >>> a.z == a['z'] == 11
673 True
674 >>> a.p2 == a['p2'] == 20
675 True
676 >>> a.p3 == a['p3'] == 30
677 True
678 >>> a.m5(100) == a.m5(100) == 500
679 True
680 >>> a.m7 == a['m7'] == '_m7'
681 True
682 >>> a.g == a['g'] == ('getattr_hook', a, 'g')
683 True
684
685 >>> b = DualOperatorWithSlots(22)
686 >>> b.x == b['x'] == 15
687 True
688 >>> b.z == b['z'] == 22
689 True
690 >>> b.p2 == b['p2'] == 30
691 True
692 >>> b.m5(200) == b['m5'](200) == 1000
693 True
694 >>> b.g == b['g'] == ('getattr_hook', b, 'g')
695 True
696
697
Raymond Hettingerc272d402020-11-15 17:44:28 -0800698Interestingly, attribute lookup doesn't call :meth:`object.__getattribute__`
699directly. Instead, both the dot operator and the :func:`getattr` function
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800700perform attribute lookup by way of a helper function:
701
702.. testcode::
Raymond Hettingerc272d402020-11-15 17:44:28 -0800703
704 def getattr_hook(obj, name):
705 "Emulate slot_tp_getattr_hook() in Objects/typeobject.c"
706 try:
707 return obj.__getattribute__(name)
708 except AttributeError:
709 if not hasattr(type(obj), '__getattr__'):
710 raise
711 return type(obj).__getattr__(obj, name) # __getattr__
712
713So if :meth:`__getattr__` exists, it is called whenever :meth:`__getattribute__`
714raises :exc:`AttributeError` (either directly or in one of the descriptor calls).
715
716Also, if a user calls :meth:`object.__getattribute__` directly, the
717:meth:`__getattr__` hook is bypassed entirely.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000718
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800719
Raymond Hettingere9208f02020-11-01 20:15:50 -0800720Invocation from a class
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800721-----------------------
722
723The logic for a dotted lookup such as ``A.x`` is in
724:meth:`type.__getattribute__`. The steps are similar to those for
725:meth:`object.__getattribute__` but the instance dictionary lookup is replaced
726by a search through the class's :term:`method resolution order`.
727
728If a descriptor is found, it is invoked with ``desc.__get__(None, A)``.
729
730The full C implementation can be found in :c:func:`type_getattro()` and
731:c:func:`_PyType_Lookup()` in :source:`Objects/typeobject.c`.
732
733
Raymond Hettingere9208f02020-11-01 20:15:50 -0800734Invocation from super
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800735---------------------
736
737The logic for super's dotted lookup is in the :meth:`__getattribute__` method for
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700738object returned by :class:`super()`.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000739
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800740A dotted lookup such as ``super(A, obj).m`` searches ``obj.__class__.__mro__``
741for the base class ``B`` immediately following ``A`` and then returns
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700742``B.__dict__['m'].__get__(obj, A)``. If not a descriptor, ``m`` is returned
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800743unchanged.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000744
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800745The full C implementation can be found in :c:func:`super_getattro()` in
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700746:source:`Objects/typeobject.c`. A pure Python equivalent can be found in
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800747`Guido's Tutorial
748<https://www.python.org/download/releases/2.2.3/descrintro/#cooperation>`_.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000749
Georg Brandl45cceeb2010-05-19 21:39:51 +0000750
Raymond Hettingere9208f02020-11-01 20:15:50 -0800751Summary of invocation logic
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800752---------------------------
753
754The mechanism for descriptors is embedded in the :meth:`__getattribute__()`
755methods for :class:`object`, :class:`type`, and :func:`super`.
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700756
757The important points to remember are:
758
759* Descriptors are invoked by the :meth:`__getattribute__` method.
760
761* Classes inherit this machinery from :class:`object`, :class:`type`, or
762 :func:`super`.
763
764* Overriding :meth:`__getattribute__` prevents automatic descriptor calls
765 because all the descriptor logic is in that method.
766
767* :meth:`object.__getattribute__` and :meth:`type.__getattribute__` make
768 different calls to :meth:`__get__`. The first includes the instance and may
769 include the class. The second puts in ``None`` for the instance and always
770 includes the class.
771
772* Data descriptors always override instance dictionaries.
773
774* Non-data descriptors may be overridden by instance dictionaries.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000775
776
Raymond Hettingere9208f02020-11-01 20:15:50 -0800777Automatic name notification
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700778---------------------------
779
780Sometimes it is desirable for a descriptor to know what class variable name it
781was assigned to. When a new class is created, the :class:`type` metaclass
782scans the dictionary of the new class. If any of the entries are descriptors
783and if they define :meth:`__set_name__`, that method is called with two
Raymond Hettinger80318772020-11-06 01:30:17 -0800784arguments. The *owner* is the class where the descriptor is used, and the
785*name* is the class variable the descriptor was assigned to.
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700786
787The implementation details are in :c:func:`type_new()` and
788:c:func:`set_names()` in :source:`Objects/typeobject.c`.
789
790Since the update logic is in :meth:`type.__new__`, notifications only take
791place at the time of class creation. If descriptors are added to the class
792afterwards, :meth:`__set_name__` will need to be called manually.
793
794
Raymond Hettingere9208f02020-11-01 20:15:50 -0800795ORM example
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700796-----------
Georg Brandl45cceeb2010-05-19 21:39:51 +0000797
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700798The following code is simplified skeleton showing how data descriptors could
799be used to implement an `object relational mapping
800<https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping>`_.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000801
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700802The essential idea is that the data is stored in an external database. The
803Python instances only hold keys to the database's tables. Descriptors take
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800804care of lookups or updates:
805
806.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000807
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700808 class Field:
809
810 def __set_name__(self, owner, name):
811 self.fetch = f'SELECT {name} FROM {owner.table} WHERE {owner.key}=?;'
812 self.store = f'UPDATE {owner.table} SET {name}=? WHERE {owner.key}=?;'
Georg Brandl45cceeb2010-05-19 21:39:51 +0000813
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700814 def __get__(self, obj, objtype=None):
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700815 return conn.execute(self.fetch, [obj.key]).fetchone()[0]
Georg Brandl45cceeb2010-05-19 21:39:51 +0000816
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700817 def __set__(self, obj, value):
818 conn.execute(self.store, [value, obj.key])
819 conn.commit()
Georg Brandl45cceeb2010-05-19 21:39:51 +0000820
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800821We can use the :class:`Field` class to define `models
822<https://en.wikipedia.org/wiki/Database_model>`_ that describe the schema for
823each table in a database:
824
825.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -0700826
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700827 class Movie:
828 table = 'Movies' # Table name
829 key = 'title' # Primary key
830 director = Field()
831 year = Field()
Georg Brandl45cceeb2010-05-19 21:39:51 +0000832
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700833 def __init__(self, key):
834 self.key = key
835
836 class Song:
837 table = 'Music'
838 key = 'title'
839 artist = Field()
840 year = Field()
841 genre = Field()
842
843 def __init__(self, key):
844 self.key = key
845
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800846To use the models, first connect to the database::
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700847
848 >>> import sqlite3
849 >>> conn = sqlite3.connect('entertainment.db')
850
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800851An interactive session shows how data is retrieved from the database and how
852it can be updated:
853
854.. testsetup::
855
856 song_data = [
857 ('Country Roads', 'John Denver', 1972),
858 ('Me and Bobby McGee', 'Janice Joplin', 1971),
859 ('Coal Miners Daughter', 'Loretta Lynn', 1970),
860 ]
861
862 movie_data = [
863 ('Star Wars', 'George Lucas', 1977),
864 ('Jaws', 'Steven Spielberg', 1975),
865 ('Aliens', 'James Cameron', 1986),
866 ]
867
868 import sqlite3
869
870 conn = sqlite3.connect(':memory:')
871 conn.execute('CREATE TABLE Music (title text, artist text, year integer);')
872 conn.execute('CREATE INDEX MusicNdx ON Music (title);')
873 conn.executemany('INSERT INTO Music VALUES (?, ?, ?);', song_data)
874 conn.execute('CREATE TABLE Movies (title text, director text, year integer);')
875 conn.execute('CREATE INDEX MovieNdx ON Music (title);')
876 conn.executemany('INSERT INTO Movies VALUES (?, ?, ?);', movie_data)
877 conn.commit()
878
879.. doctest::
880
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700881 >>> Movie('Star Wars').director
882 'George Lucas'
883 >>> jaws = Movie('Jaws')
884 >>> f'Released in {jaws.year} by {jaws.director}'
885 'Released in 1975 by Steven Spielberg'
886
887 >>> Song('Country Roads').artist
888 'John Denver'
889
890 >>> Movie('Star Wars').director = 'J.J. Abrams'
891 >>> Movie('Star Wars').director
892 'J.J. Abrams'
893
Raymond Hettingerc272d402020-11-15 17:44:28 -0800894
Raymond Hettingere6a7ea42020-10-25 07:12:50 -0700895Pure Python Equivalents
896^^^^^^^^^^^^^^^^^^^^^^^
897
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700898The descriptor protocol is simple and offers exciting possibilities. Several
Raymond Hettinger148c76b2020-11-01 09:10:06 -0800899use cases are so common that they have been prepackaged into built-in tools.
Raymond Hettingere9208f02020-11-01 20:15:50 -0800900Properties, bound methods, static methods, class methods, and \_\_slots\_\_ are
901all based on the descriptor protocol.
Georg Brandl45cceeb2010-05-19 21:39:51 +0000902
903
904Properties
905----------
906
907Calling :func:`property` is a succinct way of building a data descriptor that
Raymond Hettinger80318772020-11-06 01:30:17 -0800908triggers a function call upon access to an attribute. Its signature is::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000909
Raymond Hettinger4a9c6372020-10-24 20:34:39 -0700910 property(fget=None, fset=None, fdel=None, doc=None) -> property
Georg Brandl45cceeb2010-05-19 21:39:51 +0000911
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800912The documentation shows a typical use to define a managed attribute ``x``:
913
914.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000915
Serhiy Storchakae042a452019-06-10 13:35:52 +0300916 class C:
Georg Brandl45cceeb2010-05-19 21:39:51 +0000917 def getx(self): return self.__x
918 def setx(self, value): self.__x = value
919 def delx(self): del self.__x
920 x = property(getx, setx, delx, "I'm the 'x' property.")
921
922To see how :func:`property` is implemented in terms of the descriptor protocol,
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800923here is a pure Python equivalent:
924
925.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +0000926
Serhiy Storchakae042a452019-06-10 13:35:52 +0300927 class Property:
Georg Brandl45cceeb2010-05-19 21:39:51 +0000928 "Emulate PyProperty_Type() in Objects/descrobject.c"
929
930 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
931 self.fget = fget
932 self.fset = fset
933 self.fdel = fdel
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700934 if doc is None and fget is not None:
935 doc = fget.__doc__
Georg Brandl45cceeb2010-05-19 21:39:51 +0000936 self.__doc__ = doc
937
938 def __get__(self, obj, objtype=None):
939 if obj is None:
940 return self
941 if self.fget is None:
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700942 raise AttributeError("unreadable attribute")
Georg Brandl45cceeb2010-05-19 21:39:51 +0000943 return self.fget(obj)
944
945 def __set__(self, obj, value):
946 if self.fset is None:
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700947 raise AttributeError("can't set attribute")
Georg Brandl45cceeb2010-05-19 21:39:51 +0000948 self.fset(obj, value)
949
950 def __delete__(self, obj):
951 if self.fdel is None:
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700952 raise AttributeError("can't delete attribute")
Georg Brandl45cceeb2010-05-19 21:39:51 +0000953 self.fdel(obj)
954
Raymond Hettinger632c8c82013-03-10 09:41:18 -0700955 def getter(self, fget):
956 return type(self)(fget, self.fset, self.fdel, self.__doc__)
957
958 def setter(self, fset):
959 return type(self)(self.fget, fset, self.fdel, self.__doc__)
960
961 def deleter(self, fdel):
962 return type(self)(self.fget, self.fset, fdel, self.__doc__)
963
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -0800964.. testcode::
965 :hide:
966
967 # Verify the Property() emulation
968
969 class CC:
970 def getx(self):
971 return self.__x
972 def setx(self, value):
973 self.__x = value
974 def delx(self):
975 del self.__x
976 x = Property(getx, setx, delx, "I'm the 'x' property.")
977
978 # Now do it again but use the decorator style
979
980 class CCC:
981 @Property
982 def x(self):
983 return self.__x
984 @x.setter
985 def x(self, value):
986 self.__x = value
987 @x.deleter
988 def x(self):
989 del self.__x
990
991
992.. doctest::
993 :hide:
994
995 >>> cc = CC()
996 >>> hasattr(cc, 'x')
997 False
998 >>> cc.x = 33
999 >>> cc.x
1000 33
1001 >>> del cc.x
1002 >>> hasattr(cc, 'x')
1003 False
1004
1005 >>> ccc = CCC()
1006 >>> hasattr(ccc, 'x')
1007 False
1008 >>> ccc.x = 333
1009 >>> ccc.x == 333
1010 True
1011 >>> del ccc.x
1012 >>> hasattr(ccc, 'x')
1013 False
1014
Georg Brandl45cceeb2010-05-19 21:39:51 +00001015The :func:`property` builtin helps whenever a user interface has granted
1016attribute access and then subsequent changes require the intervention of a
1017method.
1018
1019For instance, a spreadsheet class may grant access to a cell value through
1020``Cell('b10').value``. Subsequent improvements to the program require the cell
1021to be recalculated on every access; however, the programmer does not want to
1022affect existing client code accessing the attribute directly. The solution is
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001023to wrap access to the value attribute in a property data descriptor:
1024
1025.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001026
Serhiy Storchakae042a452019-06-10 13:35:52 +03001027 class Cell:
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001028 ...
1029
1030 @property
1031 def value(self):
_ = NaNb066edf2017-06-23 11:54:35 +08001032 "Recalculate the cell before returning value"
Georg Brandl45cceeb2010-05-19 21:39:51 +00001033 self.recalc()
_ = NaNb066edf2017-06-23 11:54:35 +08001034 return self._value
Georg Brandl45cceeb2010-05-19 21:39:51 +00001035
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001036Either the built-in :func:`property` or our :func:`Property` equivalent would
1037work in this example.
1038
Georg Brandl45cceeb2010-05-19 21:39:51 +00001039
Raymond Hettingere9208f02020-11-01 20:15:50 -08001040Functions and methods
Georg Brandl45cceeb2010-05-19 21:39:51 +00001041---------------------
1042
1043Python's object oriented features are built upon a function based environment.
1044Using non-data descriptors, the two are merged seamlessly.
1045
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001046Functions stored in class dictionaries get turned into methods when invoked.
1047Methods only differ from regular functions in that the object instance is
1048prepended to the other arguments. By convention, the instance is called
1049*self* but could be called *this* or any other variable name.
Georg Brandl45cceeb2010-05-19 21:39:51 +00001050
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001051Methods can be created manually with :class:`types.MethodType` which is
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001052roughly equivalent to:
1053
1054.. testcode::
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001055
Raymond Hettingere6a7ea42020-10-25 07:12:50 -07001056 class MethodType:
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001057 "Emulate Py_MethodType in Objects/classobject.c"
1058
1059 def __init__(self, func, obj):
1060 self.__func__ = func
1061 self.__self__ = obj
1062
1063 def __call__(self, *args, **kwargs):
1064 func = self.__func__
1065 obj = self.__self__
1066 return func(obj, *args, **kwargs)
1067
1068To support automatic creation of methods, functions include the
1069:meth:`__get__` method for binding methods during attribute access. This
Raymond Hettinger80318772020-11-06 01:30:17 -08001070means that functions are non-data descriptors that return bound methods
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001071during dotted lookup from an instance. Here's how it works:
1072
1073.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001074
Serhiy Storchakae042a452019-06-10 13:35:52 +03001075 class Function:
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001076 ...
1077
Georg Brandl45cceeb2010-05-19 21:39:51 +00001078 def __get__(self, obj, objtype=None):
1079 "Simulate func_descr_get() in Objects/funcobject.c"
Raymond Hettinger0d4497b2017-09-25 01:05:49 -07001080 if obj is None:
1081 return self
Raymond Hettingere6a7ea42020-10-25 07:12:50 -07001082 return MethodType(self, obj)
Georg Brandl45cceeb2010-05-19 21:39:51 +00001083
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001084Running the following class in the interpreter shows how the function
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001085descriptor works in practice:
1086
1087.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001088
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001089 class D:
1090 def f(self, x):
1091 return x
Raymond Hettinger0d4497b2017-09-25 01:05:49 -07001092
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001093The function has a :term:`qualified name` attribute to support introspection:
1094
1095.. doctest::
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001096
1097 >>> D.f.__qualname__
1098 'D.f'
1099
1100Accessing the function through the class dictionary does not invoke
1101:meth:`__get__`. Instead, it just returns the underlying function object::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001102
Raymond Hettinger0d4497b2017-09-25 01:05:49 -07001103 >>> D.__dict__['f']
1104 <function D.f at 0x00C45070>
1105
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001106Dotted access from a class calls :meth:`__get__` which just returns the
1107underlying function unchanged::
1108
Raymond Hettinger0d4497b2017-09-25 01:05:49 -07001109 >>> D.f
1110 <function D.f at 0x00C45070>
1111
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001112The interesting behavior occurs during dotted access from an instance. The
1113dotted lookup calls :meth:`__get__` which returns a bound method object::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001114
1115 >>> d = D()
Raymond Hettinger0d4497b2017-09-25 01:05:49 -07001116 >>> d.f
Georg Brandl45cceeb2010-05-19 21:39:51 +00001117 <bound method D.f of <__main__.D object at 0x00B18C90>>
1118
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001119Internally, the bound method stores the underlying function and the bound
1120instance::
1121
Raymond Hettinger0d4497b2017-09-25 01:05:49 -07001122 >>> d.f.__func__
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001123 <function D.f at 0x00C45070>
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001124
Raymond Hettinger0d4497b2017-09-25 01:05:49 -07001125 >>> d.f.__self__
1126 <__main__.D object at 0x1012e1f98>
Georg Brandl45cceeb2010-05-19 21:39:51 +00001127
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001128If you have ever wondered where *self* comes from in regular methods or where
1129*cls* comes from in class methods, this is it!
1130
Georg Brandl45cceeb2010-05-19 21:39:51 +00001131
Raymond Hettingere9208f02020-11-01 20:15:50 -08001132Static methods
Raymond Hettingere6a7ea42020-10-25 07:12:50 -07001133--------------
Georg Brandl45cceeb2010-05-19 21:39:51 +00001134
1135Non-data descriptors provide a simple mechanism for variations on the usual
1136patterns of binding functions into methods.
1137
1138To recap, functions have a :meth:`__get__` method so that they can be converted
Serhiy Storchakad65c9492015-11-02 14:10:23 +02001139to a method when accessed as attributes. The non-data descriptor transforms an
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001140``obj.f(*args)`` call into ``f(obj, *args)``. Calling ``cls.f(*args)``
Georg Brandl45cceeb2010-05-19 21:39:51 +00001141becomes ``f(*args)``.
1142
1143This chart summarizes the binding and its two most useful variants:
1144
1145 +-----------------+----------------------+------------------+
1146 | Transformation | Called from an | Called from a |
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001147 | | object | class |
Georg Brandl45cceeb2010-05-19 21:39:51 +00001148 +=================+======================+==================+
1149 | function | f(obj, \*args) | f(\*args) |
1150 +-----------------+----------------------+------------------+
1151 | staticmethod | f(\*args) | f(\*args) |
1152 +-----------------+----------------------+------------------+
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001153 | classmethod | f(type(obj), \*args) | f(cls, \*args) |
Georg Brandl45cceeb2010-05-19 21:39:51 +00001154 +-----------------+----------------------+------------------+
1155
1156Static methods return the underlying function without changes. Calling either
1157``c.f`` or ``C.f`` is the equivalent of a direct lookup into
1158``object.__getattribute__(c, "f")`` or ``object.__getattribute__(C, "f")``. As a
1159result, the function becomes identically accessible from either an object or a
1160class.
1161
1162Good candidates for static methods are methods that do not reference the
1163``self`` variable.
1164
1165For instance, a statistics package may include a container class for
1166experimental data. The class provides normal methods for computing the average,
1167mean, median, and other descriptive statistics that depend on the data. However,
1168there may be useful functions which are conceptually related but do not depend
1169on the data. For instance, ``erf(x)`` is handy conversion routine that comes up
1170in statistical work but does not directly depend on a particular dataset.
1171It can be called either from an object or the class: ``s.erf(1.5) --> .9332`` or
1172``Sample.erf(1.5) --> .9332``.
1173
Raymond Hettinger4a9c6372020-10-24 20:34:39 -07001174Since static methods return the underlying function with no changes, the
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001175example calls are unexciting:
1176
1177.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001178
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001179 class E:
1180 @staticmethod
1181 def f(x):
1182 print(x)
1183
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001184.. doctest::
1185
Shubham Aggarwalabbdd1f2019-03-20 08:25:55 +05301186 >>> E.f(3)
Georg Brandl45cceeb2010-05-19 21:39:51 +00001187 3
Shubham Aggarwalabbdd1f2019-03-20 08:25:55 +05301188 >>> E().f(3)
Georg Brandl45cceeb2010-05-19 21:39:51 +00001189 3
1190
1191Using the non-data descriptor protocol, a pure Python version of
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001192:func:`staticmethod` would look like this:
1193
1194.. doctest::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001195
Serhiy Storchakae042a452019-06-10 13:35:52 +03001196 class StaticMethod:
Serhiy Storchakadba90392016-05-10 12:01:23 +03001197 "Emulate PyStaticMethod_Type() in Objects/funcobject.c"
Georg Brandl45cceeb2010-05-19 21:39:51 +00001198
Serhiy Storchakadba90392016-05-10 12:01:23 +03001199 def __init__(self, f):
1200 self.f = f
Georg Brandl45cceeb2010-05-19 21:39:51 +00001201
Serhiy Storchakadba90392016-05-10 12:01:23 +03001202 def __get__(self, obj, objtype=None):
1203 return self.f
Georg Brandl45cceeb2010-05-19 21:39:51 +00001204
Raymond Hettingere6a7ea42020-10-25 07:12:50 -07001205
Raymond Hettingere9208f02020-11-01 20:15:50 -08001206Class methods
Raymond Hettingere6a7ea42020-10-25 07:12:50 -07001207-------------
1208
Georg Brandl45cceeb2010-05-19 21:39:51 +00001209Unlike static methods, class methods prepend the class reference to the
1210argument list before calling the function. This format is the same
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001211for whether the caller is an object or a class:
1212
1213.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001214
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001215 class F:
1216 @classmethod
1217 def f(cls, x):
1218 return cls.__name__, x
1219
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001220.. doctest::
1221
1222 >>> F.f(3)
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001223 ('F', 3)
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001224 >>> F().f(3)
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001225 ('F', 3)
Georg Brandl45cceeb2010-05-19 21:39:51 +00001226
Raymond Hettingere6a7ea42020-10-25 07:12:50 -07001227This behavior is useful whenever the method only needs to have a class
1228reference and does rely on data stored in a specific instance. One use for
1229class methods is to create alternate class constructors. For example, the
1230classmethod :func:`dict.fromkeys` creates a new dictionary from a list of
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001231keys. The pure Python equivalent is:
Georg Brandl45cceeb2010-05-19 21:39:51 +00001232
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001233.. testcode::
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001234
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001235 class Dict(dict):
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001236 @classmethod
1237 def fromkeys(cls, iterable, value=None):
Georg Brandl45cceeb2010-05-19 21:39:51 +00001238 "Emulate dict_fromkeys() in Objects/dictobject.c"
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001239 d = cls()
Georg Brandl45cceeb2010-05-19 21:39:51 +00001240 for key in iterable:
1241 d[key] = value
1242 return d
Georg Brandl45cceeb2010-05-19 21:39:51 +00001243
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001244Now a new dictionary of unique keys can be constructed like this:
1245
1246.. doctest::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001247
Raymond Hettinger85c84922020-11-25 01:54:24 -08001248 >>> d = Dict.fromkeys('abracadabra')
1249 >>> type(d) is Dict
1250 True
1251 >>> d
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001252 {'a': None, 'b': None, 'r': None, 'c': None, 'd': None}
Georg Brandl45cceeb2010-05-19 21:39:51 +00001253
1254Using the non-data descriptor protocol, a pure Python version of
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001255:func:`classmethod` would look like this:
1256
1257.. testcode::
Georg Brandl45cceeb2010-05-19 21:39:51 +00001258
Serhiy Storchakae042a452019-06-10 13:35:52 +03001259 class ClassMethod:
Serhiy Storchakadba90392016-05-10 12:01:23 +03001260 "Emulate PyClassMethod_Type() in Objects/funcobject.c"
Georg Brandl45cceeb2010-05-19 21:39:51 +00001261
Serhiy Storchakadba90392016-05-10 12:01:23 +03001262 def __init__(self, f):
1263 self.f = f
Georg Brandl45cceeb2010-05-19 21:39:51 +00001264
Raymond Hettinger8d3d7312020-10-23 12:55:39 -07001265 def __get__(self, obj, cls=None):
1266 if cls is None:
1267 cls = type(obj)
Raymond Hettinger8e5b0fd2020-10-23 18:37:27 -07001268 if hasattr(obj, '__get__'):
1269 return self.f.__get__(cls)
Raymond Hettingere6a7ea42020-10-25 07:12:50 -07001270 return MethodType(self.f, cls)
Raymond Hettinger8e5b0fd2020-10-23 18:37:27 -07001271
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001272.. testcode::
1273 :hide:
1274
1275 # Verify the emulation works
1276 class T:
1277 @ClassMethod
1278 def cm(cls, x, y):
1279 return (cls, x, y)
1280
1281.. doctest::
1282 :hide:
1283
1284 >>> T.cm(11, 22)
1285 (<class 'T'>, 11, 22)
1286
1287 # Also call it from an instance
1288 >>> t = T()
1289 >>> t.cm(11, 22)
1290 (<class 'T'>, 11, 22)
1291
Raymond Hettinger8e5b0fd2020-10-23 18:37:27 -07001292The code path for ``hasattr(obj, '__get__')`` was added in Python 3.9 and
1293makes it possible for :func:`classmethod` to support chained decorators.
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001294For example, a classmethod and property could be chained together:
1295
1296.. testcode::
Raymond Hettinger8e5b0fd2020-10-23 18:37:27 -07001297
1298 class G:
1299 @classmethod
1300 @property
1301 def __doc__(cls):
1302 return f'A doc for {cls.__name__!r}'
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001303
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001304.. doctest::
1305
1306 >>> G.__doc__
1307 "A doc for 'G'"
1308
1309
Raymond Hettingere9208f02020-11-01 20:15:50 -08001310Member objects and __slots__
1311----------------------------
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001312
1313When a class defines ``__slots__``, it replaces instance dictionaries with a
1314fixed-length array of slot values. From a user point of view that has
1315several effects:
1316
13171. Provides immediate detection of bugs due to misspelled attribute
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001318assignments. Only attribute names specified in ``__slots__`` are allowed:
1319
1320.. testcode::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001321
1322 class Vehicle:
1323 __slots__ = ('id_number', 'make', 'model')
1324
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001325.. doctest::
1326
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001327 >>> auto = Vehicle()
1328 >>> auto.id_nubmer = 'VYE483814LQEX'
1329 Traceback (most recent call last):
1330 ...
1331 AttributeError: 'Vehicle' object has no attribute 'id_nubmer'
1332
13332. Helps create immutable objects where descriptors manage access to private
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001334attributes stored in ``__slots__``:
1335
1336.. testcode::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001337
1338 class Immutable:
1339
Raymond Hettinger80318772020-11-06 01:30:17 -08001340 __slots__ = ('_dept', '_name') # Replace the instance dictionary
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001341
1342 def __init__(self, dept, name):
1343 self._dept = dept # Store to private attribute
1344 self._name = name # Store to private attribute
1345
1346 @property # Read-only descriptor
1347 def dept(self):
1348 return self._dept
1349
1350 @property
1351 def name(self): # Read-only descriptor
1352 return self._name
1353
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001354.. doctest::
1355
1356 >>> mark = Immutable('Botany', 'Mark Watney')
1357 >>> mark.dept
1358 'Botany'
1359 >>> mark.dept = 'Space Pirate'
1360 Traceback (most recent call last):
1361 ...
1362 AttributeError: can't set attribute
1363 >>> mark.location = 'Mars'
1364 Traceback (most recent call last):
1365 ...
1366 AttributeError: 'Immutable' object has no attribute 'location'
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001367
13683. Saves memory. On a 64-bit Linux build, an instance with two attributes
1369takes 48 bytes with ``__slots__`` and 152 bytes without. This `flyweight
1370design pattern <https://en.wikipedia.org/wiki/Flyweight_pattern>`_ likely only
1371matters when a large number of instances are going to be created.
1372
13734. Blocks tools like :func:`functools.cached_property` which require an
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001374instance dictionary to function correctly:
1375
1376.. testcode::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001377
1378 from functools import cached_property
1379
1380 class CP:
1381 __slots__ = () # Eliminates the instance dict
1382
1383 @cached_property # Requires an instance dict
1384 def pi(self):
1385 return 4 * sum((-1.0)**n / (2.0*n + 1.0)
1386 for n in reversed(range(100_000)))
1387
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001388.. doctest::
1389
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001390 >>> CP().pi
1391 Traceback (most recent call last):
1392 ...
1393 TypeError: No '__dict__' attribute on 'CP' instance to cache 'pi' property.
1394
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001395It is not possible to create an exact drop-in pure Python version of
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001396``__slots__`` because it requires direct access to C structures and control
1397over object memory allocation. However, we can build a mostly faithful
1398simulation where the actual C structure for slots is emulated by a private
1399``_slotvalues`` list. Reads and writes to that private structure are managed
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001400by member descriptors:
1401
1402.. testcode::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001403
Raymond Hettingerffae9322020-11-23 10:56:59 -08001404 null = object()
1405
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001406 class Member:
1407
1408 def __init__(self, name, clsname, offset):
1409 'Emulate PyMemberDef in Include/structmember.h'
1410 # Also see descr_new() in Objects/descrobject.c
1411 self.name = name
1412 self.clsname = clsname
1413 self.offset = offset
1414
1415 def __get__(self, obj, objtype=None):
1416 'Emulate member_get() in Objects/descrobject.c'
1417 # Also see PyMember_GetOne() in Python/structmember.c
Raymond Hettingerffae9322020-11-23 10:56:59 -08001418 value = obj._slotvalues[self.offset]
1419 if value is null:
1420 raise AttributeError(self.name)
1421 return value
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001422
1423 def __set__(self, obj, value):
1424 'Emulate member_set() in Objects/descrobject.c'
1425 obj._slotvalues[self.offset] = value
1426
Raymond Hettingerffae9322020-11-23 10:56:59 -08001427 def __delete__(self, obj):
1428 'Emulate member_delete() in Objects/descrobject.c'
1429 value = obj._slotvalues[self.offset]
1430 if value is null:
1431 raise AttributeError(self.name)
1432 obj._slotvalues[self.offset] = null
1433
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001434 def __repr__(self):
1435 'Emulate member_repr() in Objects/descrobject.c'
1436 return f'<Member {self.name!r} of {self.clsname!r}>'
1437
1438The :meth:`type.__new__` method takes care of adding member objects to class
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001439variables:
1440
1441.. testcode::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001442
1443 class Type(type):
1444 'Simulate how the type metaclass adds member objects for slots'
1445
1446 def __new__(mcls, clsname, bases, mapping):
1447 'Emuluate type_new() in Objects/typeobject.c'
1448 # type_new() calls PyTypeReady() which calls add_methods()
1449 slot_names = mapping.get('slot_names', [])
1450 for offset, name in enumerate(slot_names):
1451 mapping[name] = Member(name, clsname, offset)
1452 return type.__new__(mcls, clsname, bases, mapping)
1453
Raymond Hettingerffae9322020-11-23 10:56:59 -08001454The :meth:`object.__new__` method takes care of creating instances that have
1455slots instead of an instance dictionary. Here is a rough simulation in pure
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001456Python:
1457
1458.. testcode::
Raymond Hettingerffae9322020-11-23 10:56:59 -08001459
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001460 class Object:
1461 'Simulate how object.__new__() allocates memory for __slots__'
1462
1463 def __new__(cls, *args):
1464 'Emulate object_new() in Objects/typeobject.c'
1465 inst = super().__new__(cls)
1466 if hasattr(cls, 'slot_names'):
Raymond Hettingerffae9322020-11-23 10:56:59 -08001467 empty_slots = [null] * len(cls.slot_names)
1468 object.__setattr__(inst, '_slotvalues', empty_slots)
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001469 return inst
1470
Raymond Hettingerffae9322020-11-23 10:56:59 -08001471 def __setattr__(self, name, value):
1472 'Emulate _PyObject_GenericSetAttrWithDict() Objects/object.c'
1473 cls = type(self)
1474 if hasattr(cls, 'slot_names') and name not in cls.slot_names:
1475 raise AttributeError(
1476 f'{type(self).__name__!r} object has no attribute {name!r}'
1477 )
1478 super().__setattr__(name, value)
1479
1480 def __delattr__(self, name):
1481 'Emulate _PyObject_GenericSetAttrWithDict() Objects/object.c'
1482 cls = type(self)
1483 if hasattr(cls, 'slot_names') and name not in cls.slot_names:
1484 raise AttributeError(
1485 f'{type(self).__name__!r} object has no attribute {name!r}'
1486 )
1487 super().__delattr__(name)
1488
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001489To use the simulation in a real class, just inherit from :class:`Object` and
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001490set the :term:`metaclass` to :class:`Type`:
1491
1492.. testcode::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001493
1494 class H(Object, metaclass=Type):
Raymond Hettingerffae9322020-11-23 10:56:59 -08001495 'Instance variables stored in slots'
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001496
1497 slot_names = ['x', 'y']
1498
1499 def __init__(self, x, y):
1500 self.x = x
1501 self.y = y
1502
1503At this point, the metaclass has loaded member objects for *x* and *y*::
1504
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001505 >>> from pprint import pp
1506 >>> pp(dict(vars(H)))
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001507 {'__module__': '__main__',
Raymond Hettingerffae9322020-11-23 10:56:59 -08001508 '__doc__': 'Instance variables stored in slots',
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001509 'slot_names': ['x', 'y'],
1510 '__init__': <function H.__init__ at 0x7fb5d302f9d0>,
1511 'x': <Member 'x' of 'H'>,
Raymond Hettingerffae9322020-11-23 10:56:59 -08001512 'y': <Member 'y' of 'H'>}
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001513
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001514.. doctest::
1515 :hide:
1516
1517 # We test this separately because the preceding section is not
1518 # doctestable due to the hex memory address for the __init__ function
1519 >>> isinstance(vars(H)['x'], Member)
1520 True
1521 >>> isinstance(vars(H)['y'], Member)
1522 True
1523
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001524When instances are created, they have a ``slot_values`` list where the
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001525attributes are stored:
1526
1527.. doctest::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001528
1529 >>> h = H(10, 20)
1530 >>> vars(h)
1531 {'_slotvalues': [10, 20]}
1532 >>> h.x = 55
1533 >>> vars(h)
1534 {'_slotvalues': [55, 20]}
1535
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001536Misspelled or unassigned attributes will raise an exception:
1537
1538.. doctest::
Raymond Hettinger74fa4642020-11-01 18:02:37 -08001539
Raymond Hettingerffae9322020-11-23 10:56:59 -08001540 >>> h.xz
1541 Traceback (most recent call last):
1542 ...
1543 AttributeError: 'H' object has no attribute 'xz'
Raymond Hettinger2d44a6b2020-11-24 20:57:02 -08001544
1545.. doctest::
1546 :hide:
1547
1548 # Examples for deleted attributes are not shown because this section
1549 # is already a bit lengthy. We still test that code here.
1550 >>> del h.x
1551 >>> hasattr(h, 'x')
1552 False
1553
1554 # Also test the code for uninitialized slots
1555 >>> class HU(Object, metaclass=Type):
1556 ... slot_names = ['x', 'y']
1557 ...
1558 >>> hu = HU()
1559 >>> hasattr(hu, 'x')
1560 False
1561 >>> hasattr(hu, 'y')
1562 False