Есть ли способ сделать свойство только для чтения на уровне класса в Python? Например, если у меня есть класс Foo
, я хочу сказать:
x = Foo.CLASS_PROPERTY
но не позволяйте никому говорить:
Foo.CLASS_PROPERTY = y
EDIT: Мне нравится простота решения Alex Martelli, но не тот синтаксис, который ему требуется. И его, и ~ unutbu answer вдохновили следующее решение, которое ближе к духу того, что я искал:
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
Теперь я получаю:
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
#
Я предпочитаю это решение, потому что:
- Члены получают объявленный inline, а не после факта, как в
type(X).foo = ...
- Значения членов устанавливаются в фактическом коде класса, а не в метаклассовом коде.
Это все еще не идеально, потому что:
- Мне нужно установить
__metaclass__
для корректного интерпретации объектовconst_value
. -
const_value
не ведут себя как простые значения. Например, я не мог использовать его как значение по умолчанию для параметра для метода в классе.