.. _descriptorhowto:

======================
Descriptor HowTo Guide
======================

:Author: Raymond Hettinger
:Contact: <python at rcn dot com>

.. Contents::


:term:`Descriptors <descriptor>` let objects customize attribute lookup,
storage, and deletion.

This guide has four major sections:

1) The "primer" gives a basic overview, moving gently from simple examples,
   adding one feature at a time.  Start here if you're new to descriptors.

2) The second section shows a complete, practical descriptor example.  If you
   already know the basics, start there.

3) The third section provides a more technical tutorial that goes into the
   detailed mechanics of how descriptors work.  Most people don't need this
   level of detail.

4) The last section has pure Python equivalents for built-in descriptors that
   are written in C.  Read this if you're curious about how functions turn
   into bound methods or about the implementation of common tools like
   :func:`classmethod`, :func:`staticmethod`, :func:`property`, and
   :term:`__slots__`.


Primer
^^^^^^

In this primer, we start with the most basic possible example and then we'll
add new capabilities one by one.


Simple example: A descriptor that returns a constant
----------------------------------------------------

The :class:`Ten` class is a descriptor that always returns the constant ``10``
from its :meth:`__get__` method:

.. testcode::

    class Ten:
        def __get__(self, obj, objtype=None):
            return 10

To use the descriptor, it must be stored as a class variable in another class:

.. testcode::

    class A:
        x = 5                       # Regular class attribute
        y = Ten()                   # Descriptor instance

An interactive session shows the difference between normal attribute lookup
and descriptor lookup:

.. doctest::

    >>> a = A()                     # Make an instance of class A
    >>> a.x                         # Normal attribute lookup
    5
    >>> a.y                         # Descriptor lookup
    10

In the ``a.x`` attribute lookup, the dot operator finds the key ``x`` and the
value ``5`` in the class dictionary.  In the ``a.y`` lookup, the dot operator
finds a descriptor instance, recognized by its ``__get__`` method, and calls
that method which returns ``10``.

Note that the value ``10`` is not stored in either the class dictionary or the
instance dictionary.  Instead, the value ``10`` is computed on demand.

This example shows how a simple descriptor works, but it isn't very useful.
For retrieving constants, normal attribute lookup would be better.

In the next section, we'll create something more useful, a dynamic lookup.


Dynamic lookups
---------------

Interesting descriptors typically run computations instead of returning
constants:

.. testcode::

    import os

    class DirectorySize:

        def __get__(self, obj, objtype=None):
            return len(os.listdir(obj.dirname))

    class Directory:

        size = DirectorySize()              # Descriptor instance

        def __init__(self, dirname):
            self.dirname = dirname          # Regular instance attribute

An interactive session shows that the lookup is dynamic — it computes
different, updated answers each time::

    >>> s = Directory('songs')
    >>> g = Directory('games')
    >>> s.size                              # The songs directory has twenty files
    20
    >>> g.size                              # The games directory has three files
    3
    >>> open('games/newfile').close()       # Add a fourth file to the directory
    >>> g.size                              # File count is automatically updated
    4

Besides showing how descriptors can run computations, this example also
reveals the purpose of the parameters to :meth:`__get__`.  The *self*
parameter is *size*, an instance of *DirectorySize*.  The *obj* parameter is
either *g* or *s*, an instance of *Directory*.  It is the *obj* parameter that
lets the :meth:`__get__` method learn the target directory.  The *objtype*
parameter is the class *Directory*.


Managed attributes
------------------

A popular use for descriptors is managing access to instance data.  The
descriptor is assigned to a public attribute in the class dictionary while the
actual data is stored as a private attribute in the instance dictionary.  The
descriptor's :meth:`__get__` and :meth:`__set__` methods are triggered when
the public attribute is accessed.

In the following example, *age* is the public attribute and *_age* is the
private attribute.  When the public attribute is accessed, the descriptor logs
the lookup or update:

.. testcode::

    import logging

    logging.basicConfig(level=logging.INFO)

    class LoggedAgeAccess:

        def __get__(self, obj, objtype=None):
            value = obj._age
            logging.info('Accessing %r giving %r', 'age', value)
            return value

        def __set__(self, obj, value):
            logging.info('Updating %r to %r', 'age', value)
            obj._age = value

    class Person:

        age = LoggedAgeAccess()             # Descriptor instance

        def __init__(self, name, age):
            self.name = name                # Regular instance attribute
            self.age = age                  # Calls __set__()

        def birthday(self):
            self.age += 1                   # Calls both __get__() and __set__()


An interactive session shows that all access to the managed attribute *age* is
logged, but that the regular attribute *name* is not logged:

.. testcode::
    :hide:

    import logging, sys
    logging.basicConfig(level=logging.INFO, stream=sys.stdout, force=True)

.. doctest::

    >>> mary = Person('Mary M', 30)         # The initial age update is logged
    INFO:root:Updating 'age' to 30
    >>> dave = Person('David D', 40)
    INFO:root:Updating 'age' to 40

    >>> vars(mary)                          # The actual data is in a private attribute
    {'name': 'Mary M', '_age': 30}
    >>> vars(dave)
    {'name': 'David D', '_age': 40}

    >>> mary.age                            # Access the data and log the lookup
    INFO:root:Accessing 'age' giving 30
    30
    >>> mary.birthday()                     # Updates are logged as well
    INFO:root:Accessing 'age' giving 30
    INFO:root:Updating 'age' to 31

    >>> dave.name                           # Regular attribute lookup isn't logged
    'David D'
    >>> dave.age                            # Only the managed attribute is logged
    INFO:root:Accessing 'age' giving 40
    40

