python - 使用 Python 描述符 : How best to write a general validation getter-setter

标签 python oop validation descriptor

最好的情况是,我指的是 Python 方式和尽可能少的代码行。

我习惯像这样在 Python 中定义带有属性的类。

class MyClass(object):

    def __init__(self):
        self.value = 5

但是,我经常发现自己需要确保 self.value 只能采用特定类型的值。过去(来自 PHP OOP 背景)我使用类似于此的 getter-setter 方法完成此操作:

    def value(self, new_value = -1)
        if new_value == -1:
            return self.value
        if isinstance(new_value, int) and new_value > -1:
            self.value = new_value
        else:
            raise TypeError

然后我使用 self.value() 访问 self.value,并使用 self.value(67) 设置它。通常我会将 self.value 命名为 self.__value 以阻止其直接访问。

我最近发现(或正在发现)描述符。密切关注 excellent discussion here我写了一些看起来像这样的东西:

class ValidatedAttribute(object):

    def __init__(self, key, kind):
        self.key = key
        self.kind = kind

    def __get__(self, instance, owner):
        if self.key not in instance.__dict__:
            raise AttributeError, self.key
        return instance.__dict__[self.key]

    def __set__(self, instance, value):
        if not isinstance(value, self.kind):
            raise TypeError, self.kind
        instance.__dict__[self.key] = value     


class MyUsefulClass(object):

    a = ValidatedAttribute("a", int)

但我有几个问题!

首先,MyUsefulClass().a 到底是什么?它是以某种方式绑定(bind)到 MyUsefulClass 类实例的 ValidatedAttribute 类实例吗?

其次,我真正喜欢的是,

class MyUsefulClass(object):

    def __init__(self):
        self.value = Checker(int, 99)

    def Checker(self, kind, default):
        # Code for verifying that associated attribute is of type kind.

并以某种方式将属性访问绑定(bind)到某种拦截方法,而无需使用整个其他描述符类。

如果我的理解不够,我很抱歉 - 我仍在掌握新型 Python 类。任何正确方向的帮助或指示将不胜感激。

最佳答案

Firstly, what exactly is MyUsefulClass().a? Is it an instance of a ValidatedAttribute class somehow bound to an instance of a MyUsefulClass class?

是的,就是这样。

And secondly, what I'd really like is something like [...] and somehow bind an attribute access to some sort of intercept method, without having to use a whole other descriptor class.

好吧,您可以覆盖 __getattribute__,因为它会拦截每个 属性查找,但它比使用描述符要复杂得多。

描述符正是您想要做的(自动验证)。您可以做的唯一改进是还使用元类自动为您设置 key ,然后您的类代码如下所示:

class MyUsefulClass(object):

    a = ValidatedAttribute(int)

但首先要熟悉描述符,元类很复杂并且很难理解。

哦,还有我要对您的 ValidatedAttribute 做的一个小改动:

def __init__(self, key, default):

    self.key = key
    self.kind = type(default)
    self.default = default

def __get__(self, instance, owner):
    if self.key not in instance.__dict__:
        return self.default
    return instance.__dict__[self.key]

关于python - 使用 Python 描述符 : How best to write a general validation getter-setter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18919961/

相关文章:

python - 允许 sudo 访问 celery worker

C++ 在命名管道中发送对象

javascript - (IE9) jQuery 验证错误垂直减半

python - 用于 OCR 的场景文本图像超分辨率

python - 使用 selenium 运行 django-test 时管道错误

python - 请求之间 Django 中对象的对象存储

c# - POCO Entity Framework 和多态性

javascript - facebook api回调的上下文?

来自 Google App Engine 注销链接的验证错误

c - 如何在不使用 isalpha 的情况下验证 C 中的名称?