Is the example of the descriptor protocol in the Python 3.6 documentation incorrect?

2024/10/7 20:28:38

I am new to Python and looking through its documentation I encountered the following example of the descriptor protocol that in my opinion is incorrect. .

It looks like

class IntField:def __get__(self, instance, owner):return instance.__dict__[self.name]def __set__(self, instance, value):if not isinstance(value, int):raise ValueError(f'expecting integer in {self.name}')instance.__dict__[self.name] = value# this is the new initializer:def __set_name__(self, owner, name):self.name = nameclass Model:int_field = IntField()

Here are my considerations.

The attribute int_field is a class-wide attribute is not it?

So owner.__dict__ will have such a key. However in the method __get__ there is used instance.__dict__ that does not have that key. So from the point of view of using the method the method does not deal with the class-wide attribute but deals with an instance-wide attribute.

On the other hand, the method __set__ also does not deal with the class-wide attribute but creates an instance-wide attribute because there is used

instance.__dict__[self.name] = value

So it looks like each instance of the class creates its own instance-wide attribute. Moreover a reference to the class even is not passed to the method.

Am I right or do I have missed something that I do not know yet?

To make my considerations more clear the example logically is equivalent to the following

class MyClass:int_field = 10instance_of = MyClass();instance_of.__dict__["int_field"] = 20print( MyClass.int_field )
print( instance_of.int_field )

The program output is

10
20

The instance attribute int_field has nothing common with the class-wide attribute int_field except its name.

The same is true for the example from the documentation. Intuitively one can expect that it is the class-wide attribute that is attached to the descriptor. However it is not true. The descriptor just borrows the name of the class-wide attribute. On the other hand, a class-wide attribute can indeed be attached to a descriptor.

So the example from the documentation in my opinion just confuses readers.

Answer

The example is fine.

However in the method __get__ there is used instance.__dict__ that does not have that key.

There will be such a key once you actually set instance.int_field, which will invoke the property setter and assign the key.

On the other hand, the method __set__ also does not deal with the class-wide attribute but creates an instance-wide attribute

The setter isn't supposed to create a class attribute. It assigns to the instance dict key the getter is looking for.

https://en.xdnf.cn/q/118785.html

Related Q&A

How to clean a string to get value_counts for words of interest by date?

I have the following data generated from a groupby(Datetime) and value_counts()Datetime 0 01/01/2020 Paul 803 2 01/02/2020 Paul 210982360967 1 …

Folium - Map doesnt appear

I try to get map through Folium but only thing I can see is marker on blank page. Id like to know where is problem lies, in explorer or coding. map.py import foliummap = folium.Map(location = [46.20, 6…

python tkinter exe built with cx_Freeze for windows wont show GUI

PROBLEM SOLVED. the issue was with jaraco module, that i used for clipboard manipulation, i used pyperclip instead.I made a python app with tkinter that works fine, but I wanted to make an exe from it …

lxml tree connection and properties

I have a .dtsx file so, I have multiple components with connections, so I need to extract component that have especific connection, but I can not handle that, example: <components><component r…

Python recursive function call with if statement

I have a question regarding function-calls using if-statements and recursion. I am a bit confused because python seems to jump into the if statements block even if my function returns "False"…

How can I list all 1st row values in an Excel spreadsheet using OpenPyXL?

Using the OpenPyXL module with Python 3.5, I was able to figure out how many columns there are in a spreadsheet with:In [1]: sheet.max_column Out [1]: 4Then I was able to list the values in each of the…

Using matplotlib on non-0 MPI rank causes QXcbConnection: Could not connect to display

I have written a program that uses mpi4py to do some job (making an array) in the node of rank 0 in the following code. Then it makes another array in the node of rank 1. Then I plot both the arrays. T…

ioerror errno 13 permission denied: C:\\pagefile.sys

Below is my code, what I am trying to achieve is walking through the OS generating a MD5 hash of every file the code is functional, however, I receive the error in the title "ioerror errno 13 perm…

How can PyUSB be understood? [closed]

Its difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying thi…

Resize image in python without using resize() - nearest neighbor

For an assignment I want to resize a .jpg image with a python code, but without using the pil.image.resize() function or another similar function. I want to write the code myself but I cant figure out …