One major issue with this example is that the private name *_age* is hardwired in
the *LoggedAgeAccess* class.  That means that each instance can only have one
logged attribute and that its name is unchangeable.  In the next example,
we'll fix that problem.


Customized names
----------------

When a class uses descriptors, it can inform each descriptor about which
variable name was used.

In this example, the :class:`Person` class has two descriptor instances,
*name* and *age*.  When the :class:`Person` class is defined, it makes a
callback to :meth:`__set_name__` in *LoggedAccess* so that the field names can
be recorded, giving each descriptor its own *public_name* and *private_name*:

.. testcode::

    import logging

    logging.basicConfig(level=logging.INFO)

    class LoggedAccess:

        def __set_name__(self, owner, name):
            self.public_name = name
            self.private_name = '_' + name

        def __get__(self, obj, objtype=None):
            value = getattr(obj, self.private_name)
            logging.info('Accessing %r giving %r', self.public_name, value)
            return value

        def __set__(self, obj, value):
            logging.info('Updating %r to %r', self.public_name, value)
            setattr(obj, self.private_name, value)

    class Person:

        name = LoggedAccess()                # First descriptor instance
        age = LoggedAccess()                 # Second descriptor instance

        def __init__(self, name, age):
            self.name = name                 # Calls the first descriptor
            self.age = age                   # Calls the second descriptor

        def birthday(self):
            self.age += 1

An interactive session shows that the :class:`Person` class has called
:meth:`__set_name__` so that the field names would be recorded.  Here
we call :func:`vars` to look up the descriptor without triggering it:

.. doctest::

    >>> vars(vars(Person)['name'])
    {'public_name': 'name', 'private_name': '_name'}
    >>> vars(vars(Person)['age'])
    {'public_name': 'age', 'private_name': '_age'}

The new class now logs access to both *name* and *age*:

.. testcode::
    :hide:

    import logging, sys
    logging.basicConfig(level=logging.INFO, stream=sys.stdout, force=True)

.. doctest::

    >>> pete = Person('Peter P', 10)
    INFO:root:Updating 'name' to 'Peter P'
    INFO:root:Updating 'age' to 10
    >>> kate = Person('Catherine C', 20)
    INFO:root:Updating 'name' to 'Catherine C'
    INFO:root:Updating 'age' to 20

The two *Person* instances contain only the private names::

    >>> vars(pete)
    {'_name': 'Peter P', '_age': 10}
    >>> vars(kate)
    {'_name': 'Catherine C', '_age': 20}


Closing thoughts
----------------

A :term:`descriptor` is what we call any object that defines :meth:`__get__`,
:meth:`__set__`, or :meth:`__delete__`.

Optionally, descriptors can have a :meth:`__set_name__` method.  This is only
used in cases where a descriptor needs to know either the class where it was
created or the name of class variable it was assigned to.  (This method, if
present, is called even if the class is not a descriptor.)

Descriptors get invoked by the dot "operator" during attribute lookup.  If a
descriptor is accessed indirectly with ``vars(some_class)[descriptor_name]``,
the descriptor instance is returned without invoking it.

Descriptors only work when used as class variables.  When put in instances,
they have no effect.

The main motivation for descriptors is to provide a hook allowing objects
stored in class variables to control what happens during attribute lookup.

Traditionally, the calling class controls what happens during lookup.
Descriptors invert that relationship and allow the data being looked-up to
have a say in the matter.

Descriptors are used throughout the language.  It is how functions turn into
bound methods.  Common tools like :func:`classmethod`, :func:`staticmethod`,
:func:`property`, and :func:`functools.cached_property` are all implemented as
descriptors.


Complete Practical Example
^^^^^^^^^^^^^^^^^^^^^^^^^^

In this example, we create a practical and powerful tool for locating
notoriously hard to find data corruption bugs.


Validator class
---------------

A validator is a descriptor for managed attribute access.  Prior to storing
any data, it verifies that the new value meets various type and range
restrictions.  If those restrictions aren't met, it raises an exception to
prevent data corruption at its source.

This :class:`Validator` class is both an :term:`abstract base class` and a
managed attribute descriptor:

.. testcode::

    from abc import ABC, abstractmethod

    class Validator(ABC):

        def __set_name__(self, owner, name):
            self.private_name = '_' + name

        def __get__(self, obj, objtype=None):
            return getattr(obj, self.private_name)

        def __set__(self, obj, value):
            self.validate(value)
            setattr(obj, self.private_name, value)

        @abstractmethod
        def validate(self, value):
            pass

Custom validators need to inherit from :class:`Validator` and must supply a
:meth:`validate` method to test various restrictions as needed.


Custom validators
-----------------

Here are three practical data validation utilities:

1) :class:`OneOf` verifies that a value is one of a restricted set of options.

2) :class:`Number` verifies that a value is either an :class:`int` or
   :class:`float`.  Optionally, it verifies that a value is between a given
   minimum or maximum.

3) :class:`String` verifies that a value is a :class:`str`.  Optionally, it
   validates a given minimum or maximum length.  It can validate a
   user-defined `predicate
   <https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)>`_ as well.

