2009-11-10 4 views
1

Относительно новый для python. Недавно я опубликовал вопрос о проверке того, что тип данных является логическим. [Use a Descriptor (EDIT: Not a single decorator) for multiple attributes?Duck typing: как бы вы относились к этой ситуации

Ответы, на которые дается ссылка на утиную печать. У меня есть простой пример, и я хочу убедиться, что понимаю. Если мой код:

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 == Ложные или bool1 = = Правда. Когда кто-то неправильно использует мой модуль, т. Е. 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, почему, черт возьми, я бы просто не Validate что bool1 был истинным булевым значением в первую очередь (DRY!)!?!? :-)

Спасибо!

Пол

ответ

2

Обычный стиль Python - это первый подход.

Например, я могу использовать вашу библиотеку с чем-то, что не может решить, идти ли на солнце или на Марс до самого последнего момента. Так что я мог бы передать экземпляр этого класса:

class LastMinuteDecision(object): 

    def __bool__(self): 
     return make_decision_now() 

Если бы вы застряли некоторые тесты в там, думая, что вы знали лучше, чем у меня, как я собирался назвать свою библиотеку, то я не мог сделать это, и я был бы очень раздражен и, вероятно, сказал бы вам прекратить писать Java (или что-то еще) в Python ...

[edit: в случае, если это не ясно, метод __bool__ делает экземпляр «похожим на» булевым. Он вызывается, когда язык ожидает логическое значение.]

Возможно, вы сочтете это сумасшедшим, но это работает на удивление хорошо.

0

Я бы ожидать, что упаковка динамически типизированных значение с классом, который заставляет его быть, по существу, статически типизированных не путь.

Я не эксперт, но я ожидаю, что ваш последний метод будет лучшим (например, проверить true, false или else).

Смежные вопросы