Is there some way to make a class-level read-only property in Python? For instance, if I have a class
Foo, I want to say:
x = Foo.CLASS_PROPERTY
but prevent anyone from saying:
Foo.CLASS_PROPERTY = y
EDIT: I like the simplicity of Alex Martelli's solution, but not the syntax that it requires. Both his and ~unutbu's answers inspired the following solution, which is closer to the spirit of what I was looking for:
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
Now, I get:
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 #
I prefer this solution because:
- The members get declared inline instead of after the fact, as with
type(X).foo = ...
- The members' values are set in the actual class's code as opposed to in the metaclass's code.
It's still not ideal because:
- I have to set the
__metaclass__in order for
const_valueobjects to be interpreted correctly.
const_values don't "behave" like the plain values. For example, I couldn't use it as a default value for a parameter to a method in the class.