.. testcode::

    class OneOf(Validator):

        def __init__(self, *options):
            self.options = set(options)

        def validate(self, value):
            if value not in self.options:
                raise ValueError(f'Expected {value!r} to be one of {self.options!r}')

    class Number(Validator):

        def __init__(self, minvalue=None, maxvalue=None):
            self.minvalue = minvalue
            self.maxvalue = maxvalue

        def validate(self, value):
            if not isinstance(value, (int, float)):
                raise TypeError(f'Expected {value!r} to be an int or float')
            if self.minvalue is not None and value < self.minvalue:
                raise ValueError(
                    f'Expected {value!r} to be at least {self.minvalue!r}'
                )
            if self.maxvalue is not None and value > self.maxvalue:
                raise ValueError(
                    f'Expected {value!r} to be no more than {self.maxvalue!r}'
                )

    class String(Validator):

        def __init__(self, minsize=None, maxsize=None, predicate=None):
            self.minsize = minsize
            self.maxsize = maxsize
            self.predicate = predicate

        def validate(self, value):
            if not isinstance(value, str):
                raise TypeError(f'Expected {value!r} to be an str')
            if self.minsize is not None and len(value) < self.minsize:
                raise ValueError(
                    f'Expected {value!r} to be no smaller than {self.minsize!r}'
                )
            if self.maxsize is not None and len(value) > self.maxsize:
                raise ValueError(
                    f'Expected {value!r} to be no bigger than {self.maxsize!r}'
                )
            if self.predicate is not None and not self.predicate(value):
                raise ValueError(
                    f'Expected {self.predicate} to be true for {value!r}'
                )


Practical application
---------------------

Here's how the data validators can be used in a real class:

.. testcode::

    class Component:

        name = String(minsize=3, maxsize=10, predicate=str.isupper)
        kind = OneOf('wood', 'metal', 'plastic')
        quantity = Number(minvalue=0)

        def __init__(self, name, kind, quantity):
            self.name = name
            self.kind = kind
            self.quantity = quantity

The descriptors prevent invalid instances from being created:

.. doctest::

    >>> Component('Widget', 'metal', 5)      # Blocked: 'Widget' is not all uppercase
    Traceback (most recent call last):
        ...
    ValueError: Expected <method 'isupper' of 'str' objects> to be true for 'Widget'

    >>> Component('WIDGET', 'metle', 5)      # Blocked: 'metle' is misspelled
    Traceback (most recent call last):
        ...
    ValueError: Expected 'metle' to be one of {'metal', 'plastic', 'wood'}

    >>> Component('WIDGET', 'metal', -5)     # Blocked: -5 is negative
    Traceback (most recent call last):
        ...
    ValueError: Expected -5 to be at least 0
    >>> Component('WIDGET', 'metal', 'V')    # Blocked: 'V' isn't a number
    Traceback (most recent call last):
        ...
    TypeError: Expected 'V' to be an int or float

    >>> c = Component('WIDGET', 'metal', 5)  # Allowed:  The inputs are valid


Technical Tutorial
^^^^^^^^^^^^^^^^^^

What follows is a more technical tutorial for the mechanics and details of how
descriptors work.


Abstract
--------

Defines descriptors, summarizes the protocol, and shows how descriptors are
called.  Provides an example showing how object relational mappings work.

Learning about descriptors not only provides access to a larger toolset, it
creates a deeper understanding of how Python works.


Definition and introduction
---------------------------

In general, a descriptor is an attribute value that has one of the methods in
the descriptor protocol.  Those methods are :meth:`__get__`, :meth:`__set__`,
and :meth:`__delete__`.  If any of those methods are defined for an the
attribute, it is said to be a :term:`descriptor`.

The default behavior for attribute access is to get, set, or delete the
attribute from an object's dictionary.  For instance, ``a.x`` has a lookup chain
starting with ``a.__dict__['x']``, then ``type(a).__dict__['x']``, and
continuing through the method resolution order of ``type(a)``. If the
looked-up value is an object defining one of the descriptor methods, then Python
may override the default behavior and invoke the descriptor method instead.
Where this occurs in the precedence chain depends on which descriptor methods
were defined.

Descriptors are a powerful, general purpose protocol.  They are the mechanism
behind properties, methods, static methods, class methods, and
:func:`super()`.  They are used throughout Python itself.  Descriptors
simplify the underlying C code and offer a flexible set of new tools for
everyday Python programs.


Descriptor protocol
-------------------

``descr.__get__(self, obj, type=None) -> value``

``descr.__set__(self, obj, value) -> None``

``descr.__delete__(self, obj) -> None``

That is all there is to it.  Define any of these methods and an object is
considered a descriptor and can override default behavior upon being looked up
as an attribute.

If an object defines :meth:`__set__` or :meth:`__delete__`, it is considered
a data descriptor.  Descriptors that only define :meth:`__get__` are called
non-data descriptors (they are often used for methods but other uses are
possible).

Data and non-data descriptors differ in how overrides are calculated with
respect to entries in an instance's dictionary.  If an instance's dictionary
has an entry with the same name as a data descriptor, the data descriptor
takes precedence.  If an instance's dictionary has an entry with the same
name as a non-data descriptor, the dictionary entry takes precedence.

To make a read-only data descriptor, define both :meth:`__get__` and
:meth:`__set__` with the :meth:`__set__` raising an :exc:`AttributeError` when
called.  Defining the :meth:`__set__` method with an exception raising
placeholder is enough to make it a data descriptor.


Overview of descriptor invocation
---------------------------------

A descriptor can be called directly with ``desc.__get__(obj)`` or
``desc.__get__(None, cls)``.

But it is more common for a descriptor to be invoked automatically from
attribute access.

The expression ``obj.x`` looks up the attribute ``x`` in the chain of
namespaces for ``obj``.  If the search finds a descriptor outside of the
instance ``__dict__``, its :meth:`__get__` method is invoked according to the
precedence rules listed below.

The details of invocation depend on whether ``obj`` is an object, class, or
instance of super.


