Skip to content

Commit e4c8895

Browse files
authored
Add more tests for the descriptor tutorial (GH-25164)
1 parent b2a91e0 commit e4c8895

File tree

1 file changed

+57
-7
lines changed

1 file changed

+57
-7
lines changed

Doc/howto/descriptor.rst

+57-7
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,9 @@ The new class now logs access to both *name* and *age*:
281281
INFO:root:Updating 'name' to 'Catherine C'
282282
INFO:root:Updating 'age' to 20
283283

284-
The two *Person* instances contain only the private names::
284+
The two *Person* instances contain only the private names:
285+
286+
.. doctest::
285287

286288
>>> vars(pete)
287289
{'_name': 'Peter P', '_age': 10}
@@ -710,6 +712,38 @@ perform attribute lookup by way of a helper function:
710712
raise
711713
return type(obj).__getattr__(obj, name) # __getattr__
712714

715+
.. doctest::
716+
:hide:
717+
718+
719+
>>> class ClassWithGetAttr:
720+
... x = 123
721+
... def __getattr__(self, attr):
722+
... return attr.upper()
723+
...
724+
>>> cw = ClassWithGetAttr()
725+
>>> cw.y = 456
726+
>>> getattr_hook(cw, 'x')
727+
123
728+
>>> getattr_hook(cw, 'y')
729+
456
730+
>>> getattr_hook(cw, 'z')
731+
'Z'
732+
733+
>>> class ClassWithoutGetAttr:
734+
... x = 123
735+
...
736+
>>> cwo = ClassWithoutGetAttr()
737+
>>> cwo.y = 456
738+
>>> getattr_hook(cwo, 'x')
739+
123
740+
>>> getattr_hook(cwo, 'y')
741+
456
742+
>>> getattr_hook(cwo, 'z')
743+
Traceback (most recent call last):
744+
...
745+
AttributeError: 'ClassWithoutGetAttr' object has no attribute 'z'
746+
713747
So if :meth:`__getattr__` exists, it is called whenever :meth:`__getattribute__`
714748
raises :exc:`AttributeError` (either directly or in one of the descriptor calls).
715749

@@ -1139,8 +1173,8 @@ If you have ever wondered where *self* comes from in regular methods or where
11391173
*cls* comes from in class methods, this is it!
11401174

11411175

1142-
Other kinds of methods
1143-
----------------------
1176+
Kinds of methods
1177+
----------------
11441178

11451179
Non-data descriptors provide a simple mechanism for variations on the usual
11461180
patterns of binding functions into methods.
@@ -1193,19 +1227,19 @@ example calls are unexciting:
11931227
class E:
11941228
@staticmethod
11951229
def f(x):
1196-
print(x)
1230+
return x * 10
11971231

11981232
.. doctest::
11991233

12001234
>>> E.f(3)
1201-
3
1235+
30
12021236
>>> E().f(3)
1203-
3
1237+
30
12041238

12051239
Using the non-data descriptor protocol, a pure Python version of
12061240
:func:`staticmethod` would look like this:
12071241

1208-
.. doctest::
1242+
.. testcode::
12091243

12101244
class StaticMethod:
12111245
"Emulate PyStaticMethod_Type() in Objects/funcobject.c"
@@ -1216,6 +1250,22 @@ Using the non-data descriptor protocol, a pure Python version of
12161250
def __get__(self, obj, objtype=None):
12171251
return self.f
12181252

1253+
.. testcode::
1254+
:hide:
1255+
1256+
class E_sim:
1257+
@StaticMethod
1258+
def f(x):
1259+
return x * 10
1260+
1261+
.. doctest::
1262+
:hide:
1263+
1264+
>>> E_sim.f(3)
1265+
30
1266+
>>> E_sim().f(3)
1267+
30
1268+
12191269

12201270
Class methods
12211271
-------------

0 commit comments

Comments
 (0)