as mentioned earlierproperties and descriptors are strongly related--the property built-in is just convenient way to create descriptor now that you know how both workyou should also be able to see that it' possible to simulate the property built-in with descriptor class like the followingclass propertydef __init__(selffget=nonefset=nonefdel=nonedoc=none)self fget fget self fset fset self fdel fdel save unbound methods self __doc__ doc or other callables def __get__(selfinstanceinstancetype=none)if instance is nonereturn self if self fget is noneraise attributeerror("can' get attribute"return self fget(instancepass instance to self in property accessors def __set__(selfinstancevalue)if self fset is noneraise attributeerror("can' set attribute"self fset(instancevaluedef __delete__(selfinstance)if self fdel is noneraise attributeerror("can' delete attribute"self fdel(instanceclass persondef getname(self)print('getname 'def setname(selfvalue)print('setname 'name property(getnamesetnameuse like property( person( name name 'bobdel name this property class catches attribute accesses with the descriptor protocol and routes requests to functions or methods passed in and saved in descriptor state when the class is created attribute fetchesfor exampleare routed from the person classto the property class' __get__ methodand back to the person class' getname with descriptorsthis "just works" :\codepy - prop-desc-equiv py getname setname attributeerrorcan' delete attribute note that this descriptor class equivalent only handles basic property usagethoughto use decorator syntax to also specify set and delete operationswe' have to extend managed attributes