Background
Understanding descriptors
class Employee:
def __init__(self, name):
self.name = name
emp = Employee("Aniket")
print(emp.name)
class Name:
class Name:
def __set__(self, instance, value):
print("Invoking __set__ on Name")
if not isinstance(instance, Employee):
raise ValueError("Name descriptor is to be used with Employee instance only")
if len(value) < 1 or len(value) > 10:
raise ValueError("Name cannot be less than 1 char or more than 10 char")
instance._name = value
def __get__(self, instance, owner):
print("Invoking __get__ on Name")
if not isinstance(instance, Employee):
raise ValueError("Name descriptor is to be used with Employee instance only")
return instance._name
class Employee:
name = Name()
def __init__(self, name):
self._name = None
self.name = name
emp = Employee("")
print(emp.name)
emp = Employee("Aniket")
print(emp.name)
emp.name = "Abhijit"
print(emp.name)
- "Aniket" - Works fine. print Aniket
- "" - Fails & prints ValueError: Name cannot be less than 1 char or more than 10 char
- "Aniket Thakur" & prints ValueError: Name cannot be less than 1 char or more than 10 char
Descriptor protocol
__get__(self, obj, type=None) -> value
__set__(self, obj, value) -> None
__delete__(self, obj) -> None
- If an object defines __set__() or __delete__() , it is considered a data descriptor.
- Descriptors that only define __get__() are called non-data descriptors
class Name:
def __get__(self, instance, owner):
print("Invoking __get__ on Name")
if not isinstance(instance, Employee):
raise ValueError("Name descriptor is to be used with Employee instance only")
return instance._name
class Employee:
name = Name()
def __init__(self, name):
self._name = name
emp = Employee("Aniket")
print(emp.name)
emp.name = "Abhijit"
print(emp.name)
class Name:
def __get__(self, instance, owner):
print("Invoking __get__ on Name")
if not isinstance(instance, Employee):
raise ValueError("Name descriptor is to be used with Employee instance only")
return instance._name
def __delete__(self, instance):
del instance._name
class Employee:
name = Name()
def __init__(self, name):
self._name = name
emp = Employee("Aniket")
print(emp.name)
emp.name = "Abhijit"
print(emp.name)