Invocation from an instance
---------------------------

Instance lookup scans through a chain of namespaces giving data descriptors
the highest priority, followed by instance variables, then non-data
descriptors, then class variables, and lastly :meth:`__getattr__` if it is
provided.

If a descriptor is found for ``a.x``, then it is invoked with:
``desc.__get__(a, type(a))``.

The logic for a dotted lookup is in :meth:`object.__getattribute__`.  Here is
a pure Python equivalent:

.. testcode::

    def object_getattribute(obj, name):
        "Emulate PyObject_GenericGetAttr() in Objects/object.c"
        null = object()
        objtype = type(obj)
        cls_var = getattr(objtype, name, null)
        descr_get = getattr(type(cls_var), '__get__', null)
        if descr_get is not null:
            if (hasattr(type(cls_var), '__set__')
                or hasattr(type(cls_var), '__delete__')):
                return descr_get(cls_var, obj, objtype)     # data descriptor
        if hasattr(obj, '__dict__') and name in vars(obj):
            return vars(obj)[name]                          # instance variable
        if descr_get is not null:
            return descr_get(cls_var, obj, objtype)         # non-data descriptor
        if cls_var is not null:
            return cls_var                                  # class variable
        raise AttributeError(name)


.. testcode::
    :hide:

    # Test the fidelity of object_getattribute() by comparing it with the
    # normal object.__getattribute__().  The former will be accessed by
    # square brackets and the latter by the dot operator.

    class Object:

        def __getitem__(obj, name):
            try:
                return object_getattribute(obj, name)
            except AttributeError:
                if not hasattr(type(obj), '__getattr__'):
                    raise
            return type(obj).__getattr__(obj, name)             # __getattr__

    class DualOperator(Object):

        x = 10

        def __init__(self, z):
            self.z = z

        @property
        def p2(self):
            return 2 * self.x

        @property
        def p3(self):
            return 3 * self.x

        def m5(self, y):
            return 5 * y

        def m7(self, y):
            return 7 * y

        def __getattr__(self, name):
            return ('getattr_hook', self, name)

    class DualOperatorWithSlots:

        __getitem__ = Object.__getitem__

        __slots__ = ['z']

        x = 15

        def __init__(self, z):
            self.z = z

        @property
        def p2(self):
            return 2 * self.x

        def m5(self, y):
            return 5 * y

        def __getattr__(self, name):
            return ('getattr_hook', self, name)


.. doctest::
    :hide:

    >>> a = DualOperator(11)
    >>> vars(a).update(p3 = '_p3', m7 = '_m7')
    >>> a.x == a['x'] == 10
    True
    >>> a.z == a['z'] == 11
    True
    >>> a.p2 == a['p2'] == 20
    True
    >>> a.p3 == a['p3'] == 30
    True
    >>> a.m5(100) == a.m5(100) == 500
    True
    >>> a.m7 == a['m7'] == '_m7'
    True
    >>> a.g == a['g'] == ('getattr_hook', a, 'g')
    True

    >>> b = DualOperatorWithSlots(22)
    >>> b.x == b['x'] == 15
    True
    >>> b.z == b['z'] == 22
    True
    >>> b.p2 == b['p2'] == 30
    True
    >>> b.m5(200) == b['m5'](200) == 1000
    True
    >>> b.g == b['g'] == ('getattr_hook', b, 'g')
    True


Interestingly, attribute lookup doesn't call :meth:`object.__getattribute__`
directly.  Instead, both the dot operator and the :func:`getattr` function
perform attribute lookup by way of a helper function:

.. testcode::

    def getattr_hook(obj, name):
        "Emulate slot_tp_getattr_hook() in Objects/typeobject.c"
        try:
            return obj.__getattribute__(name)
        except AttributeError:
            if not hasattr(type(obj), '__getattr__'):
                raise
        return type(obj).__getattr__(obj, name)             # __getattr__

So if :meth:`__getattr__` exists, it is called whenever :meth:`__getattribute__`
raises :exc:`AttributeError` (either directly or in one of the descriptor calls).

Also, if a user calls :meth:`object.__getattribute__` directly, the
:meth:`__getattr__` hook is bypassed entirely.


Invocation from a class
-----------------------

The logic for a dotted lookup such as ``A.x`` is in
:meth:`type.__getattribute__`.  The steps are similar to those for
:meth:`object.__getattribute__` but the instance dictionary lookup is replaced
by a search through the class's :term:`method resolution order`.

If a descriptor is found, it is invoked with ``desc.__get__(None, A)``.

The full C implementation can be found in :c:func:`type_getattro()` and
:c:func:`_PyType_Lookup()` in :source:`Objects/typeobject.c`.


Invocation from super
---------------------

The logic for super's dotted lookup is in the :meth:`__getattribute__` method for
object returned by :class:`super()`.

A dotted lookup such as ``super(A, obj).m`` searches ``obj.__class__.__mro__``
for the base class ``B`` immediately following ``A`` and then returns
``B.__dict__['m'].__get__(obj, A)``.  If not a descriptor, ``m`` is returned
unchanged.

The full C implementation can be found in :c:func:`super_getattro()` in
:source:`Objects/typeobject.c`.  A pure Python equivalent can be found in
`Guido's Tutorial
<https://www.python.org/download/releases/2.2.3/descrintro/#cooperation>`_.


Summary of invocation logic
---------------------------

The mechanism for descriptors is embedded in the :meth:`__getattribute__()`
methods for :class:`object`, :class:`type`, and :func:`super`.

The important points to remember are:

* Descriptors are invoked by the :meth:`__getattribute__` method.

