2

最好的情况是,我的意思是 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.valueself.__value不鼓励直接访问。

我最近发现(或正在发现)描述符。密切关注这里的精彩讨论,我写了一些看起来像这样的东西:

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

其次,我真正想要的是,

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 类。任何正确方向的帮助或指示将不胜感激。

4

5 回答 5

1

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

可能逃脱

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.

其次,我真正想要的是 [stuff]

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

于 2013-09-20T15:21:56.057 回答
1

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

是的,就是这样。

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

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

描述符完全适合您想要做的事情(自动验证)。关于您可以做出的唯一改进是还使用元类自动为您设置密钥,然后您的类代码如下所示:

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]
于 2013-09-20T15:24:56.810 回答
1

不要自己编写这些东西,而是使用特征库:https ://pypi.python.org/pypi/traits 。使用库是解决大多数问题的 Python 方法。

但是,一般来说,您应该编写足够通用的代码,以至于这种检查在很大程度上是不必要的。在python中很容易做到。

于 2013-09-20T19:10:52.870 回答
0

我认为您正在寻找的是 python 属性。 验证类实例属性的正确方法似乎与您的问题有关。您还可以查看Python 描述符与属性

于 2013-09-20T15:11:33.927 回答
0

听起来你想使用属性

class MyUsefulClass(object):

    def __init__(self):
        self._value = 0

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, value):
        self._value = self.Checker(value, int, 99)

    def Checker(self, value, kind, default):
        return value if isinstance(value, kind) else default
于 2013-09-20T15:12:09.903 回答