2010-04-07 11 views
42

Al usar una función, deseo asegurarme de que el tipo de variables sea el esperado. ¿Cómo hacerlo bien?Forma correcta de afirmar el tipo de variable en Python

Aquí está un ejemplo de función falsa tratando de hacer precisamente esto antes de seguir con su papel:

def my_print(begin, text, end): 
    """Print 'text' in UPPER between 'begin' and 'end' in lower 

    """ 
    for i in (begin, text, end): 
     assert isinstance(i, str), "Input variables should be strings" 
    out = begin.lower() + text.upper() + end.lower() 
    print out 

def test(): 
    """Put your test cases here! 

    """ 
    assert my_print("asdf", "fssfpoie", "fsodf") 
    assert not my_print("fasdf", 33, "adfas") 
    print "All tests passed" 

test() 

Es afirmar el enfoque correcto? ¿Debería usar try/except en su lugar?

Además, no parece mi juego de aserción de pruebas para funcionar correctamente: S

, gracias pythoneers

+7

Creo que ha llegado a la mayor debilidad de Python: no hay forma formal de especificar tipos cuando lo desee. El aspecto menor de este problema es que debe verificar los tipos manualmente (como en su pregunta). El problema más grande es que sus herramientas no pueden ayudarlo. Python sería el lenguaje perfecto si solo admite el tipado dinámico, pero también tiene la opción de especificar tipos cuando no se necesita la dinámica. – Tom

Respuesta

37

La isinstance incorporada es la forma preferida si realmente se debe, pero aún mejor es recordar el lema de Python: "¡es más fácil pedir perdón que permiso!" -) (En realidad fue el lema favorito de Grace Murray Hopper;) Es decir:

def my_print(text, begin, end): 
    "Print 'text' in UPPER between 'begin' and 'end' in lower" 
    try: 
     print begin.lower() + text.upper() + end.lower() 
    except (AttributeError, TypeError): 
     raise AssertionError('Input variables should be strings') 

Esto, por cierto, permite que el trabajo de la función muy bien en las cadenas Unicode - sin ningún esfuerzo adicional -)

+0

¿Hay algún uso para 'afirmar'? En la prueba? – Morlock

+3

'assert' a veces es útil para verificaciones de cordura que solo necesita en la fase de desarrollo (no en código de producción optimizado, donde se optimiza), por lo tanto, no comprueba entradas válidas (las que debe hacer de otra forma), sino cordura verifica tu propia lógica (variantes de bucle, invariantes de clase, etc.) - no relacionadas con el tipo de curso, por supuesto. El marco de prueba de terceros py.test usa 'assert' del mismo modo que el' unittest' estándar usa métodos como 'assertEqual' & c. –

+0

Gracias por la aclaración. – Morlock

7

Es posible que desee probar este ejemplo para la versión 2.6 de Python.

def my_print(text, begin, end): 
    "Print text in UPPER between 'begin' and 'end' in lower." 
    for obj in (text, begin, end): 
     assert isinstance(obj, str), 'Argument of wrong type!' 
    print begin.lower() + begin.upper() + end.lower() 

Sin embargo, ¿ha pensado en dejar que la función falle naturalmente?

+0

Estoy un poco retrógrado y aún estoy usando 2.6: P Gracias por la función 'isinstance()'. – Morlock

+0

La nueva versión debería funcionar ahora con la versión 2.6. –

3

Haciendo type('') está efectivamente equivalente a str y types.StringType

por lo type('') == str == types.StringType evaluará a "True"

Tenga en cuenta que las cadenas Unicode que sólo contienen ASCII fallarán si la comprobación tipos de esta manera, por lo que es posible que desee hacer somethi ng como assert type(s) in (str, unicode) o assert isinstance(obj, basestring), el último de los cuales fue sugerido en los comentarios por 007Brendan y es probablemente preferido.

isinstance() es útil si desea preguntar si un objeto es una instancia de una clase, por ejemplo:

class MyClass: pass 

print isinstance(MyClass(), MyClass) # -> True 
print isinstance(MyClass, MyClass()) # -> TypeError exception 

Pero para los tipos básicos, por ejemplo, str, unicode, int, float, long etc. preguntando type(var) == TYPE funcionará bien.

+2

Puedes hacer - assert isinstance (obj, basetring) - str y unicode ambos heredan de basestring, por lo que esto funcionará para ambos. –

+0

Gracias por esa sugerencia: la he agregado a la respuesta. – cryo

Cuestiones relacionadas