* Classes inherit this machinery from :class:`object`, :class:`type`, or
  :func:`super`.

* Overriding :meth:`__getattribute__` prevents automatic descriptor calls
  because all the descriptor logic is in that method.

* :meth:`object.__getattribute__` and :meth:`type.__getattribute__` make
  different calls to :meth:`__get__`.  The first includes the instance and may
  include the class.  The second puts in ``None`` for the instance and always
  includes the class.

* Data descriptors always override instance dictionaries.

* Non-data descriptors may be overridden by instance dictionaries.


Automatic name notification
---------------------------

Sometimes it is desirable for a descriptor to know what class variable name it
was assigned to.  When a new class is created, the :class:`type` metaclass
scans the dictionary of the new class.  If any of the entries are descriptors
and if they define :meth:`__set_name__`, that method is called with two
arguments.  The *owner* is the class where the descriptor is used, and the
*name* is the class variable the descriptor was assigned to.

The implementation details are in :c:func:`type_new()` and
:c:func:`set_names()` in :source:`Objects/typeobject.c`.

Since the update logic is in :meth:`type.__new__`, notifications only take
place at the time of class creation.  If descriptors are added to the class
afterwards, :meth:`__set_name__` will need to be called manually.


ORM example
-----------

The following code is simplified skeleton showing how data descriptors could
be used to implement an `object relational mapping
<https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping>`_.

The essential idea is that the data is stored in an external database.  The
Python instances only hold keys to the database's tables.  Descriptors take
care of lookups or updates:

.. testcode::

    class Field:

        def __set_name__(self, owner, name):
            self.fetch = f'SELECT {name} FROM {owner.table} WHERE {owner.key}=?;'
            self.store = f'UPDATE {owner.table} SET {name}=? WHERE {owner.key}=?;'

        def __get__(self, obj, objtype=None):
            return conn.execute(self.fetch, [obj.key]).fetchone()[0]

        def __set__(self, obj, value):
            conn.execute(self.store, [value, obj.key])
            conn.commit()

We can use the :class:`Field` class to define `models
<https://en.wikipedia.org/wiki/Database_model>`_ that describe the schema for
each table in a database:

.. testcode::

    class Movie:
        table = 'Movies'                    # Table name
        key = 'title'                       # Primary key
        director = Field()
        year = Field()

        def __init__(self, key):
            self.key = key

    class Song:
        table = 'Music'
        key = 'title'
        artist = Field()
        year = Field()
        genre = Field()

        def __init__(self, key):
            self.key = key

To use the models, first connect to the database::

    >>> import sqlite3
    >>> conn = sqlite3.connect('entertainment.db')

An interactive session shows how data is retrieved from the database and how
it can be updated:

.. testsetup::

    song_data = [
        ('Country Roads', 'John Denver', 1972),
        ('Me and Bobby McGee', 'Janice Joplin', 1971),
        ('Coal Miners Daughter', 'Loretta Lynn', 1970),
    ]

    movie_data = [
        ('Star Wars', 'George Lucas', 1977),
        ('Jaws', 'Steven Spielberg', 1975),
        ('Aliens', 'James Cameron', 1986),
    ]

    import sqlite3

    conn = sqlite3.connect(':memory:')
    conn.execute('CREATE TABLE Music (title text, artist text, year integer);')
    conn.execute('CREATE INDEX MusicNdx ON Music (title);')
    conn.executemany('INSERT INTO Music VALUES (?, ?, ?);', song_data)
    conn.execute('CREATE TABLE Movies (title text, director text, year integer);')
    conn.execute('CREATE INDEX MovieNdx ON Music (title);')
    conn.executemany('INSERT INTO Movies VALUES (?, ?, ?);', movie_data)
    conn.commit()

.. doctest::

    >>> Movie('Star Wars').director
    'George Lucas'
    >>> jaws = Movie('Jaws')
    >>> f'Released in {jaws.year} by {jaws.director}'
    'Released in 1975 by Steven Spielberg'

    >>> Song('Country Roads').artist
    'John Denver'

    >>> Movie('Star Wars').director = 'J.J. Abrams'
    >>> Movie('Star Wars').director
    'J.J. Abrams'


Pure Python Equivalents
^^^^^^^^^^^^^^^^^^^^^^^

The descriptor protocol is simple and offers exciting possibilities.  Several
use cases are so common that they have been prepackaged into built-in tools.
Properties, bound methods, static methods, class methods, and \_\_slots\_\_ are
all based on the descriptor protocol.


Properties
----------

Calling :func:`property` is a succinct way of building a data descriptor that
triggers a function call upon access to an attribute.  Its signature is::

    property(fget=None, fset=None, fdel=None, doc=None) -> property

The documentation shows a typical use to define a managed attribute ``x``:

.. testcode::

    class C:
        def getx(self): return self.__x
        def setx(self, value): self.__x = value
        def delx(self): del self.__x
        x = property(getx, setx, delx, "I'm the 'x' property.")

To see how :func:`property` is implemented in terms of the descriptor protocol,
here is a pure Python equivalent:

