set_name is called when a descriptor is defined in a class. Receives the attribute name.
1class Validated:2 def __set_name__(self, owner, name):3 self.name = name4 self.private_name = f"_{name}"56 def __get__(self, obj, objtype=None):7 if obj is None:8 return self9 return getattr(obj, self.private_name, None)1011 def __set__(self, obj, value):12 if not isinstance(value, str):13 raise TypeError(f"{self.name} must be a string")14 setattr(obj, self.private_name, value)1516class User:17 name = Validated() # __set_name__ called with "name"18 email = Validated() # __set_name__ called with "email"1920u = User()21u.name = "Alice" # Works22# u.name = 123 # TypeError: name must be a string2324# Without __set_name__ — need manual naming25class OldValidated:26 def __init__(self, name):27 self.name = name28 self.private_name = f"_{name}"2930class OldUser:31 name = OldValidated("name") # Manual!32 email = OldValidated("email")
Benefits: