Class-level read-only properties in Python

Viewed 13867

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_value objects to be interpreted correctly.
  • The 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.
3 Answers
Related