How to create a read-only class property in Python? [duplicate]

This will make Foo.number a read-only property:

class MetaFoo(type):
    @property
    def number(cls):
        return cls.x

class Foo(object, metaclass=MetaFoo):
    x = 4

print(Foo.number)
# 4

Foo.number = 6
# AttributeError: can't set attribute

Explanation: The usual scenario when using @property looks like this:

class Foo(object):
    @property
    def number(self):
        ...
foo = Foo()

A property defined in Foo is read-only with respect to its instances. That is, foo.number = 6 would raise an AttributeError.

Analogously, if you want Foo.number to raise an AttributeError you would need to setup a property defined in type(Foo). Hence the need for a metaclass.


Note that this read-onlyness is not immune from hackers.
The property can be made writable by changing Foo’s
class:

class Base(type): pass
Foo.__class__ = Base

# makes Foo.number a normal class attribute
Foo.number = 6   
print(Foo.number)

prints

6

or, if you wish to make Foo.number a settable property,

class WritableMetaFoo(type): 
    @property
    def number(cls):
        return cls.x
    @number.setter
    def number(cls, value):
        cls.x = value
Foo.__class__ = WritableMetaFoo

# Now the assignment modifies `Foo.x`
Foo.number = 6   
print(Foo.number)

also prints

6

Leave a Comment