2009-11-10 4 views
1

Relativement nouveau à python. J'ai récemment posté une question concernant la validation qu'un type de données est booléen. [Use a Descriptor (EDIT: Not a single decorator) for multiple attributes?Dactylographie: comment traiteriez-vous cette situation?

Les réponses données pour le typage du canard. J'ai un exemple simple, et je veux être sûr de comprendre. Si mon code est:

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. 

Si je comprends un peu de canard taper correctement, dans la classe au-dessus, je confiance que Bool1 sera toujours une valeur booléenne: je ne devrais pas vérifier si bool1 == Faux ou bool1 = = True. Quand quelqu'un utilise mon module incorrectement, ie, bool1 = None, la méthode exectue quelque chose que je n'aurais pas voulu faire sans indication qu'il y avait un problème ... et les gens de la fusée meurent.

Une autre façon que je aurais pu écrire le code pour assurer bool1 est toujours un vrai booléen serait (crédits pour BooleanDescriptor en lien ci-dessus!):

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) 

Est-ce que je comprends la première voie à suivre (non vérification) est la bonne façon de faire? Je veux dire, je pourrais toujours avoir écrit le code explicitement dans le premier exemple que:

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

Mais si je fais cela dans toutes les méthodes et ainsi de suite où j'utilise bool1, pourquoi diable aurais-je tout simplement pas validate que bool1 était une vraie valeur booléenne en premier lieu (DRY!)!?!? :-)

Merci!

Paul

Répondre

2

Le style Python habituel est la première approche. Par exemple, je peux vouloir utiliser votre bibliothèque avec quelque chose qui ne peut pas décider d'aller au soleil ou de mars jusqu'au tout dernier moment. Je pourrais donc passer dans une instance de cette classe:

class LastMinuteDecision(object): 

    def __bool__(self): 
     return make_decision_now() 

Si vous aviez coincé des tests là-dedans, pensant que vous saviez mieux que moi comment je vais appeler votre bibliothèque, alors je ne pouvais pas le faire, et je serais très ennuyé et probablement vous dire d'arrêter d'écrire Java (ou autre) en Python ...

[edit: dans le cas où ce n'est pas clair, la méthode __bool__ rend l'instance "ressembler" à un booléen. Il est appelé quand le langage attend une valeur booléenne.]

Vous pourriez penser que c'est fou, mais cela fonctionne étonnamment bien.

0

Je pense que l'emballage d'une valeur typée dynamiquement avec une classe qui l'oblige à être, pour l'essentiel, statiquement typé n'est pas le chemin à parcourir.

Je ne suis pas un expert, mais je m'attends à ce que votre méthode finale soit la meilleure (c'est-à-dire vérifier si vrai, faux ou autre).

Questions connexes