2010-04-07 8 views
42

Nell'utilizzo di una funzione, desidero garantire che il tipo di variabili sia come previsto. Come farlo bene?Modo corretto per affermare il tipo di variabile in Python

Qui è una funzione di falso esempio cercando di fare proprio questo prima di andare avanti con il suo ruolo:

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() 

È affermare l'approccio giusto? Dovrei usare try/except invece?

Inoltre, la mia asserzione serie di test non sembra funzionare correttamente: S

Grazie pythoneers

+7

Penso che tu abbia colto la più grande debolezza di Python: nessun modo formale per specificare i tipi quando vuoi. L'aspetto minore di questo problema è che devi controllare i tipi manualmente (come nella tua domanda). Il problema più grande è che i tuoi strumenti non possono aiutarti. Python sarebbe il linguaggio perfetto se solo supportasse la digitazione dinamica, ma avesse anche la possibilità di specificare i tipi quando la dinamica non era necessaria. – Tom

risposta

37

Il isinstance integrato è il modo preferito se proprio devi, ma ancora meglio è ricordare il motto di Python: "è più facile chiedere perdono che permesso"! -) (In realtà era il motto preferito di Grace Murray Hopper;). Vale a dire:!

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') 

questo, BTW, lascia il lavoro di funzione bene su stringhe Unicode -, senza alcuno sforzo aggiuntivo -)

+0

C'è qualche uso per 'assert' allora? Nel test? – Morlock

+3

'assert' a volte è utile per i controlli di integrità che sono necessari solo nella fase di sviluppo (non nel codice di produzione ottimizzato, dove viene ottimizzato) - quindi, non controlla gli input validi (quelli che devi fare altrimenti), ma sanità mentale controlla la tua logica (varianti del ciclo, invarianti di classe, ecc.) - non in relazione al tipo, naturalmente. Il framework di test di terze parti py.test usa 'assert' nel modo in cui lo standard' unittest' usa metodi come 'assertEqual' & c. –

+0

Grazie per il chiarimento. – Morlock

7

Si potrebbe desiderare di provare questo esempio per la versione 2.6 di 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() 

Tuttavia, hai considerato di lasciare che la funzione fallisca in modo naturale, invece?

+0

Sono un po 'retrogrado e sto ancora usando 2.6: P Grazie per la funzione' isinstance() '. – Morlock

+0

La nuova versione dovrebbe funzionare ora con la versione 2.6. –

3

Facendo type('') è effettivamente equivalente a str e types.StringType

così type('') == str == types.StringType valuterà a "True"

Si noti che le stringhe Unicode che contengono solo ASCII falliranno se si controllano i tipi in questo modo, quindi si consiglia di fare somethi ng come assert type(s) in (str, unicode) o assert isinstance(obj, basestring), l'ultimo dei quali è stato suggerito nei commenti da 007Brendan ed è probabilmente preferito.

isinstance() è utile se si vuole chiedere se un oggetto è un'istanza di una classe, per esempio:

class MyClass: pass 

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

Ma per i tipi di base, ad esempio, str, unicode, int, float, long ecc. Chiedendo type(var) == TYPE funzionerà OK.

+2

Puoi fare - asserire isinstance (obj, basestring) - str e unicode entrambi ereditano da basestring, quindi funzionerà per entrambi. –

+0

Grazie per il suggerimento - l'ho aggiunto alla risposta. – cryo

Problemi correlati