Code Explanation
๐น 1️⃣ Defining Descriptor Class D
class D:
Creates a class D
This class will act as a descriptor
๐น 2️⃣ Defining __get__
def __get__(self, obj, objtype):
return 100
Called when attribute is accessed
Always returns 100
Parameters:
obj → instance (a)
objtype → class (A)
๐น 3️⃣ Defining __set__
def __set__(self, obj, value):
obj.__dict__['x'] = value
Called when attribute is assigned
Stores value in instance dictionary
Example:
a.x = 5
would store:
a.__dict__['x'] = 5
๐น 4️⃣ Defining Class A
class A:
Creates class A
๐น 5️⃣ Assigning Descriptor to Class Attribute
x = D()
x is now a descriptor object
Stored in class A
Internally:
A.x → descriptor
๐น 6️⃣ Creating Object
a = A()
Creates instance a
Initially:
a.__dict__ = {}
๐น 7️⃣ Directly Modifying Instance Dictionary
a.__dict__['x'] = 5
Now:
a.__dict__ = {'x': 5}
⚠ Important:
This bypasses __set__
Still creates an instance attribute
๐น 8️⃣ Accessing a.x
print(a.x)
Now Python performs attribute lookup.
๐ Lookup Order
Python checks in this order:
1️⃣ Data descriptor → ✅ FOUND
2️⃣ Instance dictionary → skipped
3️⃣ Class → skipped
๐น 9️⃣ Descriptor Takes Control
Since x is a data descriptor, Python calls:
D.__get__(descriptor, a, A)
Inside:
return 100
๐น ๐ฅ Important Observation
Even though:
a.__dict__['x'] = 5
It is ignored because:
๐ Data descriptor has higher priority
Final Output:
100

0 Comments:
Post a Comment