【问题标题】:Validation of read-only attributes [duplicate]验证只读属性
【发布时间】:2018-06-04 12:49:22
【问题描述】:

我想在类的属性设置器中进行一些验证。此属性必须在对象创建期间设置,然后它需要从外部只读。

我找到了以下解决方案,我想知道是否有更直接或 Pythonic 的方法来做到这一点。 (我知道通过从外部调用 user._username 仍然可以设置此属性,但是“我们都是同意的成年人”等 - 重要的是 user.username 不应该有设置器)。

class User:
    def __init__(self, username):
        self._usernname = username

    @property
    def username(self):
        return self.__username

    @property
    def _username(self):
        return self.__username

    @_username.setter
    def _username(self, value):
        if not value or len(value) < 3:
            raise ValueError('Invalid username')
        self.__username = value

编辑:除了此处的 cmets,还可在此处找到构造函数中的验证选项:numpy performance and random numbers

【问题讨论】:

  • 只需在构造函数中使用一个下划线检查要存储到_username 中的值,然后完全删除_username 属性...
  • __init__ 方法中进行所有初始化/验证。额外的 _username 属性看起来非常虚假,没有实际用途。
  • 谢谢@AnttiHaapala,但是如果没有_username 属性,我在哪里可以验证这个值?
  • @SamuBalogh。只需将 setter 验证代码移动到 __init__ 并进行相应调整。去掉两个_username属性函数。
  • @SamuBalogh,_username 属性是 internal 并且应该没有面向外部的 api。它只在__init__ 中设置一次,因此没有必要为它创建属性。

标签: python validation properties


【解决方案1】:

你的例子很有趣,因为你们都需要只读(这就是你创建只读属性门面username的原因)和验证 (这就是为什么您还要为内部属性 _username 创建一个属性,并使用 setter)。

您可以使用pyfields 高效地做同样的事情:

from pyfields import field

class User(object):
    username = field(read_only=True, 
                     validators={'should contain more than 2 characters': lambda s: len(s) > 2})

u = User()
u.username = "earthling"
print("Hello %s !\n" % u.username)
print(vars(u))
print()
u.username = "earthling2"  # <-- raises error

产量

Hello earthling !

{'_username': 'earthling'}

pyfields.core.ReadOnlyFieldError: 
   Read-only field '<...>.User.username' has already been initialized on 
   instance <<...>.User object at 0x0000022895908EF0> and cannot be modified anymore.

它与您手动执行的操作基本相似,只是它依赖于描述符而不是属性(descriptor 是 python 在属性中幕后使用的低级协议)。此外,它只依赖于一个“嵌套”级别:内部属性_username 是一个普通的旧属性,正如上面ekhumoro 的评论所暗示的那样。

详情请见pyfields documentation

【讨论】:

    猜你喜欢
    • 2014-04-25
    • 1970-01-01
    • 2022-01-18
    • 2019-08-25
    • 2010-11-22
    • 1970-01-01
    • 2014-08-22
    • 2015-02-01
    相关资源
    最近更新 更多