W Pythonie, jaki jest najlepszy sposób sprawdzenia, czy zmienna zawiera listę lub krotkę? (tj. kolekcja)
Czy jest isinstance()
tak złe, jak tutaj sugerowano? http://www.canonical.org/~kragen/isinstance/
Aktualizacja: najczęstszym powodem, dla którego chcę odróżnić listę od łańcucha jest to, że mam nieskończenie głęboko zagnieżdżone drzewo / strukturę danych list list list łańcuchów itp., Które badam za pomocą algorytmu rekurencyjnego i potrzebuję wiedzieć, kiedy uderzę w węzły „liścia”.
Odpowiedzi:
Śmiało i użyj,
isinstance
jeśli potrzebujesz. Jest to trochę złe, ponieważ wyklucza niestandardowe sekwencje, iteratory i inne rzeczy, których możesz potrzebować. Czasami jednak musisz zachowywać się inaczej, jeśli ktoś, na przykład, przejdzie przez łańcuch. Moją preferencją byłoby jawne sprawdzeniestr
lubunicode
polubienie:NB Nie myl się
types.StringType
ztypes.StringTypes
. Ten ostatni zawierastr
iunicode
obiekty.types
Moduł jest uważany przez wielu za przestarzały na rzecz tylko sprawdzam bezpośrednio przed typu obiektu, więc jeśli nie chcesz korzystać z powyższym, można alternatywnie sprawdzić jawnie przeciwstr
iunicode
, podobnie jak to:Edytować:
Jeszcze lepiej jest:
Zakończ edycję
Po którymkolwiek z nich możesz wrócić do zachowywania się, jakbyś otrzymywał normalną sekwencję, pozwalając, by niesekwencje generowały odpowiednie wyjątki.
Zobacz, że „zło” w sprawdzaniu typów nie polega na tym, że możesz chcieć zachowywać się inaczej w odniesieniu do określonego typu obiektu, lecz na tym, że sztucznie ograniczasz swoją funkcję do wykonywania właściwych rzeczy z nieoczekiwanymi typami obiektów, które w przeciwnym razie mogłyby zrobić właściwą rzecz. Jeśli masz ostatnią awarię, która nie jest sprawdzona pod względem typu, usuwasz to ograniczenie. Należy zauważyć, że zbyt wiele sprawdzania typu to zapach kodu wskazujący, że możesz chcieć trochę refaktoryzować, ale to niekoniecznie oznacza, że powinieneś unikać go z getgo.
źródło
str
typ, powinieneś użyć go bezpośrednio, zamiast używać,types.StringType
który jest tylko aliasem. Ale nie sądzę, że ta odpowiedź odpowiada na zadane pytanie, ponieważ chodziło o „kolekcję”. Chyba, że używasz wystarczająco nowego Pythona, aby miećabc
moduł, który nie jest czymś, czego można użyćisinstance
do sprawdzenia, a nawet wtedy polecam unikanie sprawdzania, jeśli to w ogóle możliwe.assert isinstance(u'abc', str) == False
. Zgadzam się, że lepiej jest sprawdzić przed typu bezpośrednio, a nie za pomocątypes
modułu, aletypes.StringTypes
robi coś, costr
nie: zwraca Truestr
iunicode
obiekty. Zmienię swoją odpowiedź, aby zaoferować podwójne sprawdzenie jako alternatywę.isinstance
zło?” Dałem też kontrprzykład, który (1) jest nie-złym zastosowaniemisinstance
, ponieważ awaria oznacza, że nie psuje się, a (2) jest dobrym rozwiązaniem dla bardzo powszechnej motywacji, którą ludzie chcą sprawdzić, czy coś jest alist
lubtuple
(tj. aby odróżnić je od ciągów).class Foo(str): pass
robisz co chcesz?źródło
type([]) is list
zwracaTrue
type(x) in [list,tuple]
jest krótszy.Nie ma nic złego w korzystaniu,
isinstance
o ile nie jest to zbędne. Jeśli zmienna powinna być tylko listą / krotką, to udokumentuj interfejs i po prostu użyj go jako takiego. W przeciwnym razie kontrola jest całkowicie uzasadniona:Ten rodzaj sprawdzania ma kilka dobrych przypadków użycia, na przykład ze standardowym ciągiem rozpoczynającym się / kończącym z metodami (chociaż dla dokładności są one implementowane w C w CPython za pomocą jawnego sprawdzenia, czy jest to krotka - istnieje więcej niż jeden sposób aby rozwiązać ten problem, jak wspomniano w artykule, do którego prowadzi link).
Wyraźne sprawdzenie jest często lepsze niż próba użycia obiektu jako kontenera i obsługi wyjątku - może to spowodować różnego rodzaju problemy z częściowym lub niepotrzebnym uruchomieniem kodu.
źródło
set
Obiekt jest również iterable, co oznacza, że jednocześnie można na pewno pop elementy z nim, ale nie gwarantuje pewien porządek, który jest bardzo niebezpieczna dla niektórych algorytmów. W przypadkach, gdy kolejność elementów ma znaczenie, algorytm korzystający z tego fragmentu kodu może potencjalnie generować różne wyniki dla różnych przebiegów!Udokumentuj argument, że musi to być sekwencja, i użyj go jako sekwencji. Nie sprawdzaj typu.
źródło
Co powiesz na
hasattr(a, "__iter__")
:?Informuje, czy zwrócony obiekt może być iterowany jako generator. Domyślnie krotki i listy mogą, ale nie typy ciągów.
źródło
__iter__
.__iter__
z jakiegoś powodu ...W przypadku
type(list) is list
zwrotów w języku Python 2.8false
sugerowałbym porównanie tego typu w ten okropny sposób:
(przynajmniej w moim systemie, używając anakondy w Mac OS X Yosemite)
źródło
type(list) is list
powracaFalse
botype(list)
totype
nielist
.type(list()) is list
lub z każdym innym wystąpieniem listy powróciTrue
.Python używa „Kaczego pisania”, tzn. Jeśli zmienna kwaks jak kaczka, musi to być kaczka. W twoim przypadku prawdopodobnie chcesz, aby był iterowalny lub chcesz uzyskać dostęp do elementu pod określonym indeksem. Powinieneś po prostu to zrobić: np. Użyć obiektu w bloku
for var:
lubvar[idx]
wewnątrztry
bloku, a jeśli dostaniesz wyjątek, nie będzie to kaczka ...źródło
var
iteracja łańcucha wystąpi z prawdopodobnie nieoczekiwanymi wynikami.źródło
Jeśli potrzebujesz tylko wiedzieć, czy możesz użyć
foo[123]
notacji ze zmienną, możesz sprawdzić istnienie__getitem__
atrybutu (który wywołuje Python podczas dostępu przez indeks) za pomocąhasattr(foo, '__getitem__')
źródło
Musi być bardziej złożonym testem, jeśli naprawdę chcesz obsłużyć prawie wszystko jako argument funkcji.
Chociaż zwykle wystarczy przeliterować, że funkcja oczekuje iterowalności, a następnie tylko sprawdzić
type(a) != type('')
.Może się również zdarzyć, że dla łańcucha masz prostą ścieżkę przetwarzania lub będziesz miły i zrobisz podział itp., Więc nie chcesz krzyczeć na łańcuchy, a jeśli ktoś wyśle ci coś dziwnego, pozwól mu mieć wyjątek.
źródło
Innym łatwym sposobem sprawdzenia, czy zmienna jest listą, krotką lub ogólnie typem zmiennej, byłoby:
źródło
Zasadniczo zgadzam się z Ignacio powyżej, ale możesz także użyć type, aby sprawdzić, czy coś jest krotką lub listą.
źródło