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).
精彩评论