2012-06-02 15 views
5

He estado tratando de descifrar esto durante las últimas horas, y estoy a punto de darme por vencido.Python comprobando el parámetro __init__

¿Cómo se asegura de que en python solo un criterio específico coincidente creará el objeto?

Por ejemplo, supongamos que quiero crear un objeto Mano, e inicializar una Mano solo cuando tengo suficientes dedos en el inicializador? (Por favor, sólo tomar esto como una analogía)

Say,

class Hand: 
    def __init__(self, fingers): 
    # make sure len(fingers)==5, and 
    #only thumb, index, middle, ring, pinky are allowed in fingers 
    pass 

Gracias.

Estas son las preguntas más cercanas que encontré, pero una está en C++, la otra no responde mi pregunta.

checking of constructor parameter

How to overload __init__ method based on argument type?

+1

¿Qué desea que suceda si este no es el caso? ¿Quieres que genere algún tipo de excepción? – BrenBarn

+0

Supongo que sería una buena manera. Solo para asegurarme de que no creo un objeto equivocado. – chemelnucfin

Respuesta

5

Usted tiene que definir __new__ para ello:

class Foo(object): 
    def __new__(cls, arg): 
     if arg > 10: #error! 
      return None 
     return super(Foo, cls).__new__(cls) 

print Foo(1) # <__main__.Foo object at 0x10c903410> 
print Foo(100) # None 

Dicho esto, el uso de __init__ y lanzar una excepción en Inva tapa args es generalmente mucho mejor:

class Foo(object): 
    def __init__(self, arg): 
     if arg > 10: #error! 
      raise ValueError("invalid argument!") 
     # do stuff 
+5

La definición de '__new__' rara vez es necesaria, y devolver' None' es horrible. Solo lanza una excepción en lugar de continuar por un par de líneas (o una docena de llamadas a función, si tienes mala suerte) antes de que se cuelgue con un error inexplicable. – delnan

+0

@delnan: técnicamente, si el OP es serio acerca de "solo un criterio específico coincidente creará el objeto", sería necesario definir '__new__', porque para cuando se llama' __init__' ya se ha creado un objeto (aún tienes razón en que plantear una excepción en '__new__' sería mejor que devolver None). Pero supongo que OP no significa realmente eso, en cuyo caso la versión '__init__' es definitivamente mejor. – weronika

+0

@weronika A menos que se trate de magia profunda y hacking horrible, la publicación de una excepción en '__init__' impide que todos obtengan una referencia al objeto no realmente construido. Por lo tanto, desde el punto de vista de un observador no hay diferencia, además de que uno es una API terrible. – delnan

0

Trate afirmando:

class Hand(object): 
    def __init__(self,fingers): 
     assert len(fingers) == 5 
     for fing in ("thumb","index","middle","ring","pinky"): 
      assert fingers.has_key(fing) 
+4

No, 'assert' es para verificar invariantes * internos *: Comprobar que * su * código no está horriblemente roto. 'AssertionError' no transmite información útil a la persona que llama, y ​​puede hacer que piense que su código está roto. Además, las aserciones son eliminadas por '-O'. Lanza un 'ValueError' o' RuntimeError' o lo que sea apropiado para el caso de uso específico. – delnan

Cuestiones relacionadas