如何在Python中管理对可变属性的访问

在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是一个列表,我只想使用类C的方法来更改x的位置值。


慕丝7291255
浏览 126回答 1
1回答

慕尼黑5688855

一种方法是返回属性的副本,而不是列表本身。>>> class C:...&nbsp; &nbsp; &nbsp;def __init__(self, value):...&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;self._x = value...&nbsp; &nbsp; &nbsp;@property...&nbsp; &nbsp; &nbsp;def x(self):...&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return self._x[:]...&nbsp;>>> 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]或者,该属性可以返回迭代器over属性或视图(例如dict.items()而不是dict)。如果属性很大,则返回迭代器或视图可能有助于限制内存使用,并且与现代Python内置函数和类型的行为更加一致。如果可变属性本身包含可变属性(例如,列表或字典的列表),则可能也有必要返回这些对象的副本。如果对象图很深,则在时间和资源上可能会很昂贵。有关自定义对象复制方式的方法,请参阅复制模块的文档。此技术通常用于防止别名问题-其他对象持有对您对象内部状态的引用。这确实意味着副本可能与real属性不同步,但是如果您的代码设计良好,则其他类无论如何都不应保留您的类的值。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python