.. testcode::

    class Property:
        "Emulate PyProperty_Type() in Objects/descrobject.c"

        def __init__(self, fget=None, fset=None, fdel=None, doc=None):
            self.fget = fget
            self.fset = fset
            self.fdel = fdel
            if doc is None and fget is not None:
                doc = fget.__doc__
            self.__doc__ = doc

        def __get__(self, obj, objtype=None):
            if obj is None:
                return self
            if self.fget is None:
                raise AttributeError("unreadable attribute")
            return self.fget(obj)

        def __set__(self, obj, value):
            if self.fset is None:
                raise AttributeError("can't set attribute")
            self.fset(obj, value)

        def __delete__(self, obj):
            if self.fdel is None:
                raise AttributeError("can't delete attribute")
            self.fdel(obj)

        def getter(self, fget):
            return type(self)(fget, self.fset, self.fdel, self.__doc__)

        def setter(self, fset):
            return type(self)(self.fget, fset, self.fdel, self.__doc__)

        def deleter(self, fdel):
            return type(self)(self.fget, self.fset, fdel, self.__doc__)

.. testcode::
    :hide:

    # Verify the Property() emulation

    class CC:
        def getx(self):
            return self.__x
        def setx(self, value):
            self.__x = value
        def delx(self):
            del self.__x
        x = Property(getx, setx, delx, "I'm the 'x' property.")

    # Now do it again but use the decorator style

    class CCC:
        @Property
        def x(self):
            return self.__x
        @x.setter
        def x(self, value):
            self.__x = value
        @x.deleter
        def x(self):
            del self.__x


.. doctest::
    :hide:

    >>> cc = CC()
    >>> hasattr(cc, 'x')
    False
    >>> cc.x = 33
    >>> cc.x
    33
    >>> del cc.x
    >>> hasattr(cc, 'x')
    False

    >>> ccc = CCC()
    >>> hasattr(ccc, 'x')
    False
    >>> ccc.x = 333
    >>> ccc.x == 333
    True
    >>> del ccc.x
    >>> hasattr(ccc, 'x')
    False

The :func:`property` builtin helps whenever a user interface has granted
attribute access and then subsequent changes require the intervention of a
method.

For instance, a spreadsheet class may grant access to a cell value through
``Cell('b10').value``. Subsequent improvements to the program require the cell
to be recalculated on every access; however, the programmer does not want to
affect existing client code accessing the attribute directly.  The solution is
to wrap access to the value attribute in a property data descriptor:

.. testcode::

    class Cell:
        ...

        @property
        def value(self):
            "Recalculate the cell before returning value"
            self.recalc()
            return self._value

Either the built-in :func:`property` or our :func:`Property` equivalent would
work in this example.


Functions and methods
---------------------

Python's object oriented features are built upon a function based environment.
Using non-data descriptors, the two are merged seamlessly.

Functions stored in class dictionaries get turned into methods when invoked.
Methods only differ from regular functions in that the object instance is
prepended to the other arguments.  By convention, the instance is called
*self* but could be called *this* or any other variable name.

Methods can be created manually with :class:`types.MethodType` which is
roughly equivalent to:

.. testcode::

    class MethodType:
        "Emulate Py_MethodType in Objects/classobject.c"

        def __init__(self, func, obj):
            self.__func__ = func
            self.__self__ = obj

        def __call__(self, *args, **kwargs):
            func = self.__func__
            obj = self.__self__
            return func(obj, *args, **kwargs)

To support automatic creation of methods, functions include the
:meth:`__get__` method for binding methods during attribute access.  This
means that functions are non-data descriptors that return bound methods
during dotted lookup from an instance.  Here's how it works:

.. testcode::

    class Function:
        ...

        def __get__(self, obj, objtype=None):
            "Simulate func_descr_get() in Objects/funcobject.c"
            if obj is None:
                return self
            return MethodType(self, obj)

Running the following class in the interpreter shows how the function
descriptor works in practice:

.. testcode::

    class D:
        def f(self, x):
             return x

The function has a :term:`qualified name` attribute to support introspection:

.. doctest::

    >>> D.f.__qualname__
    'D.f'

Accessing the function through the class dictionary does not invoke
:meth:`__get__`.  Instead, it just returns the underlying function object::

    >>> D.__dict__['f']
    <function D.f at 0x00C45070>

Dotted access from a class calls :meth:`__get__` which just returns the
underlying function unchanged::

    >>> D.f
    <function D.f at 0x00C45070>

The interesting behavior occurs during dotted access from an instance.  The
dotted lookup calls :meth:`__get__` which returns a bound method object::

    >>> d = D()
    >>> d.f
    <bound method D.f of <__main__.D object at 0x00B18C90>>

Internally, the bound method stores the underlying function and the bound
instance::

    >>> d.f.__func__
    <function D.f at 0x00C45070>

    >>> d.f.__self__
    <__main__.D object at 0x1012e1f98>

If you have ever wondered where *self* comes from in regular methods or where
*cls* comes from in class methods, this is it!


Static methods
--------------

Non-data descriptors provide a simple mechanism for variations on the usual
patterns of binding functions into methods.

To recap, functions have a :meth:`__get__` method so that they can be converted
to a method when accessed as attributes.  The non-data descriptor transforms an
``obj.f(*args)`` call into ``f(obj, *args)``.  Calling ``cls.f(*args)``
becomes ``f(*args)``.

This chart summarizes the binding and its two most useful variants:

      +-----------------+----------------------+------------------+
      | Transformation  | Called from an       | Called from a    |
      |                 | object               | class            |
      +=================+======================+==================+
      | function        | f(obj, \*args)       | f(\*args)        |
      +-----------------+----------------------+------------------+
      | staticmethod    | f(\*args)            | f(\*args)        |
      +-----------------+----------------------+------------------+
      | classmethod     | f(type(obj), \*args) | f(cls, \*args)   |
      +-----------------+----------------------+------------------+

Static methods return the underlying function without changes.  Calling either
``c.f`` or ``C.f`` is the equivalent of a direct lookup into
``object.__getattribute__(c, "f")`` or ``object.__getattribute__(C, "f")``. As a
result, the function becomes identically accessible from either an object or a
class.

