Descriptor: A descriptor is a special object in Python that lets you control what happens when you get, set, or delete an attribute on a class.
All in all they helps us to customize attribute access and behavior
e.g.
__get__(self, obj, objtype=None)
__set__(self, obj, value)
__delete__(self, obj)
__get_name__
Descriptors are the core behind:
@property
@staticmethod
@classmethod
and any custom attribute access logic!
There are two types of Descriptors
- Non-data Descriptors
class Q:
def __get__(self, instance, owner):
return "Yes"
class P:
attr = Q()
p = P()
print(p.attr) # Output: Yes
- Data Descriptors
class X:
def __get__(self, obj, objcls):
print(f"Getting value from {obj=} of type {objcls=}")
if obj:
return getattr(obj, "_find_x", "Nothing here")
return getattr(objcls, "_find_x", "Nothing here")
def __set__(self, obj, value):
print(f"Setting {value=} on {obj=}")
setattr(obj, "_find_x", value)
def __delete__(self, obj):
print(f"Deleting {obj} from find_x")
delattr(obj, "_find_x")
class P:
attr = X()
def __init__(self, value):
self.attr = value
print(P.attr) # Output: Getting value from obj=None of type objcls=<class '__main__.P'>
# Nothing here
p = P(15) # Output: Setting value=15 on obj=<__main__.P object at 0x7e8eaded1d00>
print(p.attr) # Output: Getting value from obj=<__main__.P object at 0x7e8eaded1d00> of type objcls=<class '__main__.P'>
# 15
print(p.__dict__) # {'_find_x': 15}
print(del p.attr) # Output: Deleting <__main__.P object at 0x7d4a4bcd5d00> from find_x
Bonus:
__dict__
: It basically tells the attributes of the class in dictionary format.
It has two types:
-
Class Attributes: Attributes defined directly within a class are stored in class's
__dict__
.
class Q:
a = 98
q = Q()
print(q.__dict__) # Output: {}
print(q.a) # Output: 98
print(Q.__dict__) # Output: {..., 'a': 98, ...other attributes}
-
Instance Attributes: Each instance has its own
__dict__
that stores attributes unique to that instance.
class Q:
def __init__(self):
self.a = 98
q = Q()
print(q.__dict__) # Output: {'a': 98}
q.x = 23
print(q.__dict__) # Output: {'a': 98, 'x': 23}
print(Q.__dict__) # Output: {<will not contain a or x>}
Top comments (0)