2010-04-07 10 views
42

Bei der Verwendung einer Funktion möchte ich sicherstellen, dass der Typ der Variablen wie erwartet ist. Wie geht es richtig?Korrekte Art, den Typ der Variablen in Python zu bestätigen

Hier ist ein Beispiel gefälschte Funktion nur versuchen, dies zu tun, bevor er mit seiner Rolle los:

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

ist der richtige Ansatz behaupten? Sollte ich stattdessen try/except verwenden?

Auch meine assert Reihe von Tests scheint nicht richtig zu funktionieren: S

Dank pythoneers

+7

Ich denke, Sie haben auf die größte Schwäche von Python getroffen: keine formale Möglichkeit, Typen zu spezifizieren, wenn Sie wollen. Der kleinere Aspekt dieses Problems ist, dass Sie Typen manuell überprüfen müssen (wie in Ihrer Frage). Das größere Problem ist, dass Ihre Tools Ihnen nicht helfen können. Python wäre die perfekte Sprache, wenn es nur die dynamische Typisierung unterstützt, aber auch die Möglichkeit, Typen anzugeben, wenn keine dynamische benötigt wird. – Tom

Antwort

37

Die isinstance integrierte ist die bevorzugte Möglichkeit, wenn Sie wirklich müssen, aber noch besser ist, Python Motto zu erinnern: "Es ist einfacher zu bitten, Vergebung als Erlaubnis"! -) (Es war eigentlich Grace Murray Hopper Lieblings-Motto; -). Dh: Diese

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

, BTW, können die Funktion gut funktionieren auf Unicode-Strings - ohne zusätzlichen Aufwand -)

+0

Gibt es irgendeine Verwendung für 'Assert' dann? Beim Testen? – Morlock

+3

'Assert' ist manchmal nützlich für Plausibilitätsprüfungen, die Sie nur in der Entwicklungsphase brauchen (nicht im optimierten Produktionscode, wo es wegoptimiert wird) - also keine Überprüfung gültiger Eingaben (die Sie sonst machen müssen), aber Vernunft überprüft Ihre eigene Logik (Loop-Varianten, Klasseninvarianten, etc.) - natürlich nicht typbezogen. Das Drittanbieter-Testframework py.test verwendet 'assert', wie der Standard-'einheitstest' Methoden wie' assertEqual' & c verwendet. –

+0

Danke für die Klarstellung. – Morlock

7

Vielleicht möchten Sie dieses Beispiel für die Version 2.6 von Python versuchen.

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

Haben Sie jedoch in Betracht gezogen, die Funktion stattdessen auf natürliche Weise ausfallen zu lassen?

+0

Ich bin ein bisschen retrograd und benutze immer noch 2.6: P Danke für die 'isinstance()' Funktion. – Morlock

+0

Die neue Version sollte jetzt mit der Version 2.6 funktionieren. –

3

Doing type('') effektiv äquivalent zu str und types.StringType

so type('') == str == types.StringType ""

Beachten Sie, dass Unicode-Zeichenfolgen, die nur ASCII enthalten, fehlschlagen, wenn Sie Typen auf diese Weise überprüfen, also möchten Sie vielleicht somethi tun ng wie assert type(s) in (str, unicode) oder assert isinstance(obj, basestring), letzteres wurde in den Kommentaren von 007 Brendan vorgeschlagen und ist wahrscheinlich bevorzugt.

isinstance() ist nützlich, wenn Sie, ob ein Objekt fragen wollen, ist eine Instanz einer Klasse, z:

class MyClass: pass 

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

Aber für Grundtypen, z.B. str, unicode, int, float, long etc Fragen type(var) == TYPE wird funktionieren OK.

+2

Sie können tun - assert isinstance (obj, basestring) - str und unicode erben beide von basestring, so dass dies für beide funktioniert. –

+0

Danke für diesen Vorschlag - Ich habe es der Antwort hinzugefügt. – cryo

Verwandte Themen