Как управлять доступом к непостоянному атрибуту в Python - PullRequest
0 голосов
/ 30 июня 2018

В Python мы можем использовать декоратор @property для управления доступом к атрибутам. Например, если мы определим класс:

class C:
    def __init__(self,value):
        self._x = value

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

мы можем получить значение x, но не изменить его:

c = C(1)
#c.x = 4  # <= this would raise an AttributeError: can't set attribute

Однако, если атрибут имеет изменяемый тип (например, список), мы можем установить другое значение для позиции атрибута:

c = C([0,0])
c.x[0] = 1 # <= this works

Есть ли способ предотвратить это? Если x - это список, я бы хотел изменить значение позиций x только с помощью методов класса C.

1 Ответ

0 голосов
/ 30 июня 2018

Один из способов сделать это - вернуть копию атрибута, а не сам список.

>>> class C:
...     def __init__(self, value):
...         self._x = value
...     @property
...     def x(self):
...         return self._x[:]
... 
>>> c = C([1, 2, 3])


>>> c.x
[1, 2, 3]
>>> c.x.append(5)
>>> c.x
[1, 2, 3]
>>> c.x[0] = 6
>>> c.x
[1, 2, 3]

В качестве альтернативы, свойство может возвращать атрибут iterator over или view (например, dict.items () вместо dict). Возвращение итераторов или представлений может помочь ограничить использование памяти, если атрибут большой и более соответствует поведению современных встроенных функций и типов Python.

Если атрибут mutable содержит сами изменяемые атрибуты - например, список списков или словарей, - возможно, потребуется также вернуть копии этих объектов. Это может быть дорого с точки зрения времени и ресурсов, если граф объекта является глубоким. См. Документы для модуля copy , чтобы узнать, как настроить копирование объектов.

Этот метод обычно используется для предотвращения проблемы алиасинга - когда другие объекты содержат ссылки на внутреннее состояние вашего объекта.

Это означает, что копии могут не синхронизироваться с реальным атрибутом, но если ваш код хорошо спроектирован, тогда другие классы не должны все равно удерживать значения вашего класса.

...