"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "Doc/howto/descriptor.rst" between
Python-3.9.3.tar.xz and Python-3.9.4.tar.xz

About: Python is an interpreted, interactive, object-oriented programming language. It incorporates modules, exceptions, dynamic typing, very high level dynamic data types, and classes. Newest major release.

descriptor.rst  (Python-3.9.3.tar.xz):descriptor.rst  (Python-3.9.4.tar.xz)
skipping to change at line 114 skipping to change at line 114
An interactive session shows that the lookup is dynamic — it computes An interactive session shows that the lookup is dynamic — it computes
different, updated answers each time:: different, updated answers each time::
>>> s = Directory('songs') >>> s = Directory('songs')
>>> g = Directory('games') >>> g = Directory('games')
>>> s.size # The songs directory has twenty fil es >>> s.size # The songs directory has twenty fil es
20 20
>>> g.size # The games directory has three file s >>> g.size # The games directory has three file s
3 3
>>> open('games/newfile').close() # Add a fourth file to the directory >>> os.remove('games/chess') # Delete a game
>>> g.size # File count is automatically update d >>> g.size # File count is automatically update d
4 2
Besides showing how descriptors can run computations, this example also Besides showing how descriptors can run computations, this example also
reveals the purpose of the parameters to :meth:`__get__`. The *self* reveals the purpose of the parameters to :meth:`__get__`. The *self*
parameter is *size*, an instance of *DirectorySize*. The *obj* parameter is parameter is *size*, an instance of *DirectorySize*. The *obj* parameter is
either *g* or *s*, an instance of *Directory*. It is the *obj* parameter that either *g* or *s*, an instance of *Directory*. It is the *obj* parameter that
lets the :meth:`__get__` method learn the target directory. The *objtype* lets the :meth:`__get__` method learn the target directory. The *objtype*
parameter is the class *Directory*. parameter is the class *Directory*.
Managed attributes Managed attributes
------------------ ------------------
skipping to change at line 277 skipping to change at line 277
.. doctest:: .. doctest::
>>> pete = Person('Peter P', 10) >>> pete = Person('Peter P', 10)
INFO:root:Updating 'name' to 'Peter P' INFO:root:Updating 'name' to 'Peter P'
INFO:root:Updating 'age' to 10 INFO:root:Updating 'age' to 10
>>> kate = Person('Catherine C', 20) >>> kate = Person('Catherine C', 20)
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}
>>> vars(kate) >>> vars(kate)
{'_name': 'Catherine C', '_age': 20} {'_name': 'Catherine C', '_age': 20}
Closing thoughts Closing thoughts
---------------- ----------------
A :term:`descriptor` is what we call any object that defines :meth:`__get__`, A :term:`descriptor` is what we call any object that defines :meth:`__get__`,
skipping to change at line 692 skipping to change at line 694
def getattr_hook(obj, name): def getattr_hook(obj, name):
"Emulate slot_tp_getattr_hook() in Objects/typeobject.c" "Emulate slot_tp_getattr_hook() in Objects/typeobject.c"
try: try:
return obj.__getattribute__(name) return obj.__getattribute__(name)
except AttributeError: except AttributeError:
if not hasattr(type(obj), '__getattr__'): if not hasattr(type(obj), '__getattr__'):
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) .
Also, if a user calls :meth:`object.__getattribute__` directly, the Also, if a user calls :meth:`object.__getattribute__` directly, the
:meth:`__getattr__` hook is bypassed entirely. :meth:`__getattr__` hook is bypassed entirely.
Invocation from a class Invocation from a class
----------------------- -----------------------
The logic for a dotted lookup such as ``A.x`` is in The logic for a dotted lookup such as ``A.x`` is in
skipping to change at line 1101 skipping to change at line 1134
>>> d.f.__func__ >>> d.f.__func__
<function D.f at 0x00C45070> <function D.f at 0x00C45070>
>>> d.f.__self__ >>> d.f.__self__
<__main__.D object at 0x1012e1f98> <__main__.D object at 0x1012e1f98>
If you have ever wondered where *self* comes from in regular methods or where 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.
To recap, functions have a :meth:`__get__` method so that they can be converted To recap, functions have a :meth:`__get__` method so that they can be converted
to a method when accessed as attributes. The non-data descriptor transforms an to a method when accessed as attributes. The non-data descriptor transforms an
``obj.f(*args)`` call into ``f(obj, *args)``. Calling ``cls.f(*args)`` ``obj.f(*args)`` call into ``f(obj, *args)``. Calling ``cls.f(*args)``
becomes ``f(*args)``. becomes ``f(*args)``.
This chart summarizes the binding and its two most useful variants: This chart summarizes the binding and its two most useful variants:
skipping to change at line 1154 skipping to change at line 1187
``Sample.erf(1.5) --> .9332``. ``Sample.erf(1.5) --> .9332``.
Since static methods return the underlying function with no changes, the Since static methods return the underlying function with no changes, the
example calls are unexciting: example calls are unexciting:
.. testcode:: .. testcode::
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"
def __init__(self, f): def __init__(self, f):
self.f = f self.f = f
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
------------- -------------
Unlike static methods, class methods prepend the class reference to the Unlike static methods, class methods prepend the class reference to the
argument list before calling the function. This format is the same argument list before calling the function. This format is the same
for whether the caller is an object or a class: for whether the caller is an object or a class:
.. testcode:: .. testcode::
class F: class F:
 End of changes. 10 change blocks. 
8 lines changed or deleted 58 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)