mirror of
https://github.com/python/cpython.git
synced 2025-07-25 20:24:11 +00:00
Add more tests for the descriptor tutorial (GH-25164)
This commit is contained in:
parent
b2a91e0c9e
commit
e4c8895ee5
1 changed files with 57 additions and 7 deletions
|
@ -281,7 +281,9 @@ The new class now logs access to both *name* and *age*:
|
||||||
INFO:root:Updating 'name' to 'Catherine C'
|
INFO:root:Updating 'name' to 'Catherine C'
|
||||||
INFO:root:Updating 'age' to 20
|
INFO:root:Updating 'age' to 20
|
||||||
|
|
||||||
The two *Person* instances contain only the private names::
|
The two *Person* instances contain only the private names:
|
||||||
|
|
||||||
|
.. doctest::
|
||||||
|
|
||||||
>>> vars(pete)
|
>>> vars(pete)
|
||||||
{'_name': 'Peter P', '_age': 10}
|
{'_name': 'Peter P', '_age': 10}
|
||||||
|
@ -710,6 +712,38 @@ perform attribute lookup by way of a helper function:
|
||||||
raise
|
raise
|
||||||
return type(obj).__getattr__(obj, name) # __getattr__
|
return type(obj).__getattr__(obj, name) # __getattr__
|
||||||
|
|
||||||
|
.. doctest::
|
||||||
|
:hide:
|
||||||
|
|
||||||
|
|
||||||
|
>>> class ClassWithGetAttr:
|
||||||
|
... x = 123
|
||||||
|
... def __getattr__(self, attr):
|
||||||
|
... return attr.upper()
|
||||||
|
...
|
||||||
|
>>> cw = ClassWithGetAttr()
|
||||||
|
>>> cw.y = 456
|
||||||
|
>>> getattr_hook(cw, 'x')
|
||||||
|
123
|
||||||
|
>>> getattr_hook(cw, 'y')
|
||||||
|
456
|
||||||
|
>>> getattr_hook(cw, 'z')
|
||||||
|
'Z'
|
||||||
|
|
||||||
|
>>> class ClassWithoutGetAttr:
|
||||||
|
... x = 123
|
||||||
|
...
|
||||||
|
>>> cwo = ClassWithoutGetAttr()
|
||||||
|
>>> cwo.y = 456
|
||||||
|
>>> getattr_hook(cwo, 'x')
|
||||||
|
123
|
||||||
|
>>> getattr_hook(cwo, 'y')
|
||||||
|
456
|
||||||
|
>>> getattr_hook(cwo, 'z')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
AttributeError: 'ClassWithoutGetAttr' object has no attribute 'z'
|
||||||
|
|
||||||
So if :meth:`__getattr__` exists, it is called whenever :meth:`__getattribute__`
|
So if :meth:`__getattr__` exists, it is called whenever :meth:`__getattribute__`
|
||||||
raises :exc:`AttributeError` (either directly or in one of the descriptor calls).
|
raises :exc:`AttributeError` (either directly or in one of the descriptor calls).
|
||||||
|
|
||||||
|
@ -1139,8 +1173,8 @@ If you have ever wondered where *self* comes from in regular methods or where
|
||||||
*cls* comes from in class methods, this is it!
|
*cls* comes from in class methods, this is it!
|
||||||
|
|
||||||
|
|
||||||
Other kinds of methods
|
Kinds of methods
|
||||||
----------------------
|
----------------
|
||||||
|
|
||||||
Non-data descriptors provide a simple mechanism for variations on the usual
|
Non-data descriptors provide a simple mechanism for variations on the usual
|
||||||
patterns of binding functions into methods.
|
patterns of binding functions into methods.
|
||||||
|
@ -1193,19 +1227,19 @@ example calls are unexciting:
|
||||||
class E:
|
class E:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def f(x):
|
def f(x):
|
||||||
print(x)
|
return x * 10
|
||||||
|
|
||||||
.. doctest::
|
.. doctest::
|
||||||
|
|
||||||
>>> E.f(3)
|
>>> E.f(3)
|
||||||
3
|
30
|
||||||
>>> E().f(3)
|
>>> E().f(3)
|
||||||
3
|
30
|
||||||
|
|
||||||
Using the non-data descriptor protocol, a pure Python version of
|
Using the non-data descriptor protocol, a pure Python version of
|
||||||
:func:`staticmethod` would look like this:
|
:func:`staticmethod` would look like this:
|
||||||
|
|
||||||
.. doctest::
|
.. testcode::
|
||||||
|
|
||||||
class StaticMethod:
|
class StaticMethod:
|
||||||
"Emulate PyStaticMethod_Type() in Objects/funcobject.c"
|
"Emulate PyStaticMethod_Type() in Objects/funcobject.c"
|
||||||
|
@ -1216,6 +1250,22 @@ Using the non-data descriptor protocol, a pure Python version of
|
||||||
def __get__(self, obj, objtype=None):
|
def __get__(self, obj, objtype=None):
|
||||||
return self.f
|
return self.f
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
:hide:
|
||||||
|
|
||||||
|
class E_sim:
|
||||||
|
@StaticMethod
|
||||||
|
def f(x):
|
||||||
|
return x * 10
|
||||||
|
|
||||||
|
.. doctest::
|
||||||
|
:hide:
|
||||||
|
|
||||||
|
>>> E_sim.f(3)
|
||||||
|
30
|
||||||
|
>>> E_sim().f(3)
|
||||||
|
30
|
||||||
|
|
||||||
|
|
||||||
Class methods
|
Class methods
|
||||||
-------------
|
-------------
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue