首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Python描述符:如何最好地编写通用验证getter-setter

使用Python描述符:如何最好地编写通用验证getter-setter
EN

Stack Overflow用户
提问于 2013-09-20 15:01:16
回答 5查看 1.6K关注 0票数 2

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

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

代码语言:javascript
复制
class MyClass(object):

    def __init__(self):
        self.value = 5

然而,我经常发现自己需要确保self.value只能接受特定类型的值。在过去(来自PHP背景),我使用getter-setter方法完成了这一工作,类似于这样:

代码语言:javascript
复制
    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)设置它。通常,我会将mangle self.value命名为self.__value,以阻止其直接访问。

我最近发现了(或正在发现)描述符。紧跟在很好的讨论之后,我编写了如下所示的东西:

代码语言:javascript
复制
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到底是什么?它是否是ValidatedAttribute类的实例,以某种方式绑定到MyUsefulClass类的实例?

其次,我真正想要的是,

代码语言:javascript
复制
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.

并以某种方式将属性访问绑定到某种类型的拦截方法,而不必使用整个其他描述符类。

如果我缺乏理解,我很抱歉--我仍然在处理新风格的Python类。任何正确方向的帮助或指示都将不胜感激。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-09-20 15:24:56

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

是的,就是这样。

其次我真正想要的是.并以某种方式将属性访问绑定到某种类型的拦截方法,而不必使用整个其他描述符类。

好的,您可以覆盖__getattribute__,就像它可以阻止每个属性查找一样,但是它比使用描述符要复杂得多。

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

代码语言:javascript
复制
class MyUsefulClass(object):

    a = ValidatedAttribute(int)

但是首先要适应描述符,元类是复杂的,很难理解。

哦,我想给你的ValidatedAttribute做个小小的改变

代码语言:javascript
复制
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]
票数 1
EN

Stack Overflow用户

发布于 2013-09-20 15:21:56

请,请,请不要做isinstance(new_value, int)

你可能会可能会逃脱

代码语言:javascript
复制
from numbers import Integral
isinstance(new_value, Integral)

但这是完全令人讨厌的鸭子打字。

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

为了找到MyUsefulClass().a,Python询问了类。这个类告诉它它有一个属性的getter-setter,并告诉Python询问属性。属性说找到它,然后告诉类属性是什么。属性不是getter-setter。

MyUsefulClass.a是getter-setter (属性),而不是MyUsefulClass().a

其次,我真正想要的是类似的东西

AFAIK,您只能在类上设置属性,而不能设置实例,因为您如何知道是检索属性还是属性阴影项?

票数 1
EN

Stack Overflow用户

发布于 2013-09-20 19:10:52

与其自己编写这些东西,不如使用特性库:https://pypi.python.org/pypi/traits。使用库是解决大多数问题的pythonic方法。

但是,一般来说,您应该编写足够通用的代码,这样的检查基本上是不必要的。这在python中很容易做到。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18919961

复制
相关文章

相似问题

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