python document reading descriptor HowTo

https://docs.python.org/ja/3/howto/descriptor.html This is a memo when I read this. Since it is a dump of the brain while reading, it is recommended that those who simply want to know the contents read the document directly. python3.8.2

Why reading the docs

――I want to read the document here and know the functions that are actually useful to use without knowing it. ――It's been about 8 years since I started using python, but I'm doing it in an atmosphere, so there are still some features I don't know. --In python, outer class cannot be seen from inner class - https://blog.hirokiky.org/entry/2013/12/25/000000 --But you can make it visible by changing the descriptor --Stackoverflow mentioned in the above blog: https://stackoverflow.com/questions/2278426/inner-classes-how-can-i-get-the-outer-class-object-at-construction-time ――I didn't understand why this hit, so I read what a descriptor is.

Overview

--About the python descriptor

Definition and introduction

In general, a descriptor is an object attribute that has a "binding behavior" whose attribute access is overridden by a method of the descriptor protocol.

――What is it? Probably a good expression that is concise and organized when you see it after understanding it, but when you don't understand it, it looks like a spell.

The default behavior of attribute access is that ʻa.x becomes ʻa.__dict__ ['x']. The range to look for is the base class excluding the metaclass. If the found object has a descriptor method, it overrides the default behavior and calls the descriptor method instead. Is it like this in the image?

Image getattr.py


def getattr(a, name):
  _x = a.__dict__[name]
  if hasattr(_x, '__get__'):
    return _x.__get__()
  return _x

Descriptor protocol

――All of the following three

descr.__get__(self, obj, type=None) -> value
descr.__set__(self, obj, value) -> None
descr.__delete__(self, obj) -> None

--If there are data descriptors and non-data descriptors, and there is an item with the same name as the descriptor in the dictionary at the time of override, the descriptor is prioritized / the dictionary is prioritized, respectively. ――What is a data descriptor? --I feel that it can be read not only by the object you are looking for, but also by the method itself such as _get _.

Call descriptor

--When called --When called directly: d.__get__ (obj) --When accessing attributes: ʻobj.d` --A similar example came out ――It's a little different, but it seems that the general understanding is correct

An example similar to the above.py


def __getattribute__(self, key):
    "Emulate type_getattro() in Objects/typeobject.c"
    v = object.__getattribute__(self, key)
    if hasattr(v, '__get__'):
        return v.__get__(None, self)
    return v

--The actual implementation is here

--The important thing to remember is: --Descriptors are called by the \ _ \ _ getattribute \ _ \ _ () method -Overriding \ _ \ _ getattribute \ _ \ _ () prevents automatic descriptor invocation --Object. \ _ \ _ Getattribute \ _ \ _ () and type. \ _ \ _ Getattribute \ _ \ _ () call \ _ \ _ get \ _ \ _ () differently. --The data descriptor always overrides the instance dictionary. --Non-data descriptors may be overridden by the instance dictionary.

--In short, it usually has a value in \ _ \ _dict \ _ \ _ of the object to which it belongs, using itself as a key, but if you want to do it, define \ _ \ _ get \ _ \ _ to call it in another way. Is it possible to override the behavior by doing so?

Example

Sink

Property

--Understand the behavior of data descriptor calls from objects --There is also a small usage example

Functions and methods

--This is the behavior of non-data descriptors --A function / method is a non-data descriptor? --The method defined in the class is a non-data descriptor whose first argument is a special function limited to objects. --self It's customary, but just the first argument --When called from an object, call a partially applied function with the object itself in self --When called from a class, the first argument is required because the function is returned normally. --In the example, some variables that function objects have by default were introduced. -\ _ \ _dict \ _ \ _: A dictionary of attribute names and values that the object has, which appears many times. -\ _ \ _ qualname \ _ \ _: Full name when called ("D.f"when called with e.g. D.f) -\ _ \ _ func \ _ \ _: Original function. Even if it is called from an object, the first argument self is required. -\ _ \ _ self \ _ \ _: Object assigned to self -\ _ \ _ class \ _ \ _: The class of the object that has this variable

Static and class methods

――I've come to understand it somehow because I've come to understand it a lot.

Converts calls to obj.f (* args) to f (obj, * args). Calling klass.f (* args) results in f (* args)

--Methods normally defined in the class without any annotation f (self, * args) - obj.f(*args)f(obj, *args) - klass.f(*args)f(*args) --Static method (@staticmethod): Return as is --Both are f (* args) --Class method (@classmethod) - obj.f(*args)f(type(obj), *args) - klass.f(*args)f(klass, *args) --In other words, the difference between ordinary methods, static methods, and class methods must be bound. --If you want to do it, it seems possible to return a plain function when referenced from obj, and return a function bound to klass when referencing from klass. ――I can't think of any merits, --Static methods define the function you want to use without bounding anything --Class methods are always used when you want to bounce the class --As an example, a custom constructor came out (dict.fromkeys)

Impressions

--Shortly after I started touching python, I remembered that I misunderstood that writing self as the first argument of a method in a class would be a normal method and writing cls would be a class method. ――I know that this is not the case now, but I understood the concrete behavior for the first time. ――I thought that an object is to manage various dictionaries in a nice way. --The original question is that the outer class cannot be seen from the inner class because the inner class \ _ \ _dict \ _ \ _ does not contain the outer class. ――I understand that it was OK if you override the descriptor with the class decorator and put it in. ――Click here for the solid bounded inner class recipe mentioned in the blog quoted at the beginning. - http://code.activestate.com/recipes/577070-bound-inner-classes/

Recommended Posts

python document reading descriptor HowTo
python descriptor
python documentation reading socket programming HOWTO
Python here document
[Note] File reading ~ Python ~
Reading pyc file (Python 3.5.2)
python external file reading
[Python] Reading CSV files
Reading .txt files with Python
Document Python code with Doxygen
python dict object memorandum (mysterious document)
Python CSV file reading and writing
Reading and writing NetCDF with Python
Multi-line size specification reading with python
Reading and writing CSV with Python
Reading and writing text in Python