sue remain exceptprint("can' set sue remain"trysue acct ' exceptprint('bad acct for sue'here is the output of our self-test code on both python and xagainthis is the same for all versions of this exampleexcept for the tested class' name trace through this code to see how the class' methods are invokedaccounts are displayed with some digits hiddennames are converted to standard formatand time remaining until retirement is computed when fetched using class attribute cutoffc:\codepy - validate_tester py validate_properties [using **bob_smith main st **bob_q _smith main st **sue_jones main st bad age for sue can' set sue remain bad acct for sue using descriptors to validate nowlet' recode our example using descriptors instead of properties as we've seendescriptors are very similar to properties in terms of functionality and rolesin factproperties are basically restricted form of descriptor like propertiesdescriptors are designed to handle specific attributesnot generic attribute access unlike propertiesdescriptors can also have their own stateand are more general scheme option validating with shared descriptor instance state to understand the following codeit' again important to notice that the attribute assignments inside the __init__ constructor method trigger descriptor __set__ methods when the constructor method assigns to self namefor exampleit automatically invokes the name __set__(methodwhich transforms the value and assigns it to descriptor attribute called name in the endthis class implements the same attributes as the prior versionit manages attributes called nameageand acctallows the attribute addr to be accessed directlyand provides read-only attribute called remain that is entirely virtual and computed on demand notice how we must catch assignments to the remain name in its descriptor and raise an exceptionas we learned earlierif we did not do thisassigning to this attribute of an instance would silently create an instance attribute that hides the class attribute descriptor exampleattribute validations