Code Explanation:
1. Defining the descriptor class
class D:
This defines a class named D.
Objects of this class will be used as descriptors.
2. Implementing __get__
def __get__(self, obj, owner):
return "D"
__get__ makes D a descriptor.
Parameters:
self → the descriptor object (D()).
obj → the instance accessing the attribute (c).
owner → the class (C).
Whenever x is accessed, this method returns "D".
3. Implementing __set__
def __set__(self, obj, val):
pass
Presence of __set__ makes D a data descriptor.
Data descriptors have higher priority than instance attributes.
This method ignores assignments but still controls access.
4. Defining the owner class
class C:
This defines a class named C.
5. Assigning the descriptor
x = D()
x is a class attribute.
It is managed by the data descriptor D.
6. Creating an instance
c = C()
An object c of class C is created.
Initially, c.__dict__ is empty.
7. Manually inserting an instance attribute
c.__dict__['x'] = "I"
This directly adds an instance attribute x with value "I".
Normally, instance attributes override class attributes…
But not data descriptors.
8. Accessing the attribute
print(c.x)
๐ Attribute lookup order (important here):
Data descriptors
Instance attributes (c.__dict__)
Non-data descriptors
Class attributes
x is a data descriptor.
Python calls D.__get__ before checking c.__dict__.
The instance attribute "I" is ignored.
✅ Final Output
D

0 Comments:
Post a Comment