2009-09-04 3 views
4

I ont une la classe suivante:Puis-je ajouter des paramètres à une propriété python pour réduire la duplication de code?


class Vector(object): 
    def __init__(self, x=0, y=0, z=0): 
     self.x = x 
     self.y = y 
     self.z = z 

    def _getx(self): 
     return self._x 
    def _setx(self, value): 
     self._x = float(value) 
    x = property(_getx, _setx) 

    def _gety(self): 
     return self._y 
    def _sety(self, value): 
     self._y = float(value) 
    y = property(_gety, _sety) 

    def _getz(self): 
     return self._z 
    def _setz(self, value): 
     self._z = float(value) 
    z = property(_getz, _setz) 

Les trois accesseurs sont tous identiques à l'exception de la propriété de l'objet qu'ils modifient (x, y, z). Y at-il un moyen que je puisse écrire un get et un ensemble, puis passer la variable à modifier afin que je ne me répète pas?

Répondre

16

Bien sûr, faire un descripteur personnalisé selon les concepts clairement expliquées dans this doc:

class JonProperty(object): 
    def __init__(self, name): 
     self.name = name 

    def __get__(self, obj, objtype): 
     return getattr(obj, self.name) 

    def __set__(self, obj, val): 
     setattr(obj, self.name, float(val)) 

puis simplement l'utiliser:

class Vector(object): 
    def __init__(self, x=0, y=0, z=0): 
     self.x = x 
     self.y = y 
     self.z = z 
    x = JonProperty('_x') 
    y = JonProperty('_y') 
    z = JonProperty('_z') 
+0

A travaillé super! Merci. –

+1

Toujours heureux de vous aider! N'oubliez pas d'accepter une réponse (utilisez l'icône «coche» sous le numéro donnant le résultat de la réponse) une fois que vous avez vérifié que c'est une bonne solution à votre problème - c'est l'étiquette fondamentale de débordement de pile. –

0

Non testé, mais cela devrait fonctionner:

def force_float(name): 
    def get(self): 
     return getattr(self, name) 
    def set(self, x): 
     setattr(self, name, float(x)) 
    return property(get, set) 

class Vector(object): 
    x = force_float("_x") 
    y = force_float("_y") 
    # etc 
+0

Oui, cela fonctionne, à l'exception que vous devez initialiser _x et _y. –

2

Pourquoi ne pas écrire cela?

class Vector(object): 
    def __init__(self, x=0, y=0, z=0): 
     self.x = x 
     self.y = y 
     self.z = z 

Si vos accesseurs sont dans la pratique de report quelque chose comme Java, alors ne pas les écrire. Exposez simplement les attributs x, y et z. Vous pouvez les modifier ultérieurement si nécessaire et, contrairement à Java (qui nécessiterait une sorte de recompilation), tout le code client fonctionnera parfaitement. Sur le thème des getters et des setters en Python, le consensus général, tel que je le comprends, est "ne les écrivez pas jusqu'à ce que vous en ayez besoin." N'écrivez des setters et getters que s'ils ajoutent réellement de la valeur à votre programme (comme protéger une structure de données interne, peut-être). Autrement, laissez-les dehors et passez votre temps à faire du codage productif.

+1

A l'origine, je voulais un mécanisme pour garantir que x, y et z seraient toujours un flottant, au cas où un utilisateur entrerait un int ou une chaîne. Cependant, j'ai commencé à réfléchir à ce sujet un peu plus et je suis d'accord avec vous. Je vais continuer avec l'attitude python "nous sommes tous des adultes" et laisser à l'utilisateur de classe de s'assurer qu'un flotteur est stocké. Les connaissances que j'ai acquises sur la définition des décorateurs en valaient la peine. –

Questions connexes