Good candidates for static methods are methods that do not reference the
``self`` variable.

For instance, a statistics package may include a container class for
experimental data.  The class provides normal methods for computing the average,
mean, median, and other descriptive statistics that depend on the data. However,
there may be useful functions which are conceptually related but do not depend
on the data.  For instance, ``erf(x)`` is handy conversion routine that comes up
in statistical work but does not directly depend on a particular dataset.
It can be called either from an object or the class:  ``s.erf(1.5) --> .9332`` or
``Sample.erf(1.5) --> .9332``.

Since static methods return the underlying function with no changes, the
example calls are unexciting:

.. testcode::

    class E:
        @staticmethod
        def f(x):
            print(x)

.. doctest::

    >>> E.f(3)
    3
    >>> E().f(3)
    3

Using the non-data descriptor protocol, a pure Python version of
:func:`staticmethod` would look like this:

.. doctest::

    class StaticMethod:
        "Emulate PyStaticMethod_Type() in Objects/funcobject.c"

        def __init__(self, f):
            self.f = f

        def __get__(self, obj, objtype=None):
            return self.f


Class methods
-------------

Unlike static methods, class methods prepend the class reference to the
argument list before calling the function.  This format is the same
for whether the caller is an object or a class:

.. testcode::

    class F:
        @classmethod
        def f(cls, x):
            return cls.__name__, x

.. doctest::

    >>> F.f(3)
    ('F', 3)
    >>> F().f(3)
    ('F', 3)

This behavior is useful whenever the method only needs to have a class
reference and does not rely on data stored in a specific instance.  One use for
class methods is to create alternate class constructors.  For example, the
classmethod :func:`dict.fromkeys` creates a new dictionary from a list of
keys.  The pure Python equivalent is:

.. testcode::

    class Dict(dict):
        @classmethod
        def fromkeys(cls, iterable, value=None):
            "Emulate dict_fromkeys() in Objects/dictobject.c"
            d = cls()
            for key in iterable:
                d[key] = value
            return d

Now a new dictionary of unique keys can be constructed like this:

.. doctest::

    >>> d = Dict.fromkeys('abracadabra')
    >>> type(d) is Dict
    True
    >>> d
    {'a': None, 'b': None, 'r': None, 'c': None, 'd': None}

Using the non-data descriptor protocol, a pure Python version of
:func:`classmethod` would look like this:

.. testcode::

    class ClassMethod:
        "Emulate PyClassMethod_Type() in Objects/funcobject.c"

        def __init__(self, f):
            self.f = f

        def __get__(self, obj, cls=None):
            if cls is None:
                cls = type(obj)
            if hasattr(obj, '__get__'):
                return self.f.__get__(cls)
            return MethodType(self.f, cls)

.. testcode::
    :hide:

    # Verify the emulation works
    class T:
        @ClassMethod
        def cm(cls, x, y):
            return (cls, x, y)

.. doctest::
    :hide:

    >>> T.cm(11, 22)
    (<class 'T'>, 11, 22)

    # Also call it from an instance
    >>> t = T()
    >>> t.cm(11, 22)
    (<class 'T'>, 11, 22)

The code path for ``hasattr(obj, '__get__')`` was added in Python 3.9 and
makes it possible for :func:`classmethod` to support chained decorators.
For example, a classmethod and property could be chained together:

.. testcode::

    class G:
        @classmethod
        @property
        def __doc__(cls):
            return f'A doc for {cls.__name__!r}'

.. doctest::

    >>> G.__doc__
    "A doc for 'G'"


Member objects and __slots__
----------------------------

When a class defines ``__slots__``, it replaces instance dictionaries with a
fixed-length array of slot values.  From a user point of view that has
several effects:

1. Provides immediate detection of bugs due to misspelled attribute
assignments.  Only attribute names specified in ``__slots__`` are allowed:

.. testcode::

        class Vehicle:
            __slots__ = ('id_number', 'make', 'model')

.. doctest::

        >>> auto = Vehicle()
        >>> auto.id_nubmer = 'VYE483814LQEX'
        Traceback (most recent call last):
            ...
        AttributeError: 'Vehicle' object has no attribute 'id_nubmer'

2. Helps create immutable objects where descriptors manage access to private
attributes stored in ``__slots__``:

.. testcode::

    class Immutable:

        __slots__ = ('_dept', '_name')          # Replace the instance dictionary

        def __init__(self, dept, name):
            self._dept = dept                   # Store to private attribute
            self._name = name                   # Store to private attribute

        @property                               # Read-only descriptor
        def dept(self):
            return self._dept

        @property
        def name(self):                         # Read-only descriptor
            return self._name

.. doctest::

    >>> mark = Immutable('Botany', 'Mark Watney')
    >>> mark.dept
    'Botany'
    >>> mark.dept = 'Space Pirate'
    Traceback (most recent call last):
        ...
    AttributeError: can't set attribute
    >>> mark.location = 'Mars'
    Traceback (most recent call last):
        ...
    AttributeError: 'Immutable' object has no attribute 'location'

3. Saves memory.  On a 64-bit Linux build, an instance with two attributes
takes 48 bytes with ``__slots__`` and 152 bytes without.  This `flyweight
design pattern <https://en.wikipedia.org/wiki/Flyweight_pattern>`_ likely only
matters when a large number of instances are going to be created.

4. Blocks tools like :func:`functools.cached_property` which require an
instance dictionary to function correctly:

