2010-04-07 9 views
42

Korzystając z funkcji, chcę się upewnić, że typ zmiennych jest zgodny z oczekiwaniami. Jak to zrobić dobrze?Prawidłowy sposób potwierdzenia typu zmiennej w języku Python

Oto przykład fałszywa funkcja próbuje robić tylko to przed udaniem się ze swojej roli:

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

Czy dochodzić właściwe podejście? Czy powinienem użyć polecenia try/except?

Również moja assert zestaw testów nie wydaje się działać prawidłowo: S

Dzięki pythoneers

+7

Wydaje mi się, że udało Ci się osiągnąć największą słabość Pythona: brak formalnego sposobu określania typów, kiedy chcesz. Mniejszy aspekt tego problemu polega na ręcznym sprawdzaniu typów (jak w pytaniu). Większy problem polega na tym, że twoje narzędzia nie mogą ci pomóc. Python byłby idealnym językiem, gdyby tylko obsługiwał dynamiczne pisanie, ale miał również opcję określania typów, gdy dynamiczne nie było potrzebne. – Tom

Odpowiedz

37

Wbudowany jest preferowany sposób, jeśli naprawdę trzeba, ale jeszcze lepiej jest pamiętać motto Pythona: "łatwiej jest prosić o przebaczenie niż pozwolenie"! -) (było to ulubione motto Grace Murray Hopper;). Tj:

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

To BTW, umożliwia pracę funkcji dobrze na Unicode - bez dodatkowego wysiłku -)

+0

Czy jest zatem jakiś pożytek z "asert"? W testowaniu? – Morlock

+3

'assert' jest czasem przydatna do kontroli poczytalności, której potrzebujesz tylko w fazie rozwoju (nie w zoptymalizowanym kodzie produkcyjnym, gdzie jest zoptymalizowany) - więc nie sprawdza poprawnych danych wejściowych (tych, które musisz zrobić inaczej), ale zdrowego rozsądku sprawdza własną logikę (warianty pętli, niezmienniki klas itd.) - oczywiście nie w odniesieniu do typu. Zewnętrzny framework testowy py.test używa 'assert' w taki sam sposób, w jaki standardowe' unittest' używa takich metod jak 'assertEqual' i c. –

+0

Dziękuję za wyjaśnienia. – Morlock

7

może chcesz wypróbować ten przykład dla wersji 2.6 Pythona.

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

Czy zastanawiałeś się jednak nad tym, czy funkcja oczywiście nie działa poprawnie?

+0

Jestem nieco wsteczny i nadal używam 2.6: P Dzięki za funkcję "isinstance()". – Morlock

+0

Nowa wersja powinna teraz działać z wersją 2.6. –

3

Doing type('') skutecznie równoważne str i types.StringType

tak type('') == str == types.StringType przetestuje na "True"

Pamiętaj, że ciągi znaków Unicode, które zawierają tylko kod ASCII, nie będą działać, jeśli sprawdzasz typy w ten sposób, więc możesz chcieć coś zrobić ng jak assert type(s) in (str, unicode) lub assert isinstance(obj, basestring), ten ostatni został zasugerowany w komentarzach przez 007Brendan i jest prawdopodobnie preferowany.

isinstance() jest przydatna, jeśli chcesz zapytać, czy obiekt jest instancją klasy, np:

class MyClass: pass 

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

Ale dla podstawowych typów, na przykład str, unicode, int, float, long itd. Pytanie o numer type(var) == TYPE będzie działać poprawnie.

+2

Możesz zrobić - assert isinstance (obj, basestring) - str i unicode zarówno dziedziczą z basestring, więc to będzie działać dla obu. –

+0

Dzięki za tę sugestię - dodałem ją do odpowiedzi. – cryo

Powiązane problemy