Skip to article frontmatterSkip to article content
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

>>> 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

# 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