web-dev-qa-db-fra.com

Python: Comment passer plus d'un argument au getter de propriété?

Prenons l'exemple suivant:

class A:
    @property
    def x(self): return 5

Donc, bien sûr, appeler la a = A(); a.x renverra 5

Mais imaginons que vous souhaitiez pouvoir modifier la propriété x.
.__ De cette façon, par exemple:

class A:
    @property
    def x(self, neg = False): return 5 if not neg else -5

Et appelez-le avec a = A(); a.x(neg=True)

Cela générera une erreur TypeError: 'int' object is not callable, ce qui est tout à fait normal, car notre x est évalué en tant que 5.

Je voudrais donc savoir comment on peut passer plus d’un argument à l’acquéreur de propriété, si cela est possible.

42
Rizo

Notez que vous n'avez pas à utiliser property en tant que décorateur. Vous pouvez très bien l'utiliser à l'ancienne et exposer les méthodes individuelles en plus de la propriété:

class A:
    def get_x(self, neg=False):
        return -5 if neg else 5
    x = property(get_x)

>>> a = A()
>>> a.x
5
>>> a.get_x()
5
>>> a.get_x(True)
-5

Cela peut être ou ne pas être une bonne idée en fonction de ce que vous faites avec cela (mais je m'attendrais à voir une excellente justification dans un commentaire si je découvrais ce modèle dans n'importe quel code que je lisais)

47
ncoghlan

Je pense que vous n'avez pas bien compris le but des propriétés.

Si vous créez une propriété x, vous y accéderez en utilisant obj.x au lieu de obj.x(). Après avoir créé la propriété, il est difficile d'appeler directement la fonction sous-jacente.

Si vous voulez passer des arguments, nommez votre méthode get_x et n'en faites pas une propriété:

def get_x(self, neg=False):
    return 5 if not neg else -5

Si vous voulez créer un passeur, procédez comme suit:

class A:
    @property
    def x(self): return 5

    @x.setter
    def x(self, value): self._x = value
31
ThiefMaster

une propriété ne doit dépendre que de l'objet associé. Si vous souhaitez utiliser certains paramètres externes, vous devez utiliser des méthodes.

14
Sepp

Dans votre deuxième exemple, vous utilisez a.x() comme s'il s'agissait d'une fonction: a.x(neg=True). Dans cet esprit, pourquoi ne pas simplement le définir comme une fonction?

11
NPE

Je sais que cette question est ancienne, mais, pour référence, vous pouvez appeler votre propriété avec un argument comme celui-ci:

a = A()
assert a.x == 5
assert A.x.fget(a, True) == -5

Comme d'autres mentionnés par d'autres, cela n'est pas conseillé.

4
Campi

Dans ce cas particulier, vous pouvez définir deux propriétés qui appellent une fonction sous-jacente:

class A:
    @property
    def x(self):
        return self._x(neg = False)

    @property
    def x_neg(self):
        return self._x(neg = True)

    def _x(self, neg):
        return 5 if not neg else -5
1
Kim SJ