鸭子打字:你会怎么对待这种情况

时间:2009-11-10 16:29:50

标签: dry duck-typing

python相对较新。我最近发布了一个关于验证数据类型是否为布尔值的问题。 [Use a Descriptor (EDIT: Not a single decorator) for multiple attributes?

给出的答案引用了鸭子打字。我有一个简单的例子,想确保我理解。如果我的代码是:

class Foo4(object):
    def __init__(self):
        self.bool1=True

    def send_rocket(self, bool_value):
        if not bool_value:
            print "Send rocket ship to sun first... bad move."
         print "Send rocket ship to Mars... good move."

f=Foo4()
f.send_rocket(f.bool1) 
#Send rocket ship to Mars... good move.

f.bool1=None
f.send_rocket(f.bool1) 
#Send rocket ship to sun first... bad move.
#Send rocket ship to Mars... good move.

如果我理解鸭子打字有点正确,在上面的课程中我信任 bool1将永远是一个布尔值:我不应该检查bool1 == False或bool1 == True。当有人错误地使用我的模块时,即bool1 = None,该方法会显示我不想要执行的操作,但没有表明存在问题 ......并且火箭船中的人员死亡。

我可以编写代码以确保bool1始终是一个真正的布尔值的另一种方式是(上面链接中的BooleanDescriptor信用!):

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 Foo4(object):
    def __init__(self):
        self._bool1=True
    bool1 = BooleanDescriptor('_bool1')

    def send_rocket(self, bool_value):
        if not bool_value:
            print "Send rocket ship to sun... bad move."
        print "Send rocket ship to Mars... good move."

f=Foo4()
f.send_rocket(f.bool1)
#Send rocket ship to Mars... good move.

f.bool1=None
#TypeError.
#Never gets here: f.send_rocket(f.bool1)

我是否理解第一种方式(不检查)是正确的方法?我的意思是,我总是可以在第一个例子中明确地编写代码:

    if bool_value ==True:
        print "do something"
    elif bool_value == False:
        print "do something else"
    else:
        print "invalid boolean value"

但是如果我在每个使用bool1的方法中都这样做,为什么我会在第一时间没有验证bool1是一个真正的布尔值(DRY!)!?!? : - )

谢谢!

2 个答案:

答案 0 :(得分:2)

通常的Python风格是第一种方法。

例如,我可能想让你的图书馆使用的东西无法决定是去太阳还是火星,直到最后一刻。所以我可能会传入这个类的实例:

class LastMinuteDecision(object):

    def __bool__(self):
        return make_decision_now()

如果你在那里遇到了一些测试,认为你比我更了解我将如何调用你的库,那么我就不能这样做了,我会非常生气并且可能会告诉你不要再写Java了(在Python中......或者其他)...

[编辑:如果不清楚,__ bool__方法使实例“看起来像”一个布尔值。当语言需要布尔值时调用它。]

你可能会觉得它很疯狂,但它的效果非常好。

答案 1 :(得分:0)

我希望用一个强制它的类来包装一个动态类型的值,基本上是静态类型的,这是不可取的。

我不是专家,但我希望你的最终方法是最好的方法(即检查是否为真,否则)。