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
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…