--- descriptor.rst 2013-09-07 14:12:48.000000000 +0200 +++ descriptor_modified.rst 2013-09-21 14:52:00.698603196 +0200 @@ -145,27 +145,27 @@ alternate approach that could do this for every attribute. However, this descriptor is useful for monitoring just a few chosen attributes:: - class RevealAccess(object): - """A data descriptor that sets and returns values - normally and prints a message logging their access. - """ - - def __init__(self, initval=None, name='var'): - self.val = initval - self.name = name - - def __get__(self, obj, objtype): - print('Retrieving', self.name) - return self.val - - def __set__(self, obj, val): - print('Updating', self.name) - self.val = val - + >>> class RevealAccess(object): + ... """A data descriptor that sets and returns values + ... normally and prints a message logging their access. + ... """ + ... + ... def __init__(self, initval=None, name='var'): + ... self.val = initval + ... self.name = name + ... + ... def __get__(self, obj, objtype): + ... print('Retrieving', self.name) + ... return self.val + ... + ... def __set__(self, obj, val): + ... print('Updating', self.name) + ... self.val = val + ... >>> class MyClass(object): - x = RevealAccess(10, 'var "x"') - y = 5 - + ... x = RevealAccess(10, 'var "x"') + ... y = 5 + ... >>> m = MyClass() >>> m.x Retrieving var "x" @@ -287,15 +287,18 @@ Running the interpreter shows how the function descriptor works in practice:: >>> class D(object): - def f(self, x): - return x - - >>> d = D() + ... def f(self, x): + ... return x + ... + >>> d = D() >>> D.__dict__['f'] # Stored internally as a function + ... # doctest: +SKIP >>> D.f # Get from a class becomes an unbound method + ... # doctest: +SKIP >>> d.f # Get from an instance becomes a bound method + ... # doctest: +SKIP > The output suggests that bound and unbound methods are two different types. @@ -359,36 +362,38 @@ calls are unexciting:: >>> class E(object): - def f(x): - print(x) - f = staticmethod(f) + ... def f(x): + ... print(x) + ... f = staticmethod(f) >>> print(E.f(3)) 3 + None >>> print(E().f(3)) 3 + None Using the non-data descriptor protocol, a pure Python version of :func:`staticmethod` would look like this:: class StaticMethod(object): - "Emulate PyStaticMethod_Type() in Objects/funcobject.c" + "Emulate PyStaticMethod_Type() in Objects/funcobject.c" - def __init__(self, f): - self.f = f + def __init__(self, f): + self.f = f - def __get__(self, obj, objtype=None): - return self.f + def __get__(self, obj, objtype=None): + return self.f 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:: >>> class E(object): - def f(klass, x): - return klass.__name__, x - f = classmethod(f) - + ... def f(klass, x): + ... return klass.__name__, x + ... f = classmethod(f) + ... >>> print(E.f(3)) ('E', 3) >>> print(E().f(3)) @@ -413,22 +418,22 @@ Now a new dictionary of unique keys can be constructed like this:: - >>> Dict.fromkeys('abracadabra') + >>> Dict.fromkeys('abracadabra') # doctest: +SKIP {'a': None, 'r': None, 'b': None, 'c': None, 'd': None} Using the non-data descriptor protocol, a pure Python version of :func:`classmethod` would look like this:: class ClassMethod(object): - "Emulate PyClassMethod_Type() in Objects/funcobject.c" + "Emulate PyClassMethod_Type() in Objects/funcobject.c" - def __init__(self, f): - self.f = f + def __init__(self, f): + self.f = f - def __get__(self, obj, klass=None): - if klass is None: - klass = type(obj) - def newfunc(*args): - return self.f(klass, *args) - return newfunc + def __get__(self, obj, klass=None): + if klass is None: + klass = type(obj) + def newfunc(*args): + return self.f(klass, *args) + return newfunc