对多个属性使用描述符(编辑:不是单个装饰器)?

时间:2009-11-10 14:25:04

标签: python decorator descriptor

Python 2.5.4。相当新的Python,昨晚的装饰品全新。如果我有一个具有多个布尔属性的类:

class Foo(object):
    _bool1 = True
    _bool2 = True
    _bool3 = True
    #et cetera

    def __init__():
        self._bool1 = True
        self._bool2 = False
        self._bool3 = True
        #et cetera

有没有办法使用单个装饰器检查任何布尔属性的任何设置必须是布尔值,并返回任何请求的这些变量的布尔值?

换句话说,与每个属性的相似内容相反?

def bool1():
    def get_boo1():
        return self._bool1
    def set_bool1(self,value):
        if value <> True and value <> False:
            print "bool1 not a boolean value. exiting"
            exit()
        self._bool1=value
    return locals()
bool1 = property(**bool1())

#same thing for bool2, bool3, etc...

我试着把它写成这样的东西:

def stuff(obj):
    def boolx():
        def fget(self):
            return obj
        def fset(self, value):
            if value <> True and value <> False:
                print "Non-bool value" #name of object???
                exit()
            obj = value
        return locals()
    return property(**boolx())

bool1 = stuff(_bool1)
bool2 = stuff(_bool2)
bool3 = stuff(_bool3)

给了我:

File "C:/PQL/PythonCode_TestCode/Tutorials/Decorators.py", line 28, in stuff
    return property(**boolx())
TypeError: 'obj' is an invalid keyword argument for this function

有关如何正确执行此操作的任何指示?

谢谢,

2 个答案:

答案 0 :(得分:3)

您可以尝试使用descriptor

class BooleanDescriptor(object):
    def __init__(self, attr):
        self.attr = attr

    def __get__(self, instance, owner):
      return getattr(instance, self.attr)

    def __set__(self, instance, value):
      if value in (True, False):
        return setattr(instance, self.attr, value)
      else:
        raise TypeError


class Foo(object):
    _bar = False
    bar = BooleanDescriptor('_bar')

编辑:

正如S.Lott所提到的,python更喜欢Duck Typing而不是类型检查。

答案 1 :(得分:2)

两件重要的事情。

首先,“类级”属性由类的所有实例共享。就像Java中的static一样。如果您真的在谈论类级属性,那么您的问题就不清楚了。

通常,大多数面向对象编程都是使用实例变量完成的,如下所示。

class Foo(object):
    def __init__():
        self._bool1 = True
        self._bool2 = False
        self._bool3 = True
        #et cetera

第二点。我们不会浪费大量时间来验证论证的类型。

如果一个神秘的“某人”提供错误的类型数据,我们的课程将崩溃,这几乎是最好的结果。

使用类型和域验证进行操作是很多工作,可以让您的类在不同的地方崩溃。最终,异常(TypeError)是相同的,因此额外的检查结果几乎没有实际价值。

事实上,当有人创建bool的替代实现时,额外的域检查可能(通常会)适得其反,而您的类拒绝这个具有与内置bool相同功能的完全有效的类

不要将人工输入范围检查与Python类型检查混为一谈。人工输入(或您从文件或URI中读取的内容)必须范围选中,但不能选中类型。读取外部数据的应用程序部分定义了类型。无需检查类型。不会有任何谜团。

“如果我使用了错误的类型,我的程序似乎可以工作,但没有”情况实际上没有任何意义。首先,找到两种具有相同行为的类型,但产生略微不同的结果。唯一的例子是intfloat,唯一重要的是围绕除法,这是由两个分部操作员处理的。

如果您“意外”使用需要编号的字符串,您的程序将会死亡。可靠。一致。