1.. _descriptorhowto: 2 3====================== 4Descriptor HowTo Guide 5====================== 6 7:Author: Raymond Hettinger 8:Contact: <python at rcn dot com> 9 10.. Contents:: 11 12 13:term:`Descriptors <descriptor>` let objects customize attribute lookup, 14storage, and deletion. 15 16This guide has four major sections: 17 181) The "primer" gives a basic overview, moving gently from simple examples, 19 adding one feature at a time. Start here if you're new to descriptors. 20 212) The second section shows a complete, practical descriptor example. If you 22 already know the basics, start there. 23 243) The third section provides a more technical tutorial that goes into the 25 detailed mechanics of how descriptors work. Most people don't need this 26 level of detail. 27 284) 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 30 into bound methods or about the implementation of common tools like 31 :func:`classmethod`, :func:`staticmethod`, :func:`property`, and 32 :term:`__slots__`. 33 34 35Primer 36^^^^^^ 37 38In this primer, we start with the most basic possible example and then we'll 39add new capabilities one by one. 40 41 42Simple example: A descriptor that returns a constant 43---------------------------------------------------- 44 45The :class:`Ten` class is a descriptor whose :meth:`__get__` method always 46returns the constant ``10``: 47 48.. testcode:: 49 50 class Ten: 51 def __get__(self, obj, objtype=None): 52 return 10 53 54To use the descriptor, it must be stored as a class variable in another class: 55 56.. testcode:: 57 58 class A: 59 x = 5 # Regular class attribute 60 y = Ten() # Descriptor instance 61 62An interactive session shows the difference between normal attribute lookup 63and descriptor lookup: 64 65.. doctest:: 66 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 73In the ``a.x`` attribute lookup, the dot operator finds ``'x': 5`` 74in the class dictionary. In the ``a.y`` lookup, the dot operator 75finds a descriptor instance, recognized by its ``__get__`` method. 76Calling that method returns ``10``. 77 78Note 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 90Interesting descriptors typically run computations instead of returning 91constants: 92 93.. testcode:: 94 95 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 104 size = DirectorySize() # Descriptor instance 105 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 112 >>> s = Directory('songs') 113 >>> g = Directory('games') 114 >>> s.size # The songs directory has twenty files 115 20 116 >>> g.size # The games directory has three files 117 3 118 >>> os.remove('games/chess') # Delete a game 119 >>> g.size # File count is automatically updated 120 2 121 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 125either *g* or *s*, an instance of *Directory*. It is the *obj* parameter that 126lets 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 141the lookup or update: 142 143.. testcode:: 144 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 162 age = LoggedAgeAccess() # Descriptor instance 163 164 def __init__(self, name, age): 165 self.name = name # Regular instance attribute 166 self.age = age # Calls __set__() 167 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.. testcode:: 176 :hide: 177 178 import logging, sys 179 logging.basicConfig(level=logging.INFO, stream=sys.stdout, force=True) 180 181.. doctest:: 182 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 206One major issue with this example is that the private name *_age* is hardwired in 207the *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 212Customized names 213---------------- 214 215When a class uses descriptors, it can inform each descriptor about which 216variable 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 221be recorded, giving each descriptor its own *public_name* and *private_name*: 222 223.. testcode:: 224 225 import logging 226 227 logging.basicConfig(level=logging.INFO) 228 229 class LoggedAccess: 230 231 def __set_name__(self, owner, name): 232 self.public_name = name 233 self.private_name = '_' + name 234 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 246 name = LoggedAccess() # First descriptor instance 247 age = LoggedAccess() # Second descriptor instance 248 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 258we call :func:`vars` to look up the descriptor without triggering it: 259 260.. doctest:: 261 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 267The 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:: 276 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.. doctest:: 287 288 >>> vars(pete) 289 {'_name': 'Peter P', '_age': 10} 290 >>> vars(kate) 291 {'_name': 'Catherine C', '_age': 20} 292 293 294Closing thoughts 295---------------- 296 297A :term:`descriptor` is what we call any object that defines :meth:`__get__`, 298:meth:`__set__`, or :meth:`__delete__`. 299 300Optionally, descriptors can have a :meth:`__set_name__` method. This is only 301used in cases where a descriptor needs to know either the class where it was 302created or the name of class variable it was assigned to. (This method, if 303present, is called even if the class is not a descriptor.) 304 305Descriptors get invoked by the dot operator during attribute lookup. If a 306descriptor is accessed indirectly with ``vars(some_class)[descriptor_name]``, 307the descriptor instance is returned without invoking it. 308 309Descriptors only work when used as class variables. When put in instances, 310they have no effect. 311 312The main motivation for descriptors is to provide a hook allowing objects 313stored in class variables to control what happens during attribute lookup. 314 315Traditionally, the calling class controls what happens during lookup. 316Descriptors invert that relationship and allow the data being looked-up to 317have a say in the matter. 318 319Descriptors are used throughout the language. It is how functions turn into 320bound methods. Common tools like :func:`classmethod`, :func:`staticmethod`, 321:func:`property`, and :func:`functools.cached_property` are all implemented as 322descriptors. 323 324 325Complete Practical Example 326^^^^^^^^^^^^^^^^^^^^^^^^^^ 327 328In this example, we create a practical and powerful tool for locating 329notoriously hard to find data corruption bugs. 330 331 332Validator class 333--------------- 334 335A validator is a descriptor for managed attribute access. Prior to storing 336any data, it verifies that the new value meets various type and range 337restrictions. If those restrictions aren't met, it raises an exception to 338prevent data corruption at its source. 339 340This :class:`Validator` class is both an :term:`abstract base class` and a 341managed attribute descriptor: 342 343.. testcode:: 344 345 from abc import ABC, abstractmethod 346 347 class Validator(ABC): 348 349 def __set_name__(self, owner, name): 350 self.private_name = '_' + name 351 352 def __get__(self, obj, objtype=None): 353 return getattr(obj, self.private_name) 354 355 def __set__(self, obj, value): 356 self.validate(value) 357 setattr(obj, self.private_name, value) 358 359 @abstractmethod 360 def validate(self, value): 361 pass 362 363Custom validators need to inherit from :class:`Validator` and must supply a 364:meth:`validate` method to test various restrictions as needed. 365 366 367Custom validators 368----------------- 369 370Here are three practical data validation utilities: 371 3721) :class:`OneOf` verifies that a value is one of a restricted set of options. 373 3742) :class:`Number` verifies that a value is either an :class:`int` or 375 :class:`float`. Optionally, it verifies that a value is between a given 376 minimum or maximum. 377 3783) :class:`String` verifies that a value is a :class:`str`. Optionally, it 379 validates a given minimum or maximum length. It can validate a 380 user-defined `predicate 381 <https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)>`_ as well. 382 383.. testcode:: 384 385 class OneOf(Validator): 386 387 def __init__(self, *options): 388 self.options = set(options) 389 390 def validate(self, value): 391 if value not in self.options: 392 raise ValueError(f'Expected {value!r} to be one of {self.options!r}') 393 394 class Number(Validator): 395 396 def __init__(self, minvalue=None, maxvalue=None): 397 self.minvalue = minvalue 398 self.maxvalue = maxvalue 399 400 def validate(self, value): 401 if not isinstance(value, (int, float)): 402 raise TypeError(f'Expected {value!r} to be an int or float') 403 if self.minvalue is not None and value < self.minvalue: 404 raise ValueError( 405 f'Expected {value!r} to be at least {self.minvalue!r}' 406 ) 407 if self.maxvalue is not None and value > self.maxvalue: 408 raise ValueError( 409 f'Expected {value!r} to be no more than {self.maxvalue!r}' 410 ) 411 412 class String(Validator): 413 414 def __init__(self, minsize=None, maxsize=None, predicate=None): 415 self.minsize = minsize 416 self.maxsize = maxsize 417 self.predicate = predicate 418 419 def validate(self, value): 420 if not isinstance(value, str): 421 raise TypeError(f'Expected {value!r} to be an str') 422 if self.minsize is not None and len(value) < self.minsize: 423 raise ValueError( 424 f'Expected {value!r} to be no smaller than {self.minsize!r}' 425 ) 426 if self.maxsize is not None and len(value) > self.maxsize: 427 raise ValueError( 428 f'Expected {value!r} to be no bigger than {self.maxsize!r}' 429 ) 430 if self.predicate is not None and not self.predicate(value): 431 raise ValueError( 432 f'Expected {self.predicate} to be true for {value!r}' 433 ) 434 435 436Practical application 437--------------------- 438 439Here's how the data validators can be used in a real class: 440 441.. testcode:: 442 443 class Component: 444 445 name = String(minsize=3, maxsize=10, predicate=str.isupper) 446 kind = OneOf('wood', 'metal', 'plastic') 447 quantity = Number(minvalue=0) 448 449 def __init__(self, name, kind, quantity): 450 self.name = name 451 self.kind = kind 452 self.quantity = quantity 453 454The descriptors prevent invalid instances from being created: 455 456.. doctest:: 457 458 >>> Component('Widget', 'metal', 5) # Blocked: 'Widget' is not all uppercase 459 Traceback (most recent call last): 460 ... 461 ValueError: Expected <method 'isupper' of 'str' objects> to be true for 'Widget' 462 463 >>> Component('WIDGET', 'metle', 5) # Blocked: 'metle' is misspelled 464 Traceback (most recent call last): 465 ... 466 ValueError: Expected 'metle' to be one of {'metal', 'plastic', 'wood'} 467 468 >>> Component('WIDGET', 'metal', -5) # Blocked: -5 is negative 469 Traceback (most recent call last): 470 ... 471 ValueError: Expected -5 to be at least 0 472 >>> Component('WIDGET', 'metal', 'V') # Blocked: 'V' isn't a number 473 Traceback (most recent call last): 474 ... 475 TypeError: Expected 'V' to be an int or float 476 477 >>> c = Component('WIDGET', 'metal', 5) # Allowed: The inputs are valid 478 479 480Technical Tutorial 481^^^^^^^^^^^^^^^^^^ 482 483What follows is a more technical tutorial for the mechanics and details of how 484descriptors work. 485 486 487Abstract 488-------- 489 490Defines descriptors, summarizes the protocol, and shows how descriptors are 491called. Provides an example showing how object relational mappings work. 492 493Learning about descriptors not only provides access to a larger toolset, it 494creates a deeper understanding of how Python works. 495 496 497Definition and introduction 498--------------------------- 499 500In general, a descriptor is an attribute value that has one of the methods in 501the descriptor protocol. Those methods are :meth:`__get__`, :meth:`__set__`, 502and :meth:`__delete__`. If any of those methods are defined for an 503attribute, it is said to be a :term:`descriptor`. 504 505The default behavior for attribute access is to get, set, or delete the 506attribute from an object's dictionary. For instance, ``a.x`` has a lookup chain 507starting with ``a.__dict__['x']``, then ``type(a).__dict__['x']``, and 508continuing through the method resolution order of ``type(a)``. If the 509looked-up value is an object defining one of the descriptor methods, then Python 510may override the default behavior and invoke the descriptor method instead. 511Where this occurs in the precedence chain depends on which descriptor methods 512were defined. 513 514Descriptors are a powerful, general purpose protocol. They are the mechanism 515behind properties, methods, static methods, class methods, and 516:func:`super()`. They are used throughout Python itself. Descriptors 517simplify the underlying C code and offer a flexible set of new tools for 518everyday Python programs. 519 520 521Descriptor protocol 522------------------- 523 524``descr.__get__(self, obj, type=None) -> value`` 525 526``descr.__set__(self, obj, value) -> None`` 527 528``descr.__delete__(self, obj) -> None`` 529 530That is all there is to it. Define any of these methods and an object is 531considered a descriptor and can override default behavior upon being looked up 532as an attribute. 533 534If an object defines :meth:`__set__` or :meth:`__delete__`, it is considered 535a data descriptor. Descriptors that only define :meth:`__get__` are called 536non-data descriptors (they are often used for methods but other uses are 537possible). 538 539Data and non-data descriptors differ in how overrides are calculated with 540respect to entries in an instance's dictionary. If an instance's dictionary 541has an entry with the same name as a data descriptor, the data descriptor 542takes precedence. If an instance's dictionary has an entry with the same 543name as a non-data descriptor, the dictionary entry takes precedence. 544 545To make a read-only data descriptor, define both :meth:`__get__` and 546:meth:`__set__` with the :meth:`__set__` raising an :exc:`AttributeError` when 547called. Defining the :meth:`__set__` method with an exception raising 548placeholder is enough to make it a data descriptor. 549 550 551Overview of descriptor invocation 552--------------------------------- 553 554A descriptor can be called directly with ``desc.__get__(obj)`` or 555``desc.__get__(None, cls)``. 556 557But it is more common for a descriptor to be invoked automatically from 558attribute access. 559 560The expression ``obj.x`` looks up the attribute ``x`` in the chain of 561namespaces for ``obj``. If the search finds a descriptor outside of the 562instance ``__dict__``, its :meth:`__get__` method is invoked according to the 563precedence rules listed below. 564 565The details of invocation depend on whether ``obj`` is an object, class, or 566instance of super. 567 568 569Invocation from an instance 570--------------------------- 571 572Instance lookup scans through a chain of namespaces giving data descriptors 573the highest priority, followed by instance variables, then non-data 574descriptors, then class variables, and lastly :meth:`__getattr__` if it is 575provided. 576 577If a descriptor is found for ``a.x``, then it is invoked with: 578``desc.__get__(a, type(a))``. 579 580The logic for a dotted lookup is in :meth:`object.__getattribute__`. Here is 581a pure Python equivalent: 582 583.. testcode:: 584 585 def object_getattribute(obj, name): 586 "Emulate PyObject_GenericGetAttr() in Objects/object.c" 587 null = object() 588 objtype = type(obj) 589 cls_var = getattr(objtype, name, null) 590 descr_get = getattr(type(cls_var), '__get__', null) 591 if descr_get is not null: 592 if (hasattr(type(cls_var), '__set__') 593 or hasattr(type(cls_var), '__delete__')): 594 return descr_get(cls_var, obj, objtype) # data descriptor 595 if hasattr(obj, '__dict__') and name in vars(obj): 596 return vars(obj)[name] # instance variable 597 if descr_get is not null: 598 return descr_get(cls_var, obj, objtype) # non-data descriptor 599 if cls_var is not null: 600 return cls_var # class variable 601 raise AttributeError(name) 602 603 604.. testcode:: 605 :hide: 606 607 # Test the fidelity of object_getattribute() by comparing it with the 608 # normal object.__getattribute__(). The former will be accessed by 609 # square brackets and the latter by the dot operator. 610 611 class Object: 612 613 def __getitem__(obj, name): 614 try: 615 return object_getattribute(obj, name) 616 except AttributeError: 617 if not hasattr(type(obj), '__getattr__'): 618 raise 619 return type(obj).__getattr__(obj, name) # __getattr__ 620 621 class DualOperator(Object): 622 623 x = 10 624 625 def __init__(self, z): 626 self.z = z 627 628 @property 629 def p2(self): 630 return 2 * self.x 631 632 @property 633 def p3(self): 634 return 3 * self.x 635 636 def m5(self, y): 637 return 5 * y 638 639 def m7(self, y): 640 return 7 * y 641 642 def __getattr__(self, name): 643 return ('getattr_hook', self, name) 644 645 class DualOperatorWithSlots: 646 647 __getitem__ = Object.__getitem__ 648 649 __slots__ = ['z'] 650 651 x = 15 652 653 def __init__(self, z): 654 self.z = z 655 656 @property 657 def p2(self): 658 return 2 * self.x 659 660 def m5(self, y): 661 return 5 * y 662 663 def __getattr__(self, name): 664 return ('getattr_hook', self, name) 665 666 667.. doctest:: 668 :hide: 669 670 >>> a = DualOperator(11) 671 >>> vars(a).update(p3 = '_p3', m7 = '_m7') 672 >>> a.x == a['x'] == 10 673 True 674 >>> a.z == a['z'] == 11 675 True 676 >>> a.p2 == a['p2'] == 20 677 True 678 >>> a.p3 == a['p3'] == 30 679 True 680 >>> a.m5(100) == a.m5(100) == 500 681 True 682 >>> a.m7 == a['m7'] == '_m7' 683 True 684 >>> a.g == a['g'] == ('getattr_hook', a, 'g') 685 True 686 687 >>> b = DualOperatorWithSlots(22) 688 >>> b.x == b['x'] == 15 689 True 690 >>> b.z == b['z'] == 22 691 True 692 >>> b.p2 == b['p2'] == 30 693 True 694 >>> b.m5(200) == b['m5'](200) == 1000 695 True 696 >>> b.g == b['g'] == ('getattr_hook', b, 'g') 697 True 698 699 700Interestingly, attribute lookup doesn't call :meth:`object.__getattribute__` 701directly. Instead, both the dot operator and the :func:`getattr` function 702perform attribute lookup by way of a helper function: 703 704.. testcode:: 705 706 def getattr_hook(obj, name): 707 "Emulate slot_tp_getattr_hook() in Objects/typeobject.c" 708 try: 709 return obj.__getattribute__(name) 710 except AttributeError: 711 if not hasattr(type(obj), '__getattr__'): 712 raise 713 return type(obj).__getattr__(obj, name) # __getattr__ 714 715.. doctest:: 716 :hide: 717 718 719 >>> class ClassWithGetAttr: 720 ... x = 123 721 ... def __getattr__(self, attr): 722 ... return attr.upper() 723 ... 724 >>> cw = ClassWithGetAttr() 725 >>> cw.y = 456 726 >>> getattr_hook(cw, 'x') 727 123 728 >>> getattr_hook(cw, 'y') 729 456 730 >>> getattr_hook(cw, 'z') 731 'Z' 732 733 >>> class ClassWithoutGetAttr: 734 ... x = 123 735 ... 736 >>> cwo = ClassWithoutGetAttr() 737 >>> cwo.y = 456 738 >>> getattr_hook(cwo, 'x') 739 123 740 >>> getattr_hook(cwo, 'y') 741 456 742 >>> getattr_hook(cwo, 'z') 743 Traceback (most recent call last): 744 ... 745 AttributeError: 'ClassWithoutGetAttr' object has no attribute 'z' 746 747So if :meth:`__getattr__` exists, it is called whenever :meth:`__getattribute__` 748raises :exc:`AttributeError` (either directly or in one of the descriptor calls). 749 750Also, if a user calls :meth:`object.__getattribute__` directly, the 751:meth:`__getattr__` hook is bypassed entirely. 752 753 754Invocation from a class 755----------------------- 756 757The logic for a dotted lookup such as ``A.x`` is in 758:meth:`type.__getattribute__`. The steps are similar to those for 759:meth:`object.__getattribute__` but the instance dictionary lookup is replaced 760by a search through the class's :term:`method resolution order`. 761 762If a descriptor is found, it is invoked with ``desc.__get__(None, A)``. 763 764The full C implementation can be found in :c:func:`type_getattro()` and 765:c:func:`_PyType_Lookup()` in :source:`Objects/typeobject.c`. 766 767 768Invocation from super 769--------------------- 770 771The logic for super's dotted lookup is in the :meth:`__getattribute__` method for 772object returned by :class:`super()`. 773 774A dotted lookup such as ``super(A, obj).m`` searches ``obj.__class__.__mro__`` 775for the base class ``B`` immediately following ``A`` and then returns 776``B.__dict__['m'].__get__(obj, A)``. If not a descriptor, ``m`` is returned 777unchanged. 778 779The full C implementation can be found in :c:func:`super_getattro()` in 780:source:`Objects/typeobject.c`. A pure Python equivalent can be found in 781`Guido's Tutorial 782<https://www.python.org/download/releases/2.2.3/descrintro/#cooperation>`_. 783 784 785Summary of invocation logic 786--------------------------- 787 788The mechanism for descriptors is embedded in the :meth:`__getattribute__()` 789methods for :class:`object`, :class:`type`, and :func:`super`. 790 791The important points to remember are: 792 793* Descriptors are invoked by the :meth:`__getattribute__` method. 794 795* Classes inherit this machinery from :class:`object`, :class:`type`, or 796 :func:`super`. 797 798* Overriding :meth:`__getattribute__` prevents automatic descriptor calls 799 because all the descriptor logic is in that method. 800 801* :meth:`object.__getattribute__` and :meth:`type.__getattribute__` make 802 different calls to :meth:`__get__`. The first includes the instance and may 803 include the class. The second puts in ``None`` for the instance and always 804 includes the class. 805 806* Data descriptors always override instance dictionaries. 807 808* Non-data descriptors may be overridden by instance dictionaries. 809 810 811Automatic name notification 812--------------------------- 813 814Sometimes it is desirable for a descriptor to know what class variable name it 815was assigned to. When a new class is created, the :class:`type` metaclass 816scans the dictionary of the new class. If any of the entries are descriptors 817and if they define :meth:`__set_name__`, that method is called with two 818arguments. The *owner* is the class where the descriptor is used, and the 819*name* is the class variable the descriptor was assigned to. 820 821The implementation details are in :c:func:`type_new()` and 822:c:func:`set_names()` in :source:`Objects/typeobject.c`. 823 824Since the update logic is in :meth:`type.__new__`, notifications only take 825place at the time of class creation. If descriptors are added to the class 826afterwards, :meth:`__set_name__` will need to be called manually. 827 828 829ORM example 830----------- 831 832The following code is simplified skeleton showing how data descriptors could 833be used to implement an `object relational mapping 834<https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping>`_. 835 836The essential idea is that the data is stored in an external database. The 837Python instances only hold keys to the database's tables. Descriptors take 838care of lookups or updates: 839 840.. testcode:: 841 842 class Field: 843 844 def __set_name__(self, owner, name): 845 self.fetch = f'SELECT {name} FROM {owner.table} WHERE {owner.key}=?;' 846 self.store = f'UPDATE {owner.table} SET {name}=? WHERE {owner.key}=?;' 847 848 def __get__(self, obj, objtype=None): 849 return conn.execute(self.fetch, [obj.key]).fetchone()[0] 850 851 def __set__(self, obj, value): 852 conn.execute(self.store, [value, obj.key]) 853 conn.commit() 854 855We can use the :class:`Field` class to define `models 856<https://en.wikipedia.org/wiki/Database_model>`_ that describe the schema for 857each table in a database: 858 859.. testcode:: 860 861 class Movie: 862 table = 'Movies' # Table name 863 key = 'title' # Primary key 864 director = Field() 865 year = Field() 866 867 def __init__(self, key): 868 self.key = key 869 870 class Song: 871 table = 'Music' 872 key = 'title' 873 artist = Field() 874 year = Field() 875 genre = Field() 876 877 def __init__(self, key): 878 self.key = key 879 880To use the models, first connect to the database:: 881 882 >>> import sqlite3 883 >>> conn = sqlite3.connect('entertainment.db') 884 885An interactive session shows how data is retrieved from the database and how 886it can be updated: 887 888.. testsetup:: 889 890 song_data = [ 891 ('Country Roads', 'John Denver', 1972), 892 ('Me and Bobby McGee', 'Janice Joplin', 1971), 893 ('Coal Miners Daughter', 'Loretta Lynn', 1970), 894 ] 895 896 movie_data = [ 897 ('Star Wars', 'George Lucas', 1977), 898 ('Jaws', 'Steven Spielberg', 1975), 899 ('Aliens', 'James Cameron', 1986), 900 ] 901 902 import sqlite3 903 904 conn = sqlite3.connect(':memory:') 905 conn.execute('CREATE TABLE Music (title text, artist text, year integer);') 906 conn.execute('CREATE INDEX MusicNdx ON Music (title);') 907 conn.executemany('INSERT INTO Music VALUES (?, ?, ?);', song_data) 908 conn.execute('CREATE TABLE Movies (title text, director text, year integer);') 909 conn.execute('CREATE INDEX MovieNdx ON Music (title);') 910 conn.executemany('INSERT INTO Movies VALUES (?, ?, ?);', movie_data) 911 conn.commit() 912 913.. doctest:: 914 915 >>> Movie('Star Wars').director 916 'George Lucas' 917 >>> jaws = Movie('Jaws') 918 >>> f'Released in {jaws.year} by {jaws.director}' 919 'Released in 1975 by Steven Spielberg' 920 921 >>> Song('Country Roads').artist 922 'John Denver' 923 924 >>> Movie('Star Wars').director = 'J.J. Abrams' 925 >>> Movie('Star Wars').director 926 'J.J. Abrams' 927 928 929Pure Python Equivalents 930^^^^^^^^^^^^^^^^^^^^^^^ 931 932The descriptor protocol is simple and offers exciting possibilities. Several 933use cases are so common that they have been prepackaged into built-in tools. 934Properties, bound methods, static methods, class methods, and \_\_slots\_\_ are 935all based on the descriptor protocol. 936 937 938Properties 939---------- 940 941Calling :func:`property` is a succinct way of building a data descriptor that 942triggers a function call upon access to an attribute. Its signature is:: 943 944 property(fget=None, fset=None, fdel=None, doc=None) -> property 945 946The documentation shows a typical use to define a managed attribute ``x``: 947 948.. testcode:: 949 950 class C: 951 def getx(self): return self.__x 952 def setx(self, value): self.__x = value 953 def delx(self): del self.__x 954 x = property(getx, setx, delx, "I'm the 'x' property.") 955 956.. doctest:: 957 :hide: 958 959 >>> C.x.__doc__ 960 "I'm the 'x' property." 961 >>> c.x = 2.71828 962 >>> c.x 963 2.71828 964 >>> del c.x 965 >>> c.x 966 Traceback (most recent call last): 967 ... 968 AttributeError: 'C' object has no attribute '_C__x' 969 970To see how :func:`property` is implemented in terms of the descriptor protocol, 971here is a pure Python equivalent: 972 973.. testcode:: 974 975 class Property: 976 "Emulate PyProperty_Type() in Objects/descrobject.c" 977 978 def __init__(self, fget=None, fset=None, fdel=None, doc=None): 979 self.fget = fget 980 self.fset = fset 981 self.fdel = fdel 982 if doc is None and fget is not None: 983 doc = fget.__doc__ 984 self.__doc__ = doc 985 self._name = '' 986 987 def __set_name__(self, owner, name): 988 self._name = name 989 990 def __get__(self, obj, objtype=None): 991 if obj is None: 992 return self 993 if self.fget is None: 994 raise AttributeError(f'unreadable attribute {self._name}') 995 return self.fget(obj) 996 997 def __set__(self, obj, value): 998 if self.fset is None: 999 raise AttributeError(f"can't set attribute {self._name}") 1000 self.fset(obj, value) 1001 1002 def __delete__(self, obj): 1003 if self.fdel is None: 1004 raise AttributeError(f"can't delete attribute {self._name}") 1005 self.fdel(obj) 1006 1007 def getter(self, fget): 1008 prop = type(self)(fget, self.fset, self.fdel, self.__doc__) 1009 prop._name = self._name 1010 return prop 1011 1012 def setter(self, fset): 1013 prop = type(self)(self.fget, fset, self.fdel, self.__doc__) 1014 prop._name = self._name 1015 return prop 1016 1017 def deleter(self, fdel): 1018 prop = type(self)(self.fget, self.fset, fdel, self.__doc__) 1019 prop._name = self._name 1020 return prop 1021 1022.. testcode:: 1023 :hide: 1024 1025 # Verify the Property() emulation 1026 1027 class CC: 1028 def getx(self): 1029 return self.__x 1030 def setx(self, value): 1031 self.__x = value 1032 def delx(self): 1033 del self.__x 1034 x = Property(getx, setx, delx, "I'm the 'x' property.") 1035 1036 # Now do it again but use the decorator style 1037 1038 class CCC: 1039 @Property 1040 def x(self): 1041 return self.__x 1042 @x.setter 1043 def x(self, value): 1044 self.__x = value 1045 @x.deleter 1046 def x(self): 1047 del self.__x 1048 1049 1050.. doctest:: 1051 :hide: 1052 1053 >>> cc = CC() 1054 >>> hasattr(cc, 'x') 1055 False 1056 >>> cc.x = 33 1057 >>> cc.x 1058 33 1059 >>> del cc.x 1060 >>> hasattr(cc, 'x') 1061 False 1062 1063 >>> ccc = CCC() 1064 >>> hasattr(ccc, 'x') 1065 False 1066 >>> ccc.x = 333 1067 >>> ccc.x == 333 1068 True 1069 >>> del ccc.x 1070 >>> hasattr(ccc, 'x') 1071 False 1072 1073The :func:`property` builtin helps whenever a user interface has granted 1074attribute access and then subsequent changes require the intervention of a 1075method. 1076 1077For instance, a spreadsheet class may grant access to a cell value through 1078``Cell('b10').value``. Subsequent improvements to the program require the cell 1079to be recalculated on every access; however, the programmer does not want to 1080affect existing client code accessing the attribute directly. The solution is 1081to wrap access to the value attribute in a property data descriptor: 1082 1083.. testcode:: 1084 1085 class Cell: 1086 ... 1087 1088 @property 1089 def value(self): 1090 "Recalculate the cell before returning value" 1091 self.recalc() 1092 return self._value 1093 1094Either the built-in :func:`property` or our :func:`Property` equivalent would 1095work in this example. 1096 1097 1098Functions and methods 1099--------------------- 1100 1101Python's object oriented features are built upon a function based environment. 1102Using non-data descriptors, the two are merged seamlessly. 1103 1104Functions stored in class dictionaries get turned into methods when invoked. 1105Methods only differ from regular functions in that the object instance is 1106prepended to the other arguments. By convention, the instance is called 1107*self* but could be called *this* or any other variable name. 1108 1109Methods can be created manually with :class:`types.MethodType` which is 1110roughly equivalent to: 1111 1112.. testcode:: 1113 1114 class MethodType: 1115 "Emulate PyMethod_Type in Objects/classobject.c" 1116 1117 def __init__(self, func, obj): 1118 self.__func__ = func 1119 self.__self__ = obj 1120 1121 def __call__(self, *args, **kwargs): 1122 func = self.__func__ 1123 obj = self.__self__ 1124 return func(obj, *args, **kwargs) 1125 1126To support automatic creation of methods, functions include the 1127:meth:`__get__` method for binding methods during attribute access. This 1128means that functions are non-data descriptors that return bound methods 1129during dotted lookup from an instance. Here's how it works: 1130 1131.. testcode:: 1132 1133 class Function: 1134 ... 1135 1136 def __get__(self, obj, objtype=None): 1137 "Simulate func_descr_get() in Objects/funcobject.c" 1138 if obj is None: 1139 return self 1140 return MethodType(self, obj) 1141 1142Running the following class in the interpreter shows how the function 1143descriptor works in practice: 1144 1145.. testcode:: 1146 1147 class D: 1148 def f(self, x): 1149 return x 1150 1151The function has a :term:`qualified name` attribute to support introspection: 1152 1153.. doctest:: 1154 1155 >>> D.f.__qualname__ 1156 'D.f' 1157 1158Accessing the function through the class dictionary does not invoke 1159:meth:`__get__`. Instead, it just returns the underlying function object:: 1160 1161 >>> D.__dict__['f'] 1162 <function D.f at 0x00C45070> 1163 1164Dotted access from a class calls :meth:`__get__` which just returns the 1165underlying function unchanged:: 1166 1167 >>> D.f 1168 <function D.f at 0x00C45070> 1169 1170The interesting behavior occurs during dotted access from an instance. The 1171dotted lookup calls :meth:`__get__` which returns a bound method object:: 1172 1173 >>> d = D() 1174 >>> d.f 1175 <bound method D.f of <__main__.D object at 0x00B18C90>> 1176 1177Internally, the bound method stores the underlying function and the bound 1178instance:: 1179 1180 >>> d.f.__func__ 1181 <function D.f at 0x00C45070> 1182 1183 >>> d.f.__self__ 1184 <__main__.D object at 0x1012e1f98> 1185 1186If you have ever wondered where *self* comes from in regular methods or where 1187*cls* comes from in class methods, this is it! 1188 1189 1190Kinds of methods 1191---------------- 1192 1193Non-data descriptors provide a simple mechanism for variations on the usual 1194patterns of binding functions into methods. 1195 1196To recap, functions have a :meth:`__get__` method so that they can be converted 1197to a method when accessed as attributes. The non-data descriptor transforms an 1198``obj.f(*args)`` call into ``f(obj, *args)``. Calling ``cls.f(*args)`` 1199becomes ``f(*args)``. 1200 1201This chart summarizes the binding and its two most useful variants: 1202 1203 +-----------------+----------------------+------------------+ 1204 | Transformation | Called from an | Called from a | 1205 | | object | class | 1206 +=================+======================+==================+ 1207 | function | f(obj, \*args) | f(\*args) | 1208 +-----------------+----------------------+------------------+ 1209 | staticmethod | f(\*args) | f(\*args) | 1210 +-----------------+----------------------+------------------+ 1211 | classmethod | f(type(obj), \*args) | f(cls, \*args) | 1212 +-----------------+----------------------+------------------+ 1213 1214 1215Static methods 1216-------------- 1217 1218Static methods return the underlying function without changes. Calling either 1219``c.f`` or ``C.f`` is the equivalent of a direct lookup into 1220``object.__getattribute__(c, "f")`` or ``object.__getattribute__(C, "f")``. As a 1221result, the function becomes identically accessible from either an object or a 1222class. 1223 1224Good candidates for static methods are methods that do not reference the 1225``self`` variable. 1226 1227For instance, a statistics package may include a container class for 1228experimental data. The class provides normal methods for computing the average, 1229mean, median, and other descriptive statistics that depend on the data. However, 1230there may be useful functions which are conceptually related but do not depend 1231on the data. For instance, ``erf(x)`` is handy conversion routine that comes up 1232in statistical work but does not directly depend on a particular dataset. 1233It can be called either from an object or the class: ``s.erf(1.5) --> .9332`` or 1234``Sample.erf(1.5) --> .9332``. 1235 1236Since static methods return the underlying function with no changes, the 1237example calls are unexciting: 1238 1239.. testcode:: 1240 1241 class E: 1242 @staticmethod 1243 def f(x): 1244 return x * 10 1245 1246.. doctest:: 1247 1248 >>> E.f(3) 1249 30 1250 >>> E().f(3) 1251 30 1252 1253Using the non-data descriptor protocol, a pure Python version of 1254:func:`staticmethod` would look like this: 1255 1256.. testcode:: 1257 1258 class StaticMethod: 1259 "Emulate PyStaticMethod_Type() in Objects/funcobject.c" 1260 1261 def __init__(self, f): 1262 self.f = f 1263 1264 def __get__(self, obj, objtype=None): 1265 return self.f 1266 1267 def __call__(self, *args, **kwds): 1268 return self.f(*args, **kwds) 1269 1270.. testcode:: 1271 :hide: 1272 1273 class E_sim: 1274 @StaticMethod 1275 def f(x): 1276 return x * 10 1277 1278 wrapped_ord = StaticMethod(ord) 1279 1280.. doctest:: 1281 :hide: 1282 1283 >>> E_sim.f(3) 1284 30 1285 >>> E_sim().f(3) 1286 30 1287 >>> wrapped_ord('A') 1288 65 1289 1290 1291Class methods 1292------------- 1293 1294Unlike static methods, class methods prepend the class reference to the 1295argument list before calling the function. This format is the same 1296for whether the caller is an object or a class: 1297 1298.. testcode:: 1299 1300 class F: 1301 @classmethod 1302 def f(cls, x): 1303 return cls.__name__, x 1304 1305.. doctest:: 1306 1307 >>> F.f(3) 1308 ('F', 3) 1309 >>> F().f(3) 1310 ('F', 3) 1311 1312This behavior is useful whenever the method only needs to have a class 1313reference and does not rely on data stored in a specific instance. One use for 1314class methods is to create alternate class constructors. For example, the 1315classmethod :func:`dict.fromkeys` creates a new dictionary from a list of 1316keys. The pure Python equivalent is: 1317 1318.. testcode:: 1319 1320 class Dict(dict): 1321 @classmethod 1322 def fromkeys(cls, iterable, value=None): 1323 "Emulate dict_fromkeys() in Objects/dictobject.c" 1324 d = cls() 1325 for key in iterable: 1326 d[key] = value 1327 return d 1328 1329Now a new dictionary of unique keys can be constructed like this: 1330 1331.. doctest:: 1332 1333 >>> d = Dict.fromkeys('abracadabra') 1334 >>> type(d) is Dict 1335 True 1336 >>> d 1337 {'a': None, 'b': None, 'r': None, 'c': None, 'd': None} 1338 1339Using the non-data descriptor protocol, a pure Python version of 1340:func:`classmethod` would look like this: 1341 1342.. testcode:: 1343 1344 class ClassMethod: 1345 "Emulate PyClassMethod_Type() in Objects/funcobject.c" 1346 1347 def __init__(self, f): 1348 self.f = f 1349 1350 def __get__(self, obj, cls=None): 1351 if cls is None: 1352 cls = type(obj) 1353 if hasattr(type(self.f), '__get__'): 1354 return self.f.__get__(cls, cls) 1355 return MethodType(self.f, cls) 1356 1357.. testcode:: 1358 :hide: 1359 1360 # Verify the emulation works 1361 class T: 1362 @ClassMethod 1363 def cm(cls, x, y): 1364 return (cls, x, y) 1365 1366 @ClassMethod 1367 @property 1368 def __doc__(cls): 1369 return f'A doc for {cls.__name__!r}' 1370 1371 1372.. doctest:: 1373 :hide: 1374 1375 >>> T.cm(11, 22) 1376 (<class 'T'>, 11, 22) 1377 1378 # Also call it from an instance 1379 >>> t = T() 1380 >>> t.cm(11, 22) 1381 (<class 'T'>, 11, 22) 1382 1383 # Check the alternate path for chained descriptors 1384 >>> T.__doc__ 1385 "A doc for 'T'" 1386 1387 1388The code path for ``hasattr(type(self.f), '__get__')`` was added in 1389Python 3.9 and makes it possible for :func:`classmethod` to support 1390chained decorators. For example, a classmethod and property could be 1391chained together: 1392 1393.. testcode:: 1394 1395 class G: 1396 @classmethod 1397 @property 1398 def __doc__(cls): 1399 return f'A doc for {cls.__name__!r}' 1400 1401.. doctest:: 1402 1403 >>> G.__doc__ 1404 "A doc for 'G'" 1405 1406 1407Member objects and __slots__ 1408---------------------------- 1409 1410When a class defines ``__slots__``, it replaces instance dictionaries with a 1411fixed-length array of slot values. From a user point of view that has 1412several effects: 1413 14141. Provides immediate detection of bugs due to misspelled attribute 1415assignments. Only attribute names specified in ``__slots__`` are allowed: 1416 1417.. testcode:: 1418 1419 class Vehicle: 1420 __slots__ = ('id_number', 'make', 'model') 1421 1422.. doctest:: 1423 1424 >>> auto = Vehicle() 1425 >>> auto.id_nubmer = 'VYE483814LQEX' 1426 Traceback (most recent call last): 1427 ... 1428 AttributeError: 'Vehicle' object has no attribute 'id_nubmer' 1429 14302. Helps create immutable objects where descriptors manage access to private 1431attributes stored in ``__slots__``: 1432 1433.. testcode:: 1434 1435 class Immutable: 1436 1437 __slots__ = ('_dept', '_name') # Replace the instance dictionary 1438 1439 def __init__(self, dept, name): 1440 self._dept = dept # Store to private attribute 1441 self._name = name # Store to private attribute 1442 1443 @property # Read-only descriptor 1444 def dept(self): 1445 return self._dept 1446 1447 @property 1448 def name(self): # Read-only descriptor 1449 return self._name 1450 1451.. doctest:: 1452 1453 >>> mark = Immutable('Botany', 'Mark Watney') 1454 >>> mark.dept 1455 'Botany' 1456 >>> mark.dept = 'Space Pirate' 1457 Traceback (most recent call last): 1458 ... 1459 AttributeError: can't set attribute 1460 >>> mark.location = 'Mars' 1461 Traceback (most recent call last): 1462 ... 1463 AttributeError: 'Immutable' object has no attribute 'location' 1464 14653. Saves memory. On a 64-bit Linux build, an instance with two attributes 1466takes 48 bytes with ``__slots__`` and 152 bytes without. This `flyweight 1467design pattern <https://en.wikipedia.org/wiki/Flyweight_pattern>`_ likely only 1468matters when a large number of instances are going to be created. 1469 14704. Improves speed. Reading instance variables is 35% faster with 1471``__slots__`` (as measured with Python 3.10 on an Apple M1 processor). 1472 14735. Blocks tools like :func:`functools.cached_property` which require an 1474instance dictionary to function correctly: 1475 1476.. testcode:: 1477 1478 from functools import cached_property 1479 1480 class CP: 1481 __slots__ = () # Eliminates the instance dict 1482 1483 @cached_property # Requires an instance dict 1484 def pi(self): 1485 return 4 * sum((-1.0)**n / (2.0*n + 1.0) 1486 for n in reversed(range(100_000))) 1487 1488.. doctest:: 1489 1490 >>> CP().pi 1491 Traceback (most recent call last): 1492 ... 1493 TypeError: No '__dict__' attribute on 'CP' instance to cache 'pi' property. 1494 1495It is not possible to create an exact drop-in pure Python version of 1496``__slots__`` because it requires direct access to C structures and control 1497over object memory allocation. However, we can build a mostly faithful 1498simulation where the actual C structure for slots is emulated by a private 1499``_slotvalues`` list. Reads and writes to that private structure are managed 1500by member descriptors: 1501 1502.. testcode:: 1503 1504 null = object() 1505 1506 class Member: 1507 1508 def __init__(self, name, clsname, offset): 1509 'Emulate PyMemberDef in Include/structmember.h' 1510 # Also see descr_new() in Objects/descrobject.c 1511 self.name = name 1512 self.clsname = clsname 1513 self.offset = offset 1514 1515 def __get__(self, obj, objtype=None): 1516 'Emulate member_get() in Objects/descrobject.c' 1517 # Also see PyMember_GetOne() in Python/structmember.c 1518 value = obj._slotvalues[self.offset] 1519 if value is null: 1520 raise AttributeError(self.name) 1521 return value 1522 1523 def __set__(self, obj, value): 1524 'Emulate member_set() in Objects/descrobject.c' 1525 obj._slotvalues[self.offset] = value 1526 1527 def __delete__(self, obj): 1528 'Emulate member_delete() in Objects/descrobject.c' 1529 value = obj._slotvalues[self.offset] 1530 if value is null: 1531 raise AttributeError(self.name) 1532 obj._slotvalues[self.offset] = null 1533 1534 def __repr__(self): 1535 'Emulate member_repr() in Objects/descrobject.c' 1536 return f'<Member {self.name!r} of {self.clsname!r}>' 1537 1538The :meth:`type.__new__` method takes care of adding member objects to class 1539variables: 1540 1541.. testcode:: 1542 1543 class Type(type): 1544 'Simulate how the type metaclass adds member objects for slots' 1545 1546 def __new__(mcls, clsname, bases, mapping): 1547 'Emuluate type_new() in Objects/typeobject.c' 1548 # type_new() calls PyTypeReady() which calls add_methods() 1549 slot_names = mapping.get('slot_names', []) 1550 for offset, name in enumerate(slot_names): 1551 mapping[name] = Member(name, clsname, offset) 1552 return type.__new__(mcls, clsname, bases, mapping) 1553 1554The :meth:`object.__new__` method takes care of creating instances that have 1555slots instead of an instance dictionary. Here is a rough simulation in pure 1556Python: 1557 1558.. testcode:: 1559 1560 class Object: 1561 'Simulate how object.__new__() allocates memory for __slots__' 1562 1563 def __new__(cls, *args): 1564 'Emulate object_new() in Objects/typeobject.c' 1565 inst = super().__new__(cls) 1566 if hasattr(cls, 'slot_names'): 1567 empty_slots = [null] * len(cls.slot_names) 1568 object.__setattr__(inst, '_slotvalues', empty_slots) 1569 return inst 1570 1571 def __setattr__(self, name, value): 1572 'Emulate _PyObject_GenericSetAttrWithDict() Objects/object.c' 1573 cls = type(self) 1574 if hasattr(cls, 'slot_names') and name not in cls.slot_names: 1575 raise AttributeError( 1576 f'{type(self).__name__!r} object has no attribute {name!r}' 1577 ) 1578 super().__setattr__(name, value) 1579 1580 def __delattr__(self, name): 1581 'Emulate _PyObject_GenericSetAttrWithDict() Objects/object.c' 1582 cls = type(self) 1583 if hasattr(cls, 'slot_names') and name not in cls.slot_names: 1584 raise AttributeError( 1585 f'{type(self).__name__!r} object has no attribute {name!r}' 1586 ) 1587 super().__delattr__(name) 1588 1589To use the simulation in a real class, just inherit from :class:`Object` and 1590set the :term:`metaclass` to :class:`Type`: 1591 1592.. testcode:: 1593 1594 class H(Object, metaclass=Type): 1595 'Instance variables stored in slots' 1596 1597 slot_names = ['x', 'y'] 1598 1599 def __init__(self, x, y): 1600 self.x = x 1601 self.y = y 1602 1603At this point, the metaclass has loaded member objects for *x* and *y*:: 1604 1605 >>> from pprint import pp 1606 >>> pp(dict(vars(H))) 1607 {'__module__': '__main__', 1608 '__doc__': 'Instance variables stored in slots', 1609 'slot_names': ['x', 'y'], 1610 '__init__': <function H.__init__ at 0x7fb5d302f9d0>, 1611 'x': <Member 'x' of 'H'>, 1612 'y': <Member 'y' of 'H'>} 1613 1614.. doctest:: 1615 :hide: 1616 1617 # We test this separately because the preceding section is not 1618 # doctestable due to the hex memory address for the __init__ function 1619 >>> isinstance(vars(H)['x'], Member) 1620 True 1621 >>> isinstance(vars(H)['y'], Member) 1622 True 1623 1624When instances are created, they have a ``slot_values`` list where the 1625attributes are stored: 1626 1627.. doctest:: 1628 1629 >>> h = H(10, 20) 1630 >>> vars(h) 1631 {'_slotvalues': [10, 20]} 1632 >>> h.x = 55 1633 >>> vars(h) 1634 {'_slotvalues': [55, 20]} 1635 1636Misspelled or unassigned attributes will raise an exception: 1637 1638.. doctest:: 1639 1640 >>> h.xz 1641 Traceback (most recent call last): 1642 ... 1643 AttributeError: 'H' object has no attribute 'xz' 1644 1645.. doctest:: 1646 :hide: 1647 1648 # Examples for deleted attributes are not shown because this section 1649 # is already a bit lengthy. We still test that code here. 1650 >>> del h.x 1651 >>> hasattr(h, 'x') 1652 False 1653 1654 # Also test the code for uninitialized slots 1655 >>> class HU(Object, metaclass=Type): 1656 ... slot_names = ['x', 'y'] 1657 ... 1658 >>> hu = HU() 1659 >>> hasattr(hu, 'x') 1660 False 1661 >>> hasattr(hu, 'y') 1662 False 1663