开发者

Duck typing: how would you treat this situation

Relatively new to python. I recently posted a question in regards to validating that a data type is boolean. [Use a Descriptor (EDIT: Not a single decorator) for multiple attributes?

The answers given referenced duck typing. I have a simple example, and want to make sure I understand. If my code is:

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.

If I understand duck typing somewhat correctly, in the above class I trust that bool1 will always be a boolean value: I should not be checking whether bool1 == False or bool1 == True. When someone uses my module incorrectly, ie, bool1 = None, the method exectues something I would not have wanted performed without indication there was a problem... and the people in the rocketship die.

Another way I could have written the code to ensure bool1 is always a true boolean would be (credits for BooleanDescriptor in link above!):

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)

Do I understand the first way to go (not checking) is the correct way to go? I mean, I could always have written the code explicitly in the first exampl开发者_StackOverflowe as:

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

But if I do that in every method et cetera where I use bool1, why in the heck would I just not have validate that bool1 was a true boolean value in the first place (DRY!)!?!? :-)

Thanks!

Paul


The usual Python style is the first approach.

For example, I may want to use your library with something that cannot decide whether to go to the sun or to mars until the very last moment. So I might pass in an instance of this class:

class LastMinuteDecision(object):

    def __bool__(self):
        return make_decision_now()

If you had stuck some tests in there, thinking you knew better than me how I was going to call your library, then I couldn't do that, and I would be very annoyed and probably tell you to stop writing Java (or whatever) in Python...

[edit: in case it's not clear, the __bool__ method makes the instance "look like" a boolean. It is called when the language expects a boolean value.]

You might think it crazy, but it works surprisingly well.


I'd expect that wrapping a dynamically typed value with a class that forces it to be, essentially, statically typed is not the way to go.

I'm not an expert, but I expect that your final method is the best one (i.e. check for true, false, or else).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