492 Stimmen

Wie kann man prüfen, ob ein Objekt eine Liste oder ein Tupel (aber keine Zeichenkette) ist?

Das ist es, was ich normalerweise tue, um sicherzustellen, dass es sich bei der Eingabe um eine list / tuple - aber nicht ein str . Denn oft bin ich über Bugs gestolpert, bei denen eine Funktion eine str Objekt versehentlich, und die Zielfunktion macht for x in lst unter der Annahme, dass lst ist eigentlich ein list o tuple .

assert isinstance(lst, (list, tuple))

Meine Frage lautet: Gibt es eine bessere Möglichkeit, dies zu erreichen?

2voto

FlipMcF Punkte 12196

Ich tue dies in meinen Testfällen.

def assertIsIterable(self, item):
    #add types here you don't want to mistake as iterables
    if isinstance(item, basestring): 
        raise AssertionError("type %s is not iterable" % type(item))

    #Fake an iteration.
    try:
        for x in item:
            break;
    except TypeError:
        raise AssertionError("type %s is not iterable" % type(item))

Ungetestet auf Generatoren, ich denke, Sie sind bei der nächsten "Ertrag" links, wenn in einem Generator, die Dinge vermasseln kann nachgelagerten übergeben. Aber dann wieder, dies ist ein "unittest

2voto

utobi Punkte 21

Wie wäre es in "Enten-Typing"-Manier mit

try:
    lst = lst + []
except TypeError:
    #it's not a list

oder

try:
    lst = lst + ()
except TypeError:
    #it's not a tuple

bzw Dies vermeidet die isinstance / hasattr Selbstbeobachtung.

Sie können auch den umgekehrten Fall prüfen:

try:
    lst = lst + ''
except TypeError:
    #it's not (base)string

Alle Varianten ändern den Inhalt der Variablen nicht wirklich, sondern implizieren eine Neuzuweisung. Ich bin mir nicht sicher, ob dies unter bestimmten Umständen unerwünscht sein könnte.

Interessant ist, dass bei der Zuordnung "vor Ort" += keine TypeError würde in jedem Fall erhoben werden, wenn lst ist eine Liste (nicht ein Tupel ). Deshalb wird der Auftrag auf diese Weise ausgeführt. Vielleicht kann jemand Licht ins Dunkel bringen, warum das so ist.

2voto

stevepastelan Punkte 1244

Eine weitere Version der Duck-Typisierung, um string-ähnliche Objekte von anderen sequenz-ähnlichen Objekten zu unterscheiden.

Die String-Darstellung von String-ähnlichen Objekten ist der String selbst, so dass Sie prüfen können, ob Sie ein gleiches Objekt von der str Konstrukteur:

# If a string was passed, convert it to a single-element sequence
if var == str(var):
    my_list = [var]

# All other iterables
else: 
    my_list = list(var)

Dies sollte für alle Objekte funktionieren, die mit str und für alle Arten von wiederholbaren Objekten.

1voto

amulllb Punkte 2814

Einfachste Methode... mit any y isinstance

>>> console_routers = 'x'
>>> any([isinstance(console_routers, list), isinstance(console_routers, tuple)])
False
>>>
>>> console_routers = ('x',)
>>> any([isinstance(console_routers, list), isinstance(console_routers, tuple)])
True
>>> console_routers = list('x',)
>>> any([isinstance(console_routers, list), isinstance(console_routers, tuple)])
True

1voto

Juha Untinen Punkte 1643

Python 3 hat dies:

from typing import List

def isit(value):
    return isinstance(value, List)

isit([1, 2, 3])  # True
isit("test")  # False
isit({"Hello": "Mars"})  # False
isit((1, 2))  # False

Um also sowohl für Listen als auch für Tupel zu prüfen, würde es lauten:

from typing import List, Tuple

def isit(value):
    return isinstance(value, List) or isinstance(value, Tuple)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X