2011-04-19 15 views
31

Consideremos el siguiente ejemplo:Python: ¿Cómo pasar más de un argumento al getter de la propiedad?

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

Así que, por supuesto, llamar a la a = A(); a.x volverá 5

Pero imaginar que usted quiere ser capaz de modificar la propiedad x.
De esta manera, por ejemplo:

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

y llamarlo con a = A(); a.x(neg=True)

que levantará un TypeError: 'int' object is not callable, es bastante normal, ya que nuestra x se evalúa como 5.

Entonces, me gustaría saber cómo se puede pasar más de un argumento al comprador de la propiedad, si es posible.

Respuesta

37

Tenga en cuenta que no tiene para usar property como decorador. Puede usar felizmente a la antigua y exponer los métodos individuales, además de la propiedad:

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 

Esto puede o no ser una buena idea dependiendo exactamente lo que está haciendo con él (pero yo d esperar ver una justificación excelente en un comentario si encontré este patrón en cualquier código que estaba revisando)

24

Creo que no entendió del todo el propósito de las propiedades.

Si crea una propiedad x, tendrá acceso a ella usando obj.x en lugar de obj.x(). Después de crear la propiedad, no es posible llamar directamente a la función subyacente.

Si quiere pasar argumentos, el nombre de su método get_x y no hacer que una propiedad:

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

Si desea crear un setter, hacerlo de esta manera:

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

    @x.setter 
    def x(self, value): self._x = value 
+0

Lo sé! Y puedes ver la llamada 'a.x' en mi primer ejemplo. – Rizo

+1

@Rizo: las propiedades simplemente no están diseñadas para eso. – XORcist

7

En su segundo ejemplo, está usando a.x() como si fuera una función: a.x(neg=True). Con esto en mente, ¿por qué no simplemente definirlo como una función?

+0

Esa es una solución directa, pero estoy usando getters y setters muy complejos y me gustaría seguir usándolos sin tener que escribir funciones separadas para los atributos. – Rizo

+0

Esto no responde mi pregunta. ¡Ahora puedo usar funciones en Python! :) Solo quiero saber si hay alguna manera de forzar a una propiedad a actuar como una función. – Rizo

+3

@Rizo ¿por qué? Si desea que actúe como una función, entonces use una función (método). Pero en respuesta a su pregunta, la única forma sería devolver un invocable desde la propiedad que toma el parámetro. Entonces tendrías algo que se ve exactamente como una función pero menos eficiente. – Keith

6

una propiedad solo debe depender del objeto relacionado. Si desea usar algunos parámetros externos, debe usar métodos.

0

Sé que esta pregunta es antigua, pero, como referencia, puede llamar a su propiedad con un argumento como ese:

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

Como otros mencionados por otros, esto es no recomendado.

Cuestiones relacionadas