Подтвердить что ты не робот

Способы сделать класс неизменным в Python

Я делаю некоторые распределенные вычисления, в которых несколько машин общаются в предположении, что все они имеют одинаковые версии различных классов. Таким образом, кажется, что это хороший дизайн, чтобы сделать эти классы неизменными; не в том смысле, что он должен помешать пользователю с плохими намерениями, просто неизменным, что он никогда не модифицируется случайно.

Как я могу это сделать? Например, как мне реализовать метакласс, который сделает класс неизменным после его определения?

>>> class A(object):
...     __metaclass__ = ImmutableMetaclass
>>> A.something = SomethingElse # Don't want this
>>> a = A()
>>> a.something = Whatever # obviously, this is still perfectly fine.

Альтернативные методы также прекрасны, например, декоратор/функция, которая берет класс и возвращает неизменяемый класс.

4b9b3361

Ответ 1

Если старый трюк использования __slots__ не подходит вам, это или какой-либо его вариант может сделать: просто напишите __setattr__ метод вашего метакласса, чтобы быть вашим стражем. В этом примере я запрещаю назначать новые атрибуты, но допускаю модификацию существующих:

def immutable_meta(name, bases, dct):
    class Meta(type):
        def __init__(cls, name, bases, dct):
            type.__setattr__(cls,"attr",set(dct.keys()))
            type.__init__(cls, name, bases, dct)

        def __setattr__(cls, attr, value):
            if attr not in cls.attr:
                raise AttributeError ("Cannot assign attributes to this class")
            return type.__setattr__(cls, attr, value)
    return Meta(name, bases, dct)


class A:
    __metaclass__ = immutable_meta
    b = "test"

a = A()
a.c = 10 # this works
A.c = 20 # raises valueError

Ответ 2

Не тратьте время на неизменные занятия.

Есть вещи, которые вы можете сделать, которые далеки, намного проще, чем возиться с попыткой создания неизменяемого объекта.

Вот пять отдельных методов. Вы можете выбирать из них. Любой будет работать. Некоторые комбинации также будут работать.

  • Документация

    . Собственно, они этого не забудут. Дайте им кредит.

  • Unit test. Выделите ваши объекты приложения простым макетом, который обрабатывает __setattr__ в качестве исключения. Любое изменение состояния объекта является ошибкой в ​​unit test. Это легко и не требует сложного программирования.

  • Переопределить __setattr__, чтобы создать исключение при каждой попытке записи.

  • collections.namedtuple. Они неизменяемы из коробки.

  • collections.Mapping. Он неизменен, но вам нужно реализовать несколько методов, чтобы заставить его работать.

Ответ 3

Если вы не против повторного использования работы другого человека:

http://packages.python.org/pysistence/

Непрерывные постоянные (в функциональных, а не записывающих в десктоп смысле) структуры данных.

Даже если вы не используете их как есть, исходный код должен дать некоторое вдохновение. Например, их класс expando принимает в нем объект в конструкторе и возвращает неизменную версию.