在 Python 中将类实例属性设为只读

Posted

技术标签:

【中文标题】在 Python 中将类实例属性设为只读【英文标题】:Make a class instance attribute read-only in Python 【发布时间】:2016-02-02 11:45:20 【问题描述】:

我正在尝试将我的一些模块包装到类中并开始使用属性。

努力将这两个答案结合在一起:making instance attribute read-only 和 validating attributes。

我希望能够创建 DataFolder 类的实例:

df = DataFolder(owner="me", path="/.data")

之后我希望能够允许编辑owner 属性,但不能编辑path 属性。我希望能够在初始化时(pathowner)和之后(但仅限 owner)验证属性。

class DataFolder(object):
    _path = None

    #----------------------------------------------------------------------
    def __init__(self,owner,path):
        self.path = path
        self.owner = owner

    @property
    #----------------------------------------------------------------------
    def owner(self):
        return self._owner

    @owner.setter
    #----------------------------------------------------------------------
    def owner(self,owner_value):
        if "me" not in owner_value:
            raise Exception("invalid owner")
        self._owner = owner_value

    @property
    #----------------------------------------------------------------------
    def path(self):
        return self._path

    @path.setter
    #----------------------------------------------------------------------
    def path(self,path_value):
        if self._path is not None:
            raise AttributeError("Cannot edit path of existing data folder")
        if "dat" not in path_value:
            raise Exception("invalid folder")
        self._path = path_value

使用全局变量_path = None 并检查@path.setter 中的if self._path is not None: 是否正确/最好?代码工作正常,但我想知道是否有更好的方法。

【问题讨论】:

这似乎是一种合理的做法——它是一个类属性,而不是一个全局变量。不过,对于无效的论点,我会提出 ValueError 而不是基 Exception。由于这似乎是有效的代码,您可能会在Code Review 上做得更好。 谢谢!将使用 ValueError 代替。私有变量前面的“_”越来越令人困惑,但我希望习惯它们:) 【参考方案1】:

对我来说看起来不错,除了一件事:_path = None 属于一个类。

这只是一个小小的改进:

class DataFolder(object):
    def __init__(self, owner, path):
        self._path = None  # now it is an instance variable.
        self.path = path
        self.owner = owner

    @property
    def owner(self):
        return self._owner

    def _validate_owner(self, owner_value):
        if "me" not in owner_value:
            raise ValueError("invalid owner")

    @owner.setter
    def owner(self, owner_value):
        self._validate_owner(owner_value)
        self._owner = owner_value

    @property
    def path(self):
        return self._path

    def _validate_path(self, path_value):
        if self._path is not None:
            raise AttributeError("Cannot edit path of existing data folder")
        if "dat" not in path_value:
            raise ValueError("invalid folder")

    @path.setter
    def path(self, path_value):
        self._validate_path(path_value)
        self._path = path_value

使用:

d = DataFolder('me', 'data')
print(d.path, d.owner)
d.path = 'new_data'

输出:

('data', 'me')
new_me
AttributeError: Cannot edit path of existing data folder

【讨论】:

你能概括一下你认为这更好吗?为什么不直接从__init__ 委托给getter,而不是复制代码?为什么要访问类的验证,而不是实例(稍后会干扰继承)? 但这没有OP原始代码的行为,即您只能设置一次属性之一...

以上是关于在 Python 中将类实例属性设为只读的主要内容,如果未能解决你的问题,请参考以下文章

QML:在派生类中使属性只读

在 Woocommerce 中将结帐国家/地区下拉列表设为只读

怎么将checkbox,radio,select控件设置为只读,不可选

HTML 可以在 Internet Explorer 中将文本区域设为“只读”吗?

何时应将属性设为私有并设为只读属性? [关闭]

有条件地在 Angular 2 或 4 中将输入字段设为只读:建议 + 最佳/采用哪种方式