¿Hay alguna manera de hacer una propiedad de solo lectura de nivel de clase en Python? Por ejemplo, si tengo una clase Foo
, quiero decir:Propiedades de solo lectura de nivel de clase en Python
x = Foo.CLASS_PROPERTY
pero evitar que alguien diciendo:
Foo.CLASS_PROPERTY = y
EDIT: me gusta la simplicidad de Alex Martelli's solution, pero no el sintaxis que requiere Tanto su ~unutbu's answer s inspiró la siguiente solución, que es más cerca al espíritu de lo que estaba buscando:
class const_value (object):
def __init__(self, value):
self.__value = value
def make_property(self):
return property(lambda cls: self.__value)
class ROType(type):
def __new__(mcl,classname,bases,classdict):
class UniqeROType (mcl):
pass
for attr, value in classdict.items():
if isinstance(value, const_value):
setattr(UniqeROType, attr, value.make_property())
classdict[attr] = value.make_property()
return type.__new__(UniqeROType,classname,bases,classdict)
class Foo(object):
__metaclass__=ROType
BAR = const_value(1)
BAZ = 2
class Bit(object):
__metaclass__=ROType
BOO = const_value(3)
BAN = 4
Ahora, me sale:
Foo.BAR
# 1
Foo.BAZ
# 2
Foo.BAR=2
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# AttributeError: can't set attribute
Foo.BAZ=3
#
prefiero esta solución porque:
- los miembros consiguen declaradas en línea en lugar de después del hecho, al igual que con
type(X).foo = ...
- Los valores de los miembros se establecen en el código de la clase real en lugar de en el código de la metaclase.
todavía no es ideal porque:
- tengo que fijar el
__metaclass__
con el fin deconst_value
objetos sean interpretados correctamente. - Los
const_value
s no se "comportan" como los valores normales. Por ejemplo, no pude usarlo como un valor predeterminado para un parámetro a un método en la clase.
¿Por qué alguien intentará establecer Foo.CLASS_PROPERTY? El estilo típico en Python es elegir la simplicidad sobre la planificación para evitar una instancia teórica donde alguien hace algo estúpido. No hay nada que puedas hacer para evitar que la gente haga cosas estúpidas con tu código. –
@Mike: tienes razón; el sentido común le diría a las personas que no modifiquen estas propiedades. Y sin embargo, de vez en cuando, se modifican. Es por eso que me gusta que se deletree (más explícitamente que con mayúsculas). La misma lógica que usar miembros privados. Las interfaces explícitas son buenas. No me malinterpreten: me gusta la simplicidad también. Preferiría mucho si hubiera alguna instalación incorporada para esto (como un decorador @classproperty o algo así). Tal como están las cosas, ni siquiera estoy seguro de que use la solución anterior si requiere configurar '__metaclass__' cada vez. Las Mayores pueden ganar, por ahora. – mjumbewu
Nota para las personas del futuro: las versiones modernas de Python pueden usar '@ property' en las clases de estilo nuevo: http://docs.python.org/library/functions.html#property –