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 that always returns the constant ``10`` 46from its :meth:`__get__` method: 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 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 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 >>> open('games/newfile').close() # Add a fourth file to the directory 119 >>> g.size # File count is automatically updated 120 4 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 >>> 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 298Optionally, descriptors can have a :meth:`__set_name__` method. This is only 299used in cases where a descriptor needs to know either the class where it was 300created or the name of class variable it was assigned to. (This method, if 301present, is called even if the class is not a descriptor.) 302 303Descriptors get invoked by the dot "operator" during attribute lookup. If a 304descriptor 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 311stored in class variables to control what happens during attribute lookup. 312 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 336prevent data corruption at its source. 337 338This :class:`Validator` class is both an :term:`abstract base class` and a 339managed attribute descriptor: 340 341.. testcode:: 342 343 from abc import ABC, abstractmethod 344 345 class Validator(ABC): 346 347 def __set_name__(self, owner, name): 348 self.private_name = '_' + name 349 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 361Custom validators need to inherit from :class:`Validator` and must supply a 362: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 377 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. 380 381.. testcode:: 382 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 434Practical application 435--------------------- 436 437Here's how the data validators can be used in a real class: 438 439.. testcode:: 440 441 class Component: 442 443 name = String(minsize=3, maxsize=10, predicate=str.isupper) 444 kind = OneOf('wood', 'metal', 'plastic') 445 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 452The descriptors prevent invalid instances from being created: 453 454.. doctest:: 455 456 >>> 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 476 477 478Technical Tutorial 479^^^^^^^^^^^^^^^^^^ 480 481What follows is a more technical tutorial for the mechanics and details of how 482descriptors work. 483 484 485Abstract 486-------- 487 488Defines descriptors, summarizes the protocol, and shows how descriptors are 489called. Provides an example showing how object relational mappings work. 490 491Learning about descriptors not only provides access to a larger toolset, it 492creates a deeper understanding of how Python works. 493 494 495Definition and introduction 496--------------------------- 497 498In 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 501attribute, it is said to be a :term:`descriptor`. 502 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 506continuing through the method resolution order of ``type(a)``. If the 507looked-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 510were defined. 511 512Descriptors are a powerful, general purpose protocol. They are the mechanism 513behind 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. 517 518 519Descriptor protocol 520------------------- 521 522``descr.__get__(self, obj, type=None) -> value`` 523 524``descr.__set__(self, obj, value) -> None`` 525 526``descr.__delete__(self, obj) -> None`` 527 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 532If an object defines :meth:`__set__` or :meth:`__delete__`, it is considered 533a data descriptor. Descriptors that only define :meth:`__get__` are called 534non-data descriptors (they are often used for methods but other uses are 535possible). 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 549Overview of descriptor invocation 550--------------------------------- 551 552A descriptor can be called directly with ``desc.__get__(obj)`` or 553``desc.__get__(None, cls)``. 554 555But it is more common for a descriptor to be invoked automatically from 556attribute access. 557 558The expression ``obj.x`` looks up the attribute ``x`` in the chain of 559namespaces 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. 562 563The details of invocation depend on whether ``obj`` is an object, class, or 564instance of super. 565 566 567Invocation from an instance 568--------------------------- 569 570Instance 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. 574 575If a descriptor is found for ``a.x``, then it is invoked with: 576``desc.__get__(a, type(a))``. 577 578The logic for a dotted lookup is in :meth:`object.__getattribute__`. Here is 579a pure Python equivalent: 580 581.. testcode:: 582 583 def object_getattribute(obj, name): 584 "Emulate PyObject_GenericGetAttr() in Objects/object.c" 585 null = object() 586 objtype = type(obj) 587 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 599 raise AttributeError(name) 600 601 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 698Interestingly, attribute lookup doesn't call :meth:`object.__getattribute__` 699directly. Instead, both the dot operator and the :func:`getattr` function 700perform attribute lookup by way of a helper function: 701 702.. testcode:: 703 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. 718 719 720Invocation from a class 721----------------------- 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 734Invocation from super 735--------------------- 736 737The logic for super's dotted lookup is in the :meth:`__getattribute__` method for 738object returned by :class:`super()`. 739 740A dotted lookup such as ``super(A, obj).m`` searches ``obj.__class__.__mro__`` 741for the base class ``B`` immediately following ``A`` and then returns 742``B.__dict__['m'].__get__(obj, A)``. If not a descriptor, ``m`` is returned 743unchanged. 744 745The full C implementation can be found in :c:func:`super_getattro()` in 746:source:`Objects/typeobject.c`. A pure Python equivalent can be found in 747`Guido's Tutorial 748<https://www.python.org/download/releases/2.2.3/descrintro/#cooperation>`_. 749 750 751Summary of invocation logic 752--------------------------- 753 754The mechanism for descriptors is embedded in the :meth:`__getattribute__()` 755methods for :class:`object`, :class:`type`, and :func:`super`. 756 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. 775 776 777Automatic name notification 778--------------------------- 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 784arguments. The *owner* is the class where the descriptor is used, and the 785*name* is the class variable the descriptor was assigned to. 786 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 795ORM example 796----------- 797 798The 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>`_. 801 802The 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 804care of lookups or updates: 805 806.. testcode:: 807 808 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}=?;' 813 814 def __get__(self, obj, objtype=None): 815 return conn.execute(self.fetch, [obj.key]).fetchone()[0] 816 817 def __set__(self, obj, value): 818 conn.execute(self.store, [value, obj.key]) 819 conn.commit() 820 821We 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:: 826 827 class Movie: 828 table = 'Movies' # Table name 829 key = 'title' # Primary key 830 director = Field() 831 year = Field() 832 833 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 846To use the models, first connect to the database:: 847 848 >>> import sqlite3 849 >>> conn = sqlite3.connect('entertainment.db') 850 851An 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 881 >>> 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 894 895Pure Python Equivalents 896^^^^^^^^^^^^^^^^^^^^^^^ 897 898The descriptor protocol is simple and offers exciting possibilities. Several 899use cases are so common that they have been prepackaged into built-in tools. 900Properties, bound methods, static methods, class methods, and \_\_slots\_\_ are 901all based on the descriptor protocol. 902 903 904Properties 905---------- 906 907Calling :func:`property` is a succinct way of building a data descriptor that 908triggers a function call upon access to an attribute. Its signature is:: 909 910 property(fget=None, fset=None, fdel=None, doc=None) -> property 911 912The documentation shows a typical use to define a managed attribute ``x``: 913 914.. testcode:: 915 916 class C: 917 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, 923here is a pure Python equivalent: 924 925.. testcode:: 926 927 class Property: 928 "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 934 if doc is None and fget is not None: 935 doc = fget.__doc__ 936 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: 942 raise AttributeError("unreadable attribute") 943 return self.fget(obj) 944 945 def __set__(self, obj, value): 946 if self.fset is None: 947 raise AttributeError("can't set attribute") 948 self.fset(obj, value) 949 950 def __delete__(self, obj): 951 if self.fdel is None: 952 raise AttributeError("can't delete attribute") 953 self.fdel(obj) 954 955 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 964.. 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 1015The :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 1023to wrap access to the value attribute in a property data descriptor: 1024 1025.. testcode:: 1026 1027 class Cell: 1028 ... 1029 1030 @property 1031 def value(self): 1032 "Recalculate the cell before returning value" 1033 self.recalc() 1034 return self._value 1035 1036Either the built-in :func:`property` or our :func:`Property` equivalent would 1037work in this example. 1038 1039 1040Functions and methods 1041--------------------- 1042 1043Python's object oriented features are built upon a function based environment. 1044Using non-data descriptors, the two are merged seamlessly. 1045 1046Functions 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. 1050 1051Methods can be created manually with :class:`types.MethodType` which is 1052roughly equivalent to: 1053 1054.. testcode:: 1055 1056 class MethodType: 1057 "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 1070means that functions are non-data descriptors that return bound methods 1071during dotted lookup from an instance. Here's how it works: 1072 1073.. testcode:: 1074 1075 class Function: 1076 ... 1077 1078 def __get__(self, obj, objtype=None): 1079 "Simulate func_descr_get() in Objects/funcobject.c" 1080 if obj is None: 1081 return self 1082 return MethodType(self, obj) 1083 1084Running the following class in the interpreter shows how the function 1085descriptor works in practice: 1086 1087.. testcode:: 1088 1089 class D: 1090 def f(self, x): 1091 return x 1092 1093The function has a :term:`qualified name` attribute to support introspection: 1094 1095.. doctest:: 1096 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:: 1102 1103 >>> D.__dict__['f'] 1104 <function D.f at 0x00C45070> 1105 1106Dotted access from a class calls :meth:`__get__` which just returns the 1107underlying function unchanged:: 1108 1109 >>> D.f 1110 <function D.f at 0x00C45070> 1111 1112The interesting behavior occurs during dotted access from an instance. The 1113dotted lookup calls :meth:`__get__` which returns a bound method object:: 1114 1115 >>> d = D() 1116 >>> d.f 1117 <bound method D.f of <__main__.D object at 0x00B18C90>> 1118 1119Internally, the bound method stores the underlying function and the bound 1120instance:: 1121 1122 >>> d.f.__func__ 1123 <function D.f at 0x00C45070> 1124 1125 >>> d.f.__self__ 1126 <__main__.D object at 0x1012e1f98> 1127 1128If you have ever wondered where *self* comes from in regular methods or where 1129*cls* comes from in class methods, this is it! 1130 1131 1132Static methods 1133-------------- 1134 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 1139to a method when accessed as attributes. The non-data descriptor transforms an 1140``obj.f(*args)`` call into ``f(obj, *args)``. Calling ``cls.f(*args)`` 1141becomes ``f(*args)``. 1142 1143This chart summarizes the binding and its two most useful variants: 1144 1145 +-----------------+----------------------+------------------+ 1146 | Transformation | Called from an | Called from a | 1147 | | object | class | 1148 +=================+======================+==================+ 1149 | function | f(obj, \*args) | f(\*args) | 1150 +-----------------+----------------------+------------------+ 1151 | staticmethod | f(\*args) | f(\*args) | 1152 +-----------------+----------------------+------------------+ 1153 | classmethod | f(type(obj), \*args) | f(cls, \*args) | 1154 +-----------------+----------------------+------------------+ 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 1174Since static methods return the underlying function with no changes, the 1175example calls are unexciting: 1176 1177.. testcode:: 1178 1179 class E: 1180 @staticmethod 1181 def f(x): 1182 print(x) 1183 1184.. doctest:: 1185 1186 >>> E.f(3) 1187 3 1188 >>> E().f(3) 1189 3 1190 1191Using the non-data descriptor protocol, a pure Python version of 1192:func:`staticmethod` would look like this: 1193 1194.. doctest:: 1195 1196 class StaticMethod: 1197 "Emulate PyStaticMethod_Type() in Objects/funcobject.c" 1198 1199 def __init__(self, f): 1200 self.f = f 1201 1202 def __get__(self, obj, objtype=None): 1203 return self.f 1204 1205 1206Class methods 1207------------- 1208 1209Unlike static methods, class methods prepend the class reference to the 1210argument list before calling the function. This format is the same 1211for whether the caller is an object or a class: 1212 1213.. testcode:: 1214 1215 class F: 1216 @classmethod 1217 def f(cls, x): 1218 return cls.__name__, x 1219 1220.. doctest:: 1221 1222 >>> F.f(3) 1223 ('F', 3) 1224 >>> F().f(3) 1225 ('F', 3) 1226 1227This behavior is useful whenever the method only needs to have a class 1228reference and does not 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 1231keys. The pure Python equivalent is: 1232 1233.. testcode:: 1234 1235 class Dict(dict): 1236 @classmethod 1237 def fromkeys(cls, iterable, value=None): 1238 "Emulate dict_fromkeys() in Objects/dictobject.c" 1239 d = cls() 1240 for key in iterable: 1241 d[key] = value 1242 return d 1243 1244Now a new dictionary of unique keys can be constructed like this: 1245 1246.. doctest:: 1247 1248 >>> d = Dict.fromkeys('abracadabra') 1249 >>> type(d) is Dict 1250 True 1251 >>> d 1252 {'a': None, 'b': None, 'r': None, 'c': None, 'd': None} 1253 1254Using the non-data descriptor protocol, a pure Python version of 1255:func:`classmethod` would look like this: 1256 1257.. testcode:: 1258 1259 class ClassMethod: 1260 "Emulate PyClassMethod_Type() in Objects/funcobject.c" 1261 1262 def __init__(self, f): 1263 self.f = f 1264 1265 def __get__(self, obj, cls=None): 1266 if cls is None: 1267 cls = type(obj) 1268 if hasattr(obj, '__get__'): 1269 return self.f.__get__(cls) 1270 return MethodType(self.f, cls) 1271 1272.. 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 1292The code path for ``hasattr(obj, '__get__')`` was added in Python 3.9 and 1293makes it possible for :func:`classmethod` to support chained decorators. 1294For example, a classmethod and property could be chained together: 1295 1296.. testcode:: 1297 1298 class G: 1299 @classmethod 1300 @property 1301 def __doc__(cls): 1302 return f'A doc for {cls.__name__!r}' 1303 1304.. doctest:: 1305 1306 >>> G.__doc__ 1307 "A doc for 'G'" 1308 1309 1310Member objects and __slots__ 1311---------------------------- 1312 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 1318assignments. Only attribute names specified in ``__slots__`` are allowed: 1319 1320.. testcode:: 1321 1322 class Vehicle: 1323 __slots__ = ('id_number', 'make', 'model') 1324 1325.. doctest:: 1326 1327 >>> 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 1334attributes stored in ``__slots__``: 1335 1336.. testcode:: 1337 1338 class Immutable: 1339 1340 __slots__ = ('_dept', '_name') # Replace the instance dictionary 1341 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 1354.. 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' 1367 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 1374instance dictionary to function correctly: 1375 1376.. testcode:: 1377 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 1388.. doctest:: 1389 1390 >>> CP().pi 1391 Traceback (most recent call last): 1392 ... 1393 TypeError: No '__dict__' attribute on 'CP' instance to cache 'pi' property. 1394 1395It is not possible to create an exact drop-in pure Python version of 1396``__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 1400by member descriptors: 1401 1402.. testcode:: 1403 1404 null = object() 1405 1406 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 1418 value = obj._slotvalues[self.offset] 1419 if value is null: 1420 raise AttributeError(self.name) 1421 return value 1422 1423 def __set__(self, obj, value): 1424 'Emulate member_set() in Objects/descrobject.c' 1425 obj._slotvalues[self.offset] = value 1426 1427 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 1434 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 1439variables: 1440 1441.. testcode:: 1442 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 1454The :meth:`object.__new__` method takes care of creating instances that have 1455slots instead of an instance dictionary. Here is a rough simulation in pure 1456Python: 1457 1458.. testcode:: 1459 1460 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'): 1467 empty_slots = [null] * len(cls.slot_names) 1468 object.__setattr__(inst, '_slotvalues', empty_slots) 1469 return inst 1470 1471 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 1489To use the simulation in a real class, just inherit from :class:`Object` and 1490set the :term:`metaclass` to :class:`Type`: 1491 1492.. testcode:: 1493 1494 class H(Object, metaclass=Type): 1495 'Instance variables stored in slots' 1496 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 1505 >>> from pprint import pp 1506 >>> pp(dict(vars(H))) 1507 {'__module__': '__main__', 1508 '__doc__': 'Instance variables stored in slots', 1509 'slot_names': ['x', 'y'], 1510 '__init__': <function H.__init__ at 0x7fb5d302f9d0>, 1511 'x': <Member 'x' of 'H'>, 1512 'y': <Member 'y' of 'H'>} 1513 1514.. 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 1524When instances are created, they have a ``slot_values`` list where the 1525attributes are stored: 1526 1527.. doctest:: 1528 1529 >>> h = H(10, 20) 1530 >>> vars(h) 1531 {'_slotvalues': [10, 20]} 1532 >>> h.x = 55 1533 >>> vars(h) 1534 {'_slotvalues': [55, 20]} 1535 1536Misspelled or unassigned attributes will raise an exception: 1537 1538.. doctest:: 1539 1540 >>> h.xz 1541 Traceback (most recent call last): 1542 ... 1543 AttributeError: 'H' object has no attribute 'xz' 1544 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 1563