IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Peut-on boucler des setters?


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Août 2016
    Messages
    80
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Août 2016
    Messages : 80
    Par défaut Peut-on boucler des setters?
    Bonjours,

    Je viens d'écrire une classe que je suis sensé utilisé régulièrement, et dans le but de simplifié sont utilisation, j'utilise des setters.
    L'écriture de ces setters dans la classe me semble répétitive et je me demande s'il est possible d'écrire cela de meilleurs façons: Est-il possible de bouclé les setters?

    Voici le code de ma classe pour mieux visualisé ma demande.
    Je ne suis pas informaticien, des choses qui vous paraissent évidente ne le sont pas forcement pour moi.
    En vous remerciant pour le temps que vous m'accorder.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
     
    class DefPara(object):
    	""" Définition des parametreS pour class Machine
                              typval  #  Parametre type type
                              val #  Valeur du parametre
                              valini #  Valeur du parametre apprès réinitialisation
                              defmax #  Valeur Max provoquant un défaut
                              defmin #  Valeur Min provoquant un défaut
                              almax #  Valeur Max provoquant une alarme
                              almin #  Valeur Min provoquant une alarme
                              etq #  Libellé du parametre type string
            """
    	ensType = {'None','bool','int','float','str'}
    	ensArg = {'typeval', 'defmin', 'defmax', 'almin', 'almax', 'etq', 'val', 'valini'}
     
    	def __init__(self, **kwargs):
    		self._kwarg = {}
    		for key in DefPara.ensArg:
    			self._kwarg[key] = None
    		for key, value in kwargs.items():
    			if self._control(key, value):
    				self._kwarg[key] = value
     
            @property
    	def typval(self):
    		"""Type du parametre"""
    		return self._kwarg['typeval']
     
            @typval.setter
    	def typval(self, value):
    		if self._control("typeval",value):
    			self._kwarg['typeval'] = value
     
            @property
    	def val(self):
    		"""Valeur du parametre"""
    		return self._kwarg['val']
     
            @val.setter
    	def val(self, value):
    		if self._control("val",value):
    			self._kwarg['val'] = value
     
            @val.deleter
    	def val(self):
    		self._kwarg['val'] = self._kwarg['valini']
     
            @property
    	def valini(self):
    		"""Valeur du parametre après réinitialisation"""
    		return self._kwarg['valini']
     
            @valini.setter
    	def valini(self, value):
    		if self._control("valini",value):
    			self._kwarg['valini'] = value
     
            @property
    	def etq(self):
    		"""Libellé du parametre"""
    		return self._kwarg['etq']
     
            @etq.setter
    	def etq(self, value):
    		if self._control("etq",value):
    			self._kwarg['etq'] = value
     
            @property
    	def defmin(self):
    		"""Valeur Min provoquant un défaut"""
    		return self._kwarg['defmin']
     
            @defmin.setter
    	def defmin(self, value):
    		if self._control("defmin",value):
    			self._kwarg['defmin'] = value
     
            @defmin.deleter
    	def defmin(self):
    		self._kwarg['defmin'] = None
     
            @property
    	def defmax(self):
    		"""Valeur Max provoquant un défaut"""
    		return self._kwarg['defmax']
     
            @defmax.setter
    	def defmax(self, value):
    		if self._control("defmax",value):
    			self._kwarg['defmax'] = value
     
            @defmax.deleter
    	def defmax(self):
    		self._kwarg['defmax'] = None
     
            @property
    	def almin(self):
    		"""Valeur Min provoquant une alarme"""
    		return self._kwarg['almin']
     
            @almin.setter
    	def almin(self, value):
    		if self._control("almin",value):
    			self._kwarg['almin'] = value
     
            @almin.deleter
    	def almin(self):
    		self._kwarg['almin'] = None
     
            @property
    	def almax(self):
    		"""Valeur Max provoquant une alarme"""
    		return self._kwarg['almax']
     
            @almax.setter
    	def almax(self, value):
    		if self._control("almax",value):
    			self._kwarg['almax'] = value
     
            @almax.deleter
    	def almax(self):
    		self._kwarg['almax'] = None
     
    	def _control(self, arg, value):
    		if arg not in DefPara.ensArg:
    			logpara.debug('''Parametre: argument inconnu: {} n'est pas dans DefPara.ensArg'''.Format(arg))
    			return False
     
    		if arg == "typeval":
    			if (not isinstance(value, type)):
    				logpara.debug('''Parametre: typeval doit etre de type : type''')
    				return False
    			elif (value not in DefPara.ensType):
    				logpara.debug('''Parametre: typeval doit etre de type : {'None','bool','int','float','str'}''')
    				return False
    			return True
     
    		if arg in {"defmax", "defmin", "almax", "almin"}:
    			if (self._kwarg['typeval'] in {'int', 'float'}):
    				if arg == "defmax":
    					if (type(arg) is not None
    					and type(self._kwarg['defmin']) is not None
    					and arg < self._kwarg['defmin']):
    						logpara.debug('''Parametre: defmax doit etre superieur a defmin''')
    						return False
    					return True
    				if arg == "defmin":
    					if (type(arg) is not None
    						and type(self._kwarg['defmax']) is not None
    						and arg > self._kwarg['defmax']):
    						logpara.debug('''Parametre: defmin doit etre inferieur a defmax''')
    						return False
    					return True
    				if arg == "almax":
    					if (type(arg) is not None
    						and type(self._kwarg['almin']) is not None):
    						if arg < self._kwarg['almin']:
    							logpara.debug('''Parametre: almax doit etre superieur a almin''')
    							return False
    						if arg > self._kwarg['defmax']:
    							logpara.debug('''Parametre: almax doit etre inferieur a defmax''')
    							return False
    					return True
    				if arg == "almin":
    					if (type(arg) is not None
    						and type(self._kwarg['almax']) is not None):
    						if arg > self._kwarg['almax']:
    							logpara.debug('''Parametre: almin doit etre inferieur a almax''')
    							return False
    						if arg < self._kwarg['defmin']:
    							logpara.debug('''Parametre: almin doit etre superieur a defmin''')
    							return False
    					return True
    		if arg in {"val","valini"}:
    			if (self._kwarg['typeval'] in {'int', 'float'}):
    				if type(arg) is not None:
    					if type(self._kwarg['defmax']) is not None:
    						if arg >= self._kwarg['defmax']:
    							logpara.debug('''Parametre: {} doit etre inferieur a defmax''').format(arg)
    							return False
    						if arg <= self._kwarg['defmin']:
    							logpara.debug('''Parametre: {} doit etre superieur a defmin''').format(arg)
    							return False
    			return True
    		if arg == 'etq':
    			if (type(arg) is not None
    				and type(arg) is not str):
    					logpara.debug('''Parametre: etq doit etre de type string''')
    					return False
    			return True

  2. #2
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 322
    Par défaut
    bonjour
    pas compris l'intérêt d'utiliser self._kwarg ... mais tu peux regarder du côté des fonctions magiques (__setattr__), même chose pour getters.

    Petit exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    class Voiture:
        def __init__(self, **kwargs):
            self._kwarg = kwargs
     
        def __setattr__(self, key, value) -> None:
            if key == '_kwarg':
                super().__setattr__(key, value)
                return
     
            if item := self._control(key, value):
                print('   # Je change', key)
                self._kwarg[key] = value
            else:
                print('   # Je ne change PAS', key)
     
        def __getattr__(self, key):
            item = self._kwarg.get(key, None)
            # if item == None: raise Exception(f'   # {key} n'existe pas !')
            return item
     
        def _control(self, key, value) -> bool:
            item = self._kwarg.get(key, None)
            if not item:
                print(f'   # {key} existe pas !')
                return False
            int(value)
            return item
     
        def __str__(self) -> str:
            return str(self._kwarg)
     
     
    trotinette = Voiture(roues=4)
    print(trotinette)
    trotinette.roues = 3
    trotinette.moteur = 0
    print(trotinette)
    print(trotinette.roues)
    print(trotinette.moteur)

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 827
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par alexis_c Voir le message
    Je viens d'écrire une classe que je suis censé utiliser régulièrement, et dans le but de simplifier sont utilisation, j'utilise des setters.
    Punaise tu ne sais pas quand mettre à l'infinitif ou au participe passé??? Pourtant la grammaire et l'orthographe ne sont pas une option, cela permet de faire comprendre ses idées ("à essayer" et "a essayé" ne signifient pas du tout la même chose).
    Les livres ne servent pas qu'à caler les meubles ou à faire du feu!!!

    Citation Envoyé par alexis_c Voir le message
    Voici le code de ma classe pour mieux visualiser ma demande.
    Un code montrant ta façon de l'utiliser eut été apprécié.
    papajoker a montré __setattr__ et __getattr__ qui permettent de traiter l'accès à un attribut. Sinon tu peux carrément rendre ta classe indexable (tu l'utilises ensuite comme un dictionnaire)
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #!/usr/bin/env python3
    # coding: utf-8
     
     
    class cPara(object):
    	def __init__(self, **kwargs):
    		self.__kwarg = dict(kwargs)
     
    	def __setitem__(self, att, value): self.__kwarg[att]=value
    	def __getitem__(self, att): return self.__kwarg[att]
    # cPara
     
    xxx=cPara(aaa="toto", bbb="tutu")
    xxx["ccc"]="titi"
     
    for k in ("aaa", "bbb", "ccc"):
    	print("valeur [%s]=[%s]" % (k, xxx[k]))

    Accessoirement depuis Python3 ce n'est plus utile de spécifier (object). Pas non plus la peine de mettre des parenthèses au "if" quand l'expression à évaluer est binaire. Utiliser un tuple est plus léger qu'un ensemble si ce dernier ne se justifie pas (remplacer if arg in {"defmax", "defmin", "almax", "almin"} par if arg in ("defmax", "defmin", "almax", "almin")). Et tu devrais éviter de mélanger "espaces" et "tabulations" car ce n'est plus admis sous P3 (ce qui m'incite à penser qu'il s'agit ici d'un code P2).
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 322
    Par défaut
    Un code montrant ta façon de l'utiliser eut été apprécié.
    Clair car ici, je ne comprends pas l'intérêt de ce _kwarg je suppose que ce n'est qu'un bricolage pour faire des getters/setters

    Opps, j'avais zappé dans init que les attributs sont fixés

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        ensArg = ('typeval', 'defmin', 'defmax', 'almin', 'almax', 'etq', 'val', 'valini')
     
        def __init__(self, **kwargs):
            self._kwarg = {x:None for x in self.ensArg}
            self._kwarg = self._kwarg | kwargs     # ici on peut donc ajouter des attributs ...
            for key, value in kwargs.items():
                setattr(self, key, value)

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 827
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par papajoker Voir le message
    Opps, j'avais zappé dans init que les attributs sont fixés
    En plus ça peut se gérer directement via __slots__
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class personne:
    	__slots__=("nom", "prenom")
     
    	def __init__(self, nom, prenom):
    		self.nom=nom
    		self.prenom=prenom
     
    >>> p=personne("LeRoi", "Arthur")
    >>> p.age=800
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'personne' object has no attribute 'age'
    Toutefois je crois que __slots__ peut influer sur __setattr__ (que j'ai très peu eu l'occasion d'utiliser)...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 322
    Par défaut
    une version sans __slot__ mais avec même fonctionnement que __slot__ (sans l'optimisation)

    getter et setter sur chaque attribut et une bête méthode pour contrôler les setters

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    class Personne:
        _slots_=("nom", "prenom")
     
        def __init__(self, nom, prenom):
            self.nom = nom
            self.prenom = prenom
     
        def __setattr__(self, key: str, value) -> None:
            if key not in self._slots_:
                # pas d'exception ?
                raise AttributeError(f"{key} est invalide pour cet objet!")
                return
            if self._control(key, value):
                super().__setattr__(key, value)
            else:
                print('   # Je ne change PAS', key, 'valeur incorrecte')
     
        def __getattribute__(self, key: str):
            if key in self._slots_:
                # je fais un éventuel travail ?
                pass
            return super().__getattribute__(key)
     
        def _control(self, key, value) -> bool:
            return 'e' in value
     
        def __str__(self) -> str:
            return f'{self.prenom} {self.nom}'
    ps: écrire une énorme méthode _control des petits setters sont beaucoup plus maintenables

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    721
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 721

  8. #8
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 715
    Par défaut
    Citation Envoyé par alexis_c Voir le message
    L'écriture de ces setters dans la classe me semble répétitive et je me demande s'il est possible d'écrire cela de meilleurs façons: Est-il possible de bouclé les setters?
    Vous utilisez des properties pour valider un type de données... ok mais autant le faire avec les descriptors qui réalisent ces properties: ce sera plus souple et il y a un bon tuto qui montre comment ça marche et ce qu'on peut faire avec.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Peut on lire des tables Paradox sans le BDE ?
    Par der§en dans le forum Bases de données
    Réponses: 3
    Dernier message: 02/11/2005, 11h42
  2. Réponses: 2
    Dernier message: 27/03/2005, 16h09
  3. Peut-on lire des gros fichiers(100k) avec "TClientSocke
    Par Fred LEM dans le forum C++Builder
    Réponses: 3
    Dernier message: 20/12/2004, 14h41
  4. [Outils][BootStrapper] Où peut-on disposer des sources ?
    Par Didier69 dans le forum Contribuez
    Réponses: 3
    Dernier message: 28/09/2004, 15h32
  5. Comment peut on integer des controles dans un prog opengl
    Par franck31400 dans le forum OpenGL
    Réponses: 2
    Dernier message: 28/04/2004, 09h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo