Licence CC BY-NC-ND Thierry Parmentelat & Arnaud Legout
création de propriétés à la volée¶
en s’inspirant du code:¶
class Person(object):
def __init__(self):
self._name = ''
def fget(self):
print(f"Getting: {self._name}")
return self._name
def fset(self, value):
print(f"Setting: {value}")
self._name = value.title()
name = property(fget=fget, fset=fset, doc="I'm the property.")user = Person()
user.name = 'john smith'Setting: john smith
# remarquez d'ailleurs - sans rapport avec l'exercice
# qu'ici on ne spécifie pas de deleter
try:
del user.name
except AttributeError as e:
print("OOPS", e)OOPS property 'name' of 'Person' object has no deleter
écrivez¶
une nouvelle version
DynamicPersonde cette classequi ne possède plus les 2 méthodes
fget/fsetmais en remplacement une méthode
addPropertyet autres méthodes privées si nécessaire
de façon à ce qu’on puisse l’utiliser comme ceci
>>> user = DynamicPerson()
>>> user.addProperty('name')
>>> user.addProperty('phone')
>>> user.name = 'john smith'
Setting: name = john smith
>>> user.phone = '12345'
Setting: phone = 12345
>>> user.name
Getting: name
'John Smith'
>>> user.__dict__
{'_phone': '12345', '_name': 'John Smith'}indices¶
pour cet exercice il semble plus naturel
d’utiliser la builtin
propertyplutôt que la version avec décorateur
remarquez que le récepteur de addProperty
est l’instance
useret non la classe
Person
# une façon possible de faire
class DynamicPerson(object):
def addProperty(self, attribute):
# avec une clôture on capture attribute
# dans les getter et setter
def setter(self, value):
print(f"Setting: {attribute} = {value}")
setattr(self, '_' + attribute, value)
def getter(self):
value = getattr(self, '_' + attribute)
print(f"Getting: {attribute} = {value}")
return value
# on attache la property à la classe et pas à l'instance
setattr(self.__class__,
attribute,
# le descriptor fabriqué par property
property(fget=getter,
fset=setter,
doc=f"Auto-generated {attribute} method"))user = DynamicPerson()
user.addProperty('name')
user.addProperty('phone')
user.name = 'john smith'
user.phone = '12345'
user.name
user.__dict__Setting: name = john smith
Setting: phone = 12345
Getting: name = john smith
{'_name': 'john smith', '_phone': '12345'}pour les rapides¶
ajoutez du code de sorte que
addProperty()crée l’attribut à une valeur
Noneou encore mieux, à une valeur passée à
addProperty