2010-01-31 13 views
8

El siguiente no funciona por alguna razón:¿Hay alguna manera de crear una propiedad de clase en Python?

>>> class foo(object): 
...  @property 
...  @classmethod 
...  def bar(cls): 
...    return "asdf" 
... 
>>> foo.bar 
<property object at 0x1da8d0> 
>>> foo.bar + '\n' 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for +: 'property' and 'str' 

¿Hay una manera de hacer esto, o es mi única alternativa que recurrir a algún tipo de engaño metaclase?

+1

Para cualquier persona que no esté familiarizada con las 'propiedades' en Python tal vez esto lo ayude a comprender de qué está hablando Jason. Http://docs.python.org/library/functions.html#property – MatrixFrog

Respuesta

6

Si desea que se active el descriptor property cuando obtiene un atributo del objeto X, debe poner el descriptor en type(X). Entonces, si X es una clase, el descriptor debe ir en el tipo de la clase, también conocida como la metaclase de la clase, sin "trucos", solo se trata de reglas completamente generales.

Alternativamente, puede escribir su propio descriptor de propósito especial. Ver here para un excelente tratado de "cómo hacerlo" sobre los descriptores. Editar por ejemplo:

class classprop(object): 
    def __init__(self, f): 
    self.f = classmethod(f) 
    def __get__(self, *a): 
    return self.f.__get__(*a)() 

class buh(object): 
    @classprop 
    def bah(cls): return 23 

print buh.bah 

emite 23, según se desee.

+0

Estoy usando una metaclase en otra parte del jerarquía de herencia, así que si utilizo la metaclase, obtengo lo siguiente: 'conflicto de metaclase: la metaclase de una clase derivada debe ser una subclase (no estricta) de las metaclases de todas sus bases' –

+0

* Sin embargo *, el decorador funcionó como un encanto. ¡Gracias! –

+0

@Jason, también podría usar una subclase de todas las metaclases involucradas, como dice el mensaje de error (pocas usan metaclases personalizadas múltiples, o metaclases que no subclasifican 'tipo', por lo que probablemente solo necesite subclasificar la metaclass personalizada que está usando), pero si el descriptor personalizado hace el trabajo, de hecho puede ser un enfoque más simple. –

Cuestiones relacionadas