2012-07-26 16 views
10

Estoy tratando de encontrar la mejor manera de extender una variable de clase. Espero que un ejemplo del método que he presentado hasta ahora lo aclare.propiedades de la clase python

class A(object): 
    foo = ['thing', 'another thing'] 

class B(A): 
    foo = A.foo + ['stuff', 'more stuff'] 

Intento que la subclase herede y extienda la variable de clase primaria. El método anterior funciona, pero parece un poco tonto. Estoy abierto a cualquier sugerencia, incluso lograr algo similar usando un enfoque completamente diferente.

Obviamente, puedo seguir usando este método si es necesario, pero si hay una manera mejor en la que me gustaría encontrarlo.

+6

¿Qué hay en 'foo' que tiene que ser un [clase de propiedad] (http: // stackoverflow.com/questions/128573/) y no solo una propiedad de instancia? (Para el caso, dado que las listas son mutables, puede * cambiar * la propiedad de la clase en el momento '__init__'.) – kojiro

+7

En mi humilde opinión, lo que tiene se ve bien para mí (y no puedo pensar en una manera más limpia de hacerlo eso). Por cierto, yo llamaría a estos "atributos de clase", no a "propiedades de clase", ya que una propiedad es algo diferente (normalmente creado por la función/decorador incorporado 'propiedad'). – mgilson

+0

@kojiro Él no se está refiriendo a ese tipo de propiedades, solo significa atributos. – Julian

Respuesta

8

podría utilizar una metaclase:

class AutoExtendingFoo(type): 

    def __new__(cls, name, bases, attrs): 
     foo = [] 
     for base in bases: 
      try: 
       foo.extend(getattr(base, 'foo')) 
      except AttributeError: 
       pass 
     try: 
      foo.extend(attrs.pop('foo_additions')) 
     except KeyError: 
      pass 
     attrs['foo'] = foo 
     return type.__new__(cls, name, bases, attrs) 

class A(object): 
    __metaclass__ = AutoExtendingFoo 
    foo_additions = ['thing1', 'thing2'] 
    # will have A.foo = ['thing1', 'thing2'] 

class B(A): 
    foo_additions = ['thing3', 'thing4'] 
    # will have B.foo = ['thing1', 'thing2', 'thing3', 'thing4'] 

class C(A): 
    pass 
    # will have C.foo = ['thing1', 'thing2'] 

class D(B): 
    pass 
    # will have D.foo = ['thing1', 'thing2', 'thing3', 'thing4'] 
+2

Agradable, pero viola el principio de menor sorpresa. Tal vez asignar a '__add_to_foo__', en su lugar, pretendiendo que heredamos un' foo' vacío de 'object'. – chepner

+0

@chepner Eso es más agradable. Lo cambiaré ... –

1

que definitivamente iría por ejemplo- propiedades. (si lo hizo bien, no están obligados a ser estática para su caso ?!)

>>> class A: 
...  @property 
...  def foo(self): 
...   return ['thin', 'another thing'] 
... 
>>> class B(A): 
...  @property 
...  def foo(self): 
...   return super().foo + ['stuff', 'thing 3'] 
... 
>>> B().foo 
['thin', 'another thing', 'stuff', 'thing 3'] 
+0

Eso no es particularmente eficiente si accedes a estos datos con frecuencia. Tienes que hacer una búsqueda de atributos en 'A' luego crear una nueva lista y anexarla cada vez que accedes a' B.foo'. Además, todavía tienes el problema de que cada subclase tiene que definir la propiedad de modo que recupere 'super(). Foo'. Y si alguna clase futura hereda de múltiples clases que se divierten, comienza a obtener muchos problemas difíciles de seguir rápidamente. –

Cuestiones relacionadas