summaryrefslogtreecommitdiffstats
path: root/Doc/howto
diff options
context:
space:
mode:
authorRaymond Hettinger <rhettinger@users.noreply.github.com>2021-04-03 20:07:52 (GMT)
committerGitHub <noreply@github.com>2021-04-03 20:07:52 (GMT)
commite4c8895ee5457b11f52841b79b51f3c3d6373fef (patch)
tree418191e654435cfaa3b2972eb4d3470ea16c63d1 /Doc/howto
parentb2a91e0c9ee18b50cc86b21211c2258520a9f5d0 (diff)
downloadcpython-e4c8895ee5457b11f52841b79b51f3c3d6373fef.zip
cpython-e4c8895ee5457b11f52841b79b51f3c3d6373fef.tar.gz
cpython-e4c8895ee5457b11f52841b79b51f3c3d6373fef.tar.bz2
Add more tests for the descriptor tutorial (GH-25164)
Diffstat (limited to 'Doc/howto')
-rw-r--r--Doc/howto/descriptor.rst64
1 files changed, 57 insertions, 7 deletions
diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst
index 420d9b9..819401e 100644
--- a/Doc/howto/descriptor.rst
+++ b/Doc/howto/descriptor.rst
@@ -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 'age' to 20
-The two *Person* instances contain only the private names::
+The two *Person* instances contain only the private names:
+
+.. doctest::
>>> vars(pete)
{'_name': 'Peter P', '_age': 10}
@@ -710,6 +712,38 @@ perform attribute lookup by way of a helper function:
raise
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__`
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!
-Other kinds of methods
-----------------------
+Kinds of methods
+----------------
Non-data descriptors provide a simple mechanism for variations on the usual
patterns of binding functions into methods.
@@ -1193,19 +1227,19 @@ example calls are unexciting:
class E:
@staticmethod
def f(x):
- print(x)
+ return x * 10
.. doctest::
>>> E.f(3)
- 3
+ 30
>>> E().f(3)
- 3
+ 30
Using the non-data descriptor protocol, a pure Python version of
:func:`staticmethod` would look like this:
-.. doctest::
+.. testcode::
class StaticMethod:
"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):
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
-------------