alternate approach that could do this for every attribute. However, this
descriptor is useful for monitoring just a few chosen attributes::
- class RevealAccess(object):
+ class RevealAccess:
"""A data descriptor that sets and returns values
normally and prints a message logging their access.
"""
print('Updating', self.name)
self.val = val
- >>> class MyClass(object):
+ >>> class MyClass:
... x = RevealAccess(10, 'var "x"')
... y = 5
...
The documentation shows a typical use to define a managed attribute ``x``::
- class C(object):
+ class C:
def getx(self): return self.__x
def setx(self, value): self.__x = value
def delx(self): del self.__x
To see how :func:`property` is implemented in terms of the descriptor protocol,
here is a pure Python equivalent::
- class Property(object):
+ class Property:
"Emulate PyProperty_Type() in Objects/descrobject.c"
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
affect existing client code accessing the attribute directly. The solution is
to wrap access to the value attribute in a property data descriptor::
- class Cell(object):
+ class Cell:
. . .
def getvalue(self):
"Recalculate the cell before returning value"
non-data descriptors which return bound methods when they are invoked from an
object. In pure Python, it works like this::
- class Function(object):
+ class Function:
. . .
def __get__(self, obj, objtype=None):
"Simulate func_descr_get() in Objects/funcobject.c"
Running the interpreter shows how the function descriptor works in practice::
- >>> class D(object):
+ >>> class D:
... def f(self, x):
... return x
...
Since staticmethods return the underlying function with no changes, the example
calls are unexciting::
- >>> class E(object):
+ >>> class E:
... def f(x):
... print(x)
... f = staticmethod(f)
Using the non-data descriptor protocol, a pure Python version of
:func:`staticmethod` would look like this::
- class StaticMethod(object):
+ class StaticMethod:
"Emulate PyStaticMethod_Type() in Objects/funcobject.c"
def __init__(self, f):
argument list before calling the function. This format is the same
for whether the caller is an object or a class::
- >>> class E(object):
+ >>> class E:
... def f(klass, x):
... return klass.__name__, x
... f = classmethod(f)
:func:`dict.fromkeys` creates a new dictionary from a list of keys. The pure
Python equivalent is::
- class Dict(object):
+ class Dict:
. . .
def fromkeys(klass, iterable, value=None):
"Emulate dict_fromkeys() in Objects/dictobject.c"
Using the non-data descriptor protocol, a pure Python version of
:func:`classmethod` would look like this::
- class ClassMethod(object):
+ class ClassMethod:
"Emulate PyClassMethod_Type() in Objects/funcobject.c"
def __init__(self, f):