2010-01-23 13 views
13

Tenga en cuenta las siguientes definiciones de clasesPython: múltiples propiedades, una setter/getter

class of2010(object): 
    def __init__(self): 
     self._a = 1 
     self._b = 2 
     self._c = 3 

    def set_a(self,value): 
     print('setting a...') 
     self._a = value 
    def set_b(self,value): 
     print('setting b...') 
     self._b = value 
    def set_c(self,value): 
     print('setting c...') 
     self._c = value 
    a = property(fset=self.set_a) 
    b = property(fset=self.set_b) 
    c = property(fset=self.set_c) 

nota que set_[a|b|c]() hacen lo mismo. hay una manera de definir qué:

def set_magic(self,value): 
    print('setting <???>...') 
    self._??? = value 

una vez y usarlo para a, b, c de la siguiente manera

a = property(fset=self.set_magic) 
b = property(fset=self.set_magic) 
c = property(fset=self.set_magic) 

Respuesta

20
def attrsetter(attr): 
    def set_any(self, value): 
    setattr(self, attr, value) 
    return set_any 

a = property(fset=attrsetter('_a')) 
b = property(fset=attrsetter('_b')) 
c = property(fset=attrsetter('_c')) 
+0

Es propiedad (fset = ...), pero de lo contrario usaría algo así. – olt

+0

@olt: Gracias, corregido. –

1

Puede ser que usted está buscando __setattr__(self, name, value)

Tome una mirada here

2
class... 
def __setattr__(self, name, value): 
    print 'setting', name 
    self.__dict__[name] = value 

Eso es todo.

+1

Este consejo no está actualizado. De acuerdo con https://docs.python.org/2/reference/datamodel.html#customizing-attribute-access, "Para las clases de estilo nuevo, en lugar de acceder al diccionario de instancia,' __setattr__' debe llamar al método de clase base con el mismo nombre, por ejemplo, 'object .__ setattr __ (self, name, value)'. " Tenga en cuenta que OP está usando una nueva clase de estilo. –

5

Veo que sus ajustadores solo registran un mensaje y luego simplemente asignan el valor - de hecho, su respuesta aceptada solo asigna el valor. ¿Está utilizando este patrón porque es la Práctica Aceptada/Sabiduría Convencional en algún otro idioma, tal vez uno cuyo nombre comienza con "J"? Si es así, por favor, saber que el enfoque Pythonic a este mismo diseño es el más sencillo:

class Of2010(object): 
    def __init__(self): 
     self.a = 1 
     self.b = 2 
     self.c = 3 

No hay que no hacen nada set, ninguna función intermedia exige sólo para asignar un valor. "¿Que dices? "La exposición pública a las variables miembro? !!" Bueno, en realidad.

Observe estas clases desde el punto de vista del código del cliente. Para utilizar su clase, los clientes a crear un objeto, y luego asignar la propiedad "a" usando:

obj = Of2010() 
obj.a = 42 

Sorprendentemente, este es exactamente el mismo código para la clase 5-liner he publicado anteriormente.

¿Por qué el lenguaje J fomenta el estilo de propiedad más detallado? Para preservar la interfaz de clase en caso de cambios futuros en los requisitos. Si en algún momento, algún otro valor del objeto debe cambiar en concierto con cualquier cambio en a, entonces debe implementar el mecanismo de propiedad. Lamentablemente, el lenguaje J expone la naturaleza del mecanismo de acceso de atributo al código del cliente, de modo que introducir una propiedad en algún momento en el futuro es una tarea de refactorización intrusiva que requerirá una reconstrucción de todos los clientes que hacen uso de esa clase y su atributo "a".

En Python, este no es el caso. El acceso al atributo "a" del objeto se determina en tiempo de ejecución en la persona que llama. Como el acceso directo y el acceso a la propiedad se "parecen" igual, su clase de Python conserva esta interfaz aunque el mecanismo real sea diferente. Lo que importa es que es idéntico en lo que respecta al código del cliente.

Así que en Java, se introduce esta complejidad derecho de propiedad desde el inicio de esta clase (y, de hecho, por Aceptados, de todos clases), en la remota posibilidad de que puede ser necesario algún día en el futuro. Con Python, uno puede comenzar implementando lo más simple que podría funcionar, es decir, el acceso directo a variables simples de miembros, dejando el enfoque complejo para el tiempo en el futuro en que las cosas adicionales son realmente necesarias y de valor. Dado que ese día tal vez nunca llegue, este es un gran avance para lograr que la primera versión de trabajo de su código salga por la puerta.

+0

Quiero que ocurra una acción cada vez que se establecen ciertos miembros de (una instancia de) una clase. Quiero que se produzca la misma acción para estos miembros (mi ejemplo: imprimir el nombre del miembro) sin duplicar sus configuradores. esta es la razón por la que necesito setters. de lo contrario, como sabiamente dijo. no los usaría, ya que son innecesarios en python – bandana

+0

Si es tan simple como imprimir un nombre en cada invocación, ¿por qué no simplemente codificar esto en el padre __init __(), que siempre es llamado por cada instancia? –