diff -r 8a364deb0225 Doc/howto/descriptor.rst --- a/Doc/howto/descriptor.rst Thu May 02 10:44:04 2013 -0700 +++ b/Doc/howto/descriptor.rst Thu May 02 21:53:42 2013 -0400 @@ -4,6 +4,7 @@ :Author: Raymond Hettinger :Contact: +:Release: 2.0 .. Contents:: @@ -23,25 +24,32 @@ Definition and Introduction --------------------------- -In general, a descriptor is an object attribute with "binding behavior", one -whose attribute access has been overridden by methods in the descriptor +A descriptor is an object that customizes how attributes behave. If an +object's attribute is defined as a descriptor, then looking up or setting the +value of the attribute will actually invoke special methods on the descriptor +instead. + +If this sounds like properties, that's because descriptors are what make +properties behave as they do. But descriptors can do much more than just +implement properties. + +A descriptor is any object with one of the special methods in the descriptor protocol. Those methods are :meth:`__get__`, :meth:`__set__`, and :meth:`__delete__`. If any of those methods are defined for an object, it is -said to be a descriptor. +a 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 base classes of ``type(a)`` excluding metaclasses. 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. +Typical 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 base classes of ``type(a)``. If the found value is an object +defining one of the descriptor methods, then Python will invoke a descriptor +method instead. Where this occurs in the precedence chain depends on which +descriptor methods are 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 to implement the new style classes -introduced in version 2.2. Descriptors simplify the underlying C-code and offer +introduced in version 2.2. Descriptors simplify the underlying C code and offer a flexible set of new tools for everyday Python programs. @@ -50,15 +58,26 @@ ``descr.__get__(self, obj, type=None) --> value`` +The :meth:`__get__` method is invoked when getting an attribute's value. The +values passed to it depends on whether the attribute was looked up on an object +or on a class. If looked up on an object, :meth:`__get__` is passed the object and the class +of the object. If looked up on a class, it is passed `None` and the class. The +value it returns will be used as the value of the attribute. + ``descr.__set__(self, obj, value) --> None`` +The :meth:`__set__` method is invoked when setting an attribute's value. +It is passed the object and the value to set. + ``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. +The :meth:`__delete__` method is invoked to delete the attribute, and is +passed the object. -If an object defines both :meth:`__get__` and :meth:`__set__`, it is considered +That is all there is to it. Define any of these methods and an object is a +descriptor and can override default behavior when found as an attribute. + +If an object defines both :meth:`__get__` and :meth:`__set__`, it is called a data descriptor. Descriptors that only define :meth:`__get__` are called non-data descriptors (they are typically used for methods but other uses are possible). @@ -78,10 +97,7 @@ Invoking Descriptors -------------------- -A descriptor can be called directly by its method name. For example, -``d.__get__(obj)``. - -Alternatively, it is more common for a descriptor to be invoked automatically +Descriptors are invoked automatically upon attribute access. For example, ``obj.d`` looks up ``d`` in the dictionary of ``obj``. If ``d`` defines the method :meth:`__get__`, then ``d.__get__(obj)`` is invoked according to the precedence rules listed below. @@ -262,7 +278,7 @@ Functions and Methods --------------------- -Python's object oriented features are built upon a function based environment. +Python's object oriented features are built upon a function-based environment. Using non-data descriptors, the two are merged seamlessly. Class dictionaries store methods as functions. In a class definition, methods