Code Explanation:
1. Defining the Descriptor Class
class D:
Creates a class D
This class is meant to act as a descriptor
๐น 2. Implementing the __get__ Method
def __get__(self, obj, objtype):
return 99
__get__ controls attribute access
Called whenever x is read (a.x)
Always returns 99
Parameters:
self → descriptor object
obj → instance accessing the attribute (a)
objtype → owner class (A)
๐น 3. Implementing the __set__ Method
def __set__(self, obj, value):
pass
__set__ controls attribute assignment
Called when a.x = 5
pass means do nothing
No instance attribute is created
๐ Important:
Having __set__ makes this a DATA DESCRIPTOR.
๐น 4. Why This Is a Data Descriptor (Very Important)
A descriptor that defines:
__get__ and/or __set__
is a DATA DESCRIPTOR
๐ Data descriptors have higher priority than:
Instance attributes
Non-data descriptors
๐น 5. Defining Class A
class A:
x = D()
x is a class attribute
Value is an instance of D
Since D is a data descriptor, x is managed by the descriptor
๐น 6. Creating an Instance of A
a = A()
Creates object a
a.__dict__ is empty at this point
๐น 7. Assigning to a.x
a.x = 5
What happens internally:
Python sees assignment to x
Finds that x is a data descriptor
Calls:
D.__set__(x_descriptor, a, 5)
__set__ does nothing (pass)
No instance attribute is created
๐ So a.__dict__ still does not contain x
๐น 8. Accessing a.x
print(a.x)
Attribute lookup order:
Data descriptor → ✅ found
Instance dictionary → skipped
Class attributes → skipped
Python calls:
D.__get__(x_descriptor, a, A)
Which returns 99
✅ Final Output
99

0 Comments:
Post a Comment