首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何对只读实例属性执行输入验证?

如何对只读实例属性执行输入验证?
EN

Stack Overflow用户
提问于 2021-12-15 17:20:42
回答 1查看 143关注 0票数 2

here发布了一个非常类似的问题,但是没有被接受的答案,也没有代码示例,我真的不喜欢使用外部库的想法,因为这里提供的答案只有一个。

以下代码允许定义只读实例属性:

代码语言:javascript
复制
class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

    @property
    def x(self):
        return self._x

    @property
    def y(self):
        return self._y

但是我也想验证用户的输入。我想验证xy是否有正确的类型。

做这件事的最有效的方法是什么?如果我提供setter,则属性不再是只读的。

在构造函数中执行输入验证是唯一的方法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-15 19:50:50

下面是一种优雅和节奏式的方法,它使用工厂函数来创建属性:

代码语言:javascript
复制
class ReadOnlyError(Exception):
    """Attempt made to assign a new value to something that can't be changed."""


# Based on recipe in book "Python Cookbook 3rd Edition" - section 9.21 -
# titled "Avoiding Repetitive Property Methods".
def readonly_typed_property(name, expected_type):
    storage_name = '_' + name

    @property
    def prop(self):
        return getattr(self, storage_name)

    @prop.setter
    def prop(self, value):
        if hasattr(self, storage_name):
            raise ReadOnlyError('{!r} is read-only!'.format(name))
        if not isinstance(value, expected_type):
            raise TypeError('{!r} must be a {!r}'.format(name, expected_type.__name__))
        setattr(self, storage_name, value)

    return prop


class Point:
    x = readonly_typed_property('x', int)
    y = readonly_typed_property('y', int)

    def __init__(self, x, y):
        self.x = x
        self.y = y


if __name__ == '__main__':
    try:
        p1 = Point(1, 2)
    except Exception as e:
        print('ERROR: No exception should have been raised for case 1.')
        print(e)
    else:
        print('As expected, NO exception raised for case 1.')

    print()
    try:
        p2 = Point('1', 2)
    except TypeError as e:
        print(e)
        print(f'As expected, {type(e).__name__} exception raised for case 2.')
    else:
        print('ERROR: expected TypeError exception not raised for case 2')

    print()
    try:
        p1.x = 42
    except Exception as e:
        print(e)
        print(f'As expected, {type(e).__name__} exception raised for case 3.')
    else:
        print('ERROR: expected ReadOnlyError exception not raised for case 3')
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70367781

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档