Tipo de comprobación de argumentos Python

A veces es necesario verificar los argumentos en Python. por ejemplo, tengo una función que acepta la dirección de otro nodo en la red como la dirección de cadena sin formato o el nodo de clase que encapsula la información del otro nodo.

Yo uso el tipo (0 función como en:

if type(n) == type(Node): do this elif type(n) == type(str) do this 

¿Es esta una buena manera de hacer esto?

Actualización 1: Python 3 tiene anotación para los parámetros de la función. Estos pueden usarse para verificaciones de tipos usando la herramienta: http://mypy-lang.org/

    Utilice isinstance() . Muestra:

     if isinstance(n, unicode): # do this elif isinstance(n, Node): # do that ... 
     >>> isinstance('a', str) True >>> isinstance(n, Node) True 

    También puede usar un retén de prueba para escribir cheque si es necesario:

     def my_function(this_node): try: # call a method/attribute for the Node object if this_node.address: # more code here pass except AttributeError, e: # either this is not a Node or maybe it's a string, # so behavior accordingly pass 

    Puedes ver un ejemplo de esto en Beginning Python en el segundo sobre generadores (página 197 en mi edición) y creo en el libro de cocina de Python . Muchas veces la captura de un AttributeError o TypeError es más simple y aparentemente más rápida. Además, puede funcionar mejor de esta manera porque entonces no está vinculado a un árbol de herencia particular (por ejemplo, su objeto podría ser un Node o podría ser otro objeto que tenga el mismo comportamiento que un Node ).

    Suena como si estuvieras buscando una “función genérica”, una que se comporte de manera diferente según los argumentos dados. Es un poco como la forma en que obtendrás una función diferente cuando llamas a un método en un objeto diferente, pero en lugar de usar el primer argumento (el objeto / yo) para buscar la función, en su lugar, utilizas todos los argumentos.

    Turbogears usa algo como esto para decidir cómo convertir objetos a JSON, si recuerdo bien.

    Hay un artículo de IBM sobre el uso del paquete de despachador para este tipo de cosas:

    De ese artículo:

     import dispatch @dispatch.generic() def doIt(foo, other): "Base generic function of 'doIt()'" @doIt.when("isinstance(foo,int) and isinstance(other,str)") def doIt(foo, other): print "foo is an unrestricted int |", foo, other @doIt.when("isinstance(foo,str) and isinstance(other,int)") def doIt(foo, other): print "foo is str, other an int |", foo, other @doIt.when("isinstance(foo,int) and 3<=foo<=17 and isinstance(other,str)") def doIt(foo, other): print "foo is between 3 and 17 |", foo, other @doIt.when("isinstance(foo,int) and 0<=foo<=1000 and isinstance(other,str)") def doIt(foo, other): print "foo is between 0 and 1000 |", foo, other 

    No, no es necesario revisar los argumentos en Python. Nunca es necesario.

    Si su código acepta direcciones como rawstring o como un objeto Node , su diseño se rompe.

    Eso se debe al hecho de que si no conoce el tipo de objeto en su propio progtwig, entonces ya está haciendo algo mal.

    La comprobación de tipos daña la reutilización del código y reduce el rendimiento. Tener una función que realiza diferentes cosas dependiendo del tipo de objeto pasado es propenso a errores y tiene un comportamiento más difícil de entender y mantener.

    Tienes las siguientes opciones de saner:

    1. Cree un constructor de objetos Node que acepte cadenas sin formato o una función que convierta cadenas en objetos Node . Haz que tu función asum que el argumento pasado es un objeto Node . De esa manera, si necesita pasar una cadena a la función, simplemente haga lo siguiente:

       myfunction(Node(some_string)) 

      Esa es su mejor opción, es limpia, fácil de entender y mantener. Cualquiera que lea el código de inmediato comprende lo que está sucediendo, y usted no tiene que revisar a máquina.

    2. Haga dos funciones, una que acepte objetos de Node y otra que acepte cadenas crudas. Puede hacer una llamada a la otra internamente, de la manera más conveniente ( myfunction_str puede crear un objeto Node y llamar a myfunction_node , o al revés).

    3. Los objetos Make Node tienen un método __str__ y dentro de su función, llame a str() en el argumento recibido. De esa manera siempre obtienes una cuerda por coerción.

    En cualquier caso, no hay que revisar . Es completamente innecesario y solo tiene desventajas. Refactorice su código en lugar de una manera en la que no necesite verificarlo. Solo obtienes beneficios al hacerlo, tanto a corto como a largo plazo.