Настройка __setattr__
в каждом классе (например, как показано в моем старом рецепте, на который указывает ответ @ ainab и другие ответы), работает только для прекращения назначения атрибутов INSTANCE, а не атрибутов CLASS. Таким образом, ни один из существующих ответов на самом деле не удовлетворит ваше требование, как указано.
Если то, что вы просили, на самом деле именно то, что вы хотите, вы можете прибегнуть к некоторому сочетанию пользовательских метаклассов и дескрипторов, таких как:
class const(object):
def __init__(self, val): self.val = val
def __get__(self, *_): return self.val
def __set__(self, *_): raise TypeError("Can't reset const!")
class mcl(type):
def __init__(cls, *a, **k):
mkl = cls.__class__
class spec(mkl): pass
for n, v in vars(cls).items():
if isinstance(v, const):
setattr(spec, n, v)
spec.__name__ = mkl.__name__
cls.__class__ = spec
class with_const:
__metaclass__ = mcl
class foo(with_const):
CLASS_CONSTANT = const('this is a constant')
print foo().CLASS_CONSTANT
print foo.CLASS_CONSTANT
foo.CLASS_CONSTANT = 'Oops!'
print foo.CLASS_CONSTANT
Это довольно продвинутый материал, поэтому вы можете предпочесть более простой подход __setattr__
, предложенный в других ответах, несмотря на то, что он НЕ соответствует вашим требованиям, как указано (т. Е. Вы можете разумно решить ослабить свои требования, чтобы добиться простоты; - ). Но методы здесь могут все еще быть интересными: пользовательский тип дескриптора const
- это другой способ (ИМХО, гораздо лучше, чем переопределение __setattr__
в каждом классе, для которого нужны некоторые константы И создание всех атрибутов констант, а не выбор и выбор ... ) заблокировать присвоение атрибуту экземпляра; остальная часть кода посвящена пользовательскому метаклассу, создающему уникальные подклассы для каждого класса, чтобы максимально использовать указанный дескриптор и получить именно ту функциональность, которую вы специально запрашивали.