.. testcode::

    from functools import cached_property

    class CP:
        __slots__ = ()                          # Eliminates the instance dict

        @cached_property                        # Requires an instance dict
        def pi(self):
            return 4 * sum((-1.0)**n / (2.0*n + 1.0)
                           for n in reversed(range(100_000)))

.. doctest::

    >>> CP().pi
    Traceback (most recent call last):
      ...
    TypeError: No '__dict__' attribute on 'CP' instance to cache 'pi' property.

It is not possible to create an exact drop-in pure Python version of
``__slots__`` because it requires direct access to C structures and control
over object memory allocation.  However, we can build a mostly faithful
simulation where the actual C structure for slots is emulated by a private
``_slotvalues`` list.  Reads and writes to that private structure are managed
by member descriptors:

.. testcode::

    null = object()

    class Member:

        def __init__(self, name, clsname, offset):
            'Emulate PyMemberDef in Include/structmember.h'
            # Also see descr_new() in Objects/descrobject.c
            self.name = name
            self.clsname = clsname
            self.offset = offset

        def __get__(self, obj, objtype=None):
            'Emulate member_get() in Objects/descrobject.c'
            # Also see PyMember_GetOne() in Python/structmember.c
            value = obj._slotvalues[self.offset]
            if value is null:
                raise AttributeError(self.name)
            return value

        def __set__(self, obj, value):
            'Emulate member_set() in Objects/descrobject.c'
            obj._slotvalues[self.offset] = value

        def __delete__(self, obj):
            'Emulate member_delete() in Objects/descrobject.c'
            value = obj._slotvalues[self.offset]
            if value is null:
                raise AttributeError(self.name)
            obj._slotvalues[self.offset] = null

        def __repr__(self):
            'Emulate member_repr() in Objects/descrobject.c'
            return f'<Member {self.name!r} of {self.clsname!r}>'

The :meth:`type.__new__` method takes care of adding member objects to class
variables:

.. testcode::

    class Type(type):
        'Simulate how the type metaclass adds member objects for slots'

        def __new__(mcls, clsname, bases, mapping):
            'Emuluate type_new() in Objects/typeobject.c'
            # type_new() calls PyTypeReady() which calls add_methods()
            slot_names = mapping.get('slot_names', [])
            for offset, name in enumerate(slot_names):
                mapping[name] = Member(name, clsname, offset)
            return type.__new__(mcls, clsname, bases, mapping)

The :meth:`object.__new__` method takes care of creating instances that have
slots instead of an instance dictionary.  Here is a rough simulation in pure
Python:

.. testcode::

    class Object:
        'Simulate how object.__new__() allocates memory for __slots__'

        def __new__(cls, *args):
            'Emulate object_new() in Objects/typeobject.c'
            inst = super().__new__(cls)
            if hasattr(cls, 'slot_names'):
                empty_slots = [null] * len(cls.slot_names)
                object.__setattr__(inst, '_slotvalues', empty_slots)
            return inst

        def __setattr__(self, name, value):
            'Emulate _PyObject_GenericSetAttrWithDict() Objects/object.c'
            cls = type(self)
            if hasattr(cls, 'slot_names') and name not in cls.slot_names:
                raise AttributeError(
                    f'{type(self).__name__!r} object has no attribute {name!r}'
                )
            super().__setattr__(name, value)

        def __delattr__(self, name):
            'Emulate _PyObject_GenericSetAttrWithDict() Objects/object.c'
            cls = type(self)
            if hasattr(cls, 'slot_names') and name not in cls.slot_names:
                raise AttributeError(
                    f'{type(self).__name__!r} object has no attribute {name!r}'
                )
            super().__delattr__(name)

To use the simulation in a real class, just inherit from :class:`Object` and
set the :term:`metaclass` to :class:`Type`:

.. testcode::

    class H(Object, metaclass=Type):
        'Instance variables stored in slots'

        slot_names = ['x', 'y']

        def __init__(self, x, y):
            self.x = x
            self.y = y

At this point, the metaclass has loaded member objects for *x* and *y*::

    >>> from pprint import pp
    >>> pp(dict(vars(H)))
    {'__module__': '__main__',
     '__doc__': 'Instance variables stored in slots',
     'slot_names': ['x', 'y'],
     '__init__': <function H.__init__ at 0x7fb5d302f9d0>,
     'x': <Member 'x' of 'H'>,
     'y': <Member 'y' of 'H'>}

.. doctest::
    :hide:

    # We test this separately because the preceding section is not
    # doctestable due to the hex memory address for the __init__ function
    >>> isinstance(vars(H)['x'], Member)
    True
    >>> isinstance(vars(H)['y'], Member)
    True

When instances are created, they have a ``slot_values`` list where the
attributes are stored:

.. doctest::

    >>> h = H(10, 20)
    >>> vars(h)
    {'_slotvalues': [10, 20]}
    >>> h.x = 55
    >>> vars(h)
    {'_slotvalues': [55, 20]}

Misspelled or unassigned attributes will raise an exception:

.. doctest::

    >>> h.xz
    Traceback (most recent call last):
        ...
    AttributeError: 'H' object has no attribute 'xz'

.. doctest::
   :hide:

    # Examples for deleted attributes are not shown because this section
    # is already a bit lengthy.  We still test that code here.
    >>> del h.x
    >>> hasattr(h, 'x')
    False

    # Also test the code for uninitialized slots
    >>> class HU(Object, metaclass=Type):
    ...     slot_names = ['x', 'y']
    ...
    >>> hu = HU()
    >>> hasattr(hu, 'x')
    False
    >>> hasattr(hu, 'y')
    False
