as for the property and descriptor versions of this exampleit' critical to notice that the attribute assignments inside the __init__ constructor method trigger the class' __setattr__ method too when this method assigns to self namefor exampleit automatically invokes the __setattr__ methodwhich transforms the value and assigns it to an instance attribute called name by storing name on the instanceit ensures that future accesses will not trigger __getattr__ in contrastacct is stored as _acctso that later accesses to acct do invoke __getattr__ in the endthis classlike the prior twomanages attributes called nameageand acctallows the attribute addr to be accessed directlyand provides read-only attribute called remain that is entirely virtual and is computed on demand for comparison purposesthis alternative comes in at lines of code-- fewer than the property-based versionand fewer than the version using descriptors clarity matters more than code sizeof coursebut extra code can sometimes imply extra development and maintenance work probably more important here are rolesgeneric tools like __getattr__ may be better suited to generic delegationwhile properties and descriptors are more directly designed to manage specific attributes also note that the code here incurs extra calls when setting unmanaged attributes ( addr)although no extra calls are incurred for fetching unmanaged attributessince they are defined though this will likely result in negligible overhead for most programsthe more narrowly focused properties and descriptors incur an extra call only when managed attributes are accessedand also appear in dir results when needed by generic tools here' the __getattr__ version of our validations codefile validate_getattr py class cardholderacctlen retireage def __init__(selfacctnameageaddr)self acct acct self name name self age age self addr addr def __getattr__(selfname)if name ='acct'return self _acct[:- '***elif name ='remain'return self retireage self age elseraise attributeerror(nameclass data instance data these trigger __setattr__ too _acct not mangledname tested addr is not managed remain has no data on undefined attr fetches nameageaddr are defined doesn' trigger __getattr__ def __setattr__(selfnamevalue)if name ='name'on all attr assignments value value lower(replace('' 'addr stored directly managed attributes