Jaki jest kanoniczny sposób sprawdzania typu w Pythonie?

Jaki jest najlepszy sposób na sprawdzenie czy dany obiekt jest danego typu? Co powiesz na sprawdzenie, czy obiekt dziedziczy z danego typu?

Powiedzmy, że mam obiekt o. Jak sprawdzić, czy jest to str?

 1400
Author: Peter Mortensen, 2008-09-30

12 answers

Aby sprawdzić, czy o jest instancją str lub dowolną podklasą str, użyj isinstance (byłby to sposób "kanoniczny"):

if isinstance(o, str):

Aby sprawdzić, czy typ o jest dokładnie str (wyklucz podklasy):

if type(o) is str:

Poniższe również działa i mogą być przydatne w niektórych przypadkach:

if issubclass(type(o), str):

Zobacz wbudowane funkcje W referencji Biblioteki Pythona, aby uzyskać istotne informacje.

Jeszcze jedna uwaga: w tym przypadku, jeśli używasz Pythona 2, możesz faktycznie chce używać:

if isinstance(o, basestring):

Ponieważ będzie to również przechwytywać ciągi Unicode(unicode nie jest podklasą str; zarówno str, jak i unicode są podklasami basestring). Zauważ, że basestring nie istnieje już w Pythonie 3, gdzie istnieje ścisłe oddzielenie łańcuchów (str) i dane binarne (bytes).

Alternatywnie, isinstance akceptuje krotkę klas. Zwróci True, Jeśli o jest instancją dowolnej podklasy dowolnego z (str, unicode):

if isinstance(o, (str, unicode)):
 1672
Author: Fredrik Johansson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-27 06:19:32

Najbardziej Pythoniczny sposób sprawdzenia typu obiektu jest... nie sprawdzać.

Ponieważ Python zachęca do pisania kaczek , powinieneś po prostu try...except używać metod obiektu tak, jak chcesz ich używać. Jeśli więc twoja funkcja szuka zapisywalnego obiektu pliku, nie sprawdzaj, czy jest to podklasa file, po prostu spróbuj użyć jej metody .write()!

Oczywiście, czasami te ładne abstrakcje załamują się i isinstance(obj, cls) jest tym, czego potrzebujesz. Ale użyj oszczędnie.

 211
Author: Dan Lenski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-09 23:55:36

isinstance(o, str) zwróci True, Jeśli o jest typem str lub jest typem dziedziczonym z str.

type(o) is str zwróci True wtedy i tylko wtedy, gdy o jest str. Zwróci False, Jeśli {[2] } jest typu, który dziedziczy z str.

 60
Author: Herge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-10 16:04:07

Po zadaniu pytania i odpowiedzi, podpowiedzi typu zostały dodane do Pythona. Podpowiedzi typu w Pythonie pozwalają sprawdzać typy, ale w zupełnie inny sposób niż języki typowane statycznie. Podpowiedzi typu w Pythonie kojarzą oczekiwane typy argumentów z funkcjami jako dostępnymi danymi uruchomieniowymi powiązanymi z funkcjami, a to pozwala sprawdzać typy. Przykład składni podpowiedzi typu:

def foo(i: int):
    return i

foo(5)
foo('oops')

W tym przypadku chcemy aby błąd został wywołany dla foo('oops') ponieważ opisywany typ argumentu to int. Dodana podpowiedź typu nie powoduje błędu , gdy skrypt jest uruchamiany normalnie. Jednak dodaje atrybuty do funkcji opisującej oczekiwane typy, które inne programy mogą odpytywać i używać do sprawdzania błędów typu.

Jednym z tych innych programów, które mogą być użyte do znalezienia błędu typu jest mypy:

mypy script.py
script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"

(może być konieczne zainstalowanie mypy z menedżera pakietów. Nie wydaje mi się, że chodzi o CPython, ale wydaje się mieć pewien poziom "urzędowości".)

Sprawdzanie typu w ten sposób różni się od sprawdzania typu w statycznie typowanych językach skompilowanych. Ponieważ typy są dynamiczne w Pythonie, sprawdzanie typów musi być wykonywane w czasie wykonywania, co nakłada koszty - nawet na poprawne programy-jeśli nalegamy, aby stało się to przy każdej okazji. Jawne sprawdzanie typu może być również bardziej restrykcyjne niż jest to konieczne i powodować niepotrzebne błędy (np. czy argument naprawdę musi być dokładnie typu list lub jest cokolwiek iterowalne wystarczy?).

Zaletą jawnego sprawdzania typu jest to, że może wychwytywać błędy wcześniej i dawać jaśniejsze komunikaty o błędach niż pisanie kaczką. Dokładne wymagania typu kaczki można wyrazić tylko za pomocą zewnętrznej dokumentacji (miejmy nadzieję, że jest dokładna i dokładna), a błędy z niekompatybilnych typów mogą wystąpić daleko od miejsca ich pochodzenia.

Podpowiedzi typu Pythona mają na celu oferowanie kompromisu, w którym typy mogą być określone i sprawdzone, ale nie ma dodatkowych kosztów podczas zwykłe wykonanie kodu.

Pakiet typing oferuje zmienne typu, które mogą być używane w podpowiedziach do wyrażania potrzebnych zachowań bez konieczności stosowania określonych typów. Na przykład zawiera zmienne, takie jak Iterable i Callable dla podpowiedzi określających potrzebę dowolnego typu z tymi zachowaniami.

Podczas gdy podpowiedzi typu są najbardziej Pythonicznym sposobem sprawdzania typów, często jeszcze bardziej Pythoniczne jest nie sprawdzanie typów i poleganie na pisaniu kaczek. Podpowiedzi typu są stosunkowo nowe, a jury wciąż kiedy są najbardziej Pythonicznym rozwiązaniem. Stosunkowo niekontrowersyjne, ale bardzo ogólne porównanie: podpowiedzi typu zapewniają formę dokumentacji, która może być wymuszona, pozwalają kodowi generować wcześniejsze i łatwiejsze do zrozumienia błędy, mogą wychwycić błędy, których pisanie kaczką nie jest możliwe, i mogą być sprawdzane statycznie(w nietypowym sensie, ale nadal poza uruchomieniem). Z drugiej strony, pisanie kaczek od dawna jest sposobem Pythonicznym, nie narzuca poznawczego narzutu typowania statycznego, jest mniej gadatliwy, i zaakceptuje wszystkie żywotne typy, a potem niektóre.

 34
Author: Praxeolitic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-10 06:22:16

Oto przykład, dlaczego pisanie kaczek jest złe, nie wiedząc, kiedy jest niebezpieczne. Na przykład: tutaj jest kod Pythona (ewentualnie pomijając właściwe wcięcie), zauważ, że to sytuacji można uniknąć, dbając o funkcje isinstance i issubclassof, aby upewnić się, że kiedy naprawdę potrzebujesz kaczki, nie dostaniesz bomby.

class Bomb:
    def __init__(self):
        ""

    def talk(self):
        self.explode()

    def explode(self):
        print "BOOM!, The bomb explodes."

class Duck:
    def __init__(self):
        ""
    def talk(self):
        print "I am a duck, I will not blow up if you ask me to talk."    

class Kid:
    kids_duck = None

    def __init__(self):
        print "Kid comes around a corner and asks you for money so he could buy a duck."

    def takeDuck(self, duck):
        self.kids_duck = duck
        print "The kid accepts the duck, and happily skips along"

    def doYourThing(self):
        print "The kid tries to get the duck to talk"
        self.kids_duck.talk()

myKid = Kid()
myBomb = Bomb()
myKid.takeDuck(myBomb)
myKid.doYourThing()
 17
Author: Dmitry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-28 05:30:58
isinstance(o, str)

Link do docs

 12
Author: Alexander Kojevnikov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-14 06:37:39

Możesz sprawdzić typ zmiennej używając__ nazwa _ _ typu.

Ex:

>>> a = [1,2,3,4]  
>>> b = 1  
>>> type(a).__name__
'list'
>>> type(a).__name__ == 'list'
True
>>> type(b).__name__ == 'list'
False
>>> type(b).__name__
'int'
 9
Author: Yerramsetty Rohit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-18 17:23:39

Myślę, że fajną rzeczą w używaniu dynamicznego języka, takiego jak Python, jest to, że naprawdę nie powinieneś musieć sprawdzać czegoś takiego.

Po prostu wywołałbym wymagane metody na Twoim obiekcie i złapał AttributeError. Później pozwoli Ci to na wywołanie metod z innymi (pozornie niepowiązanymi) obiektami w celu wykonania różnych zadań, takich jak wyśmiewanie obiektu do testowania.

Używałem tego często podczas pobierania danych z sieci za pomocą urllib2.urlopen(), który zwraca Plik jak obiekt. To z kolei może być przekazane do prawie każdej metody, która odczytuje z pliku, ponieważ implementuje tę samą metodę read() jako prawdziwy plik.

Ale jestem pewien, że jest czas i miejsce na użycie isinstance(), w przeciwnym razie pewnie by go nie było :)

 7
Author: Will Harding,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-11 13:34:30

Dla bardziej złożonych walidacji typu Lubię typeguard podejście do walidacji oparte na adnotacjach podpowiedzi typu python:

from typeguard import check_type
from typing import List

try:
    check_type('mylist', [1, 2], List[int])
except TypeError as e:
    print(e)

Możesz wykonywać bardzo złożone walidacje w bardzo przejrzysty i czytelny sposób.

check_type('foo', [1, 3.14], List[Union[int, float]])
# vs
isinstance(foo, list) and all(isinstance(a, (int, float)) for a in foo) 
 7
Author: Granitosaurus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-16 07:06:16

Do Hugo:

Prawdopodobnie masz na myśli list zamiast array, ale to wskazuje na cały problem z sprawdzaniem typu-nie chcesz wiedzieć, czy dany obiekt jest listą, chcesz wiedzieć, czy jest to jakaś Sekwencja, czy jest to pojedynczy obiekt. Więc spróbuj użyć go jak sekwencji.

Powiedz, że chcesz dodać obiekt do istniejącej sekwencji, lub jeśli jest to sekwencja obiektów, dodaj je wszystkie

try:
   my_sequence.extend(o)
except TypeError:
  my_sequence.append(o)

Jedna sztuczka z tym polega na tym, że pracujesz ze strunami i / lub sekwencje ciągów-to trudne, ponieważ ciąg jest często uważany za pojedynczy obiekt, ale jest to również sekwencja znaków. Co gorsza, bo to tak naprawdę ciąg ciągów o pojedynczej długości.

Zazwyczaj wybieram projektowanie mojego API tak, aby akceptowało tylko pojedynczą wartość lub sekwencję - to ułatwia sprawę. Nie jest trudno umieścić [ ] wokół swojej pojedynczej wartości, kiedy ją przekazujesz, jeśli zajdzie taka potrzeba.

(chociaż może to powodować błędy z łańcuchami, ponieważ wyglądają jak (są) sekwencje.)

 5
Author: Chris Barker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-11 13:36:15

Prostym sposobem sprawdzenia typu jest porównanie go z czymś, którego typ znasz.

>>> a  = 1
>>> type(a) == type(1)
True
>>> b = 'abc'
>>> type(b) == type('')
True
 -1
Author: Ultrablendz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-31 20:42:07

Myślę, że najlepszym sposobem jest dobre wpisanie zmiennych. Możesz to zrobić za pomocą biblioteki "typowanie".

Przykład:

from typing import NewType UserId = NewType ('UserId', int) some_id = UserId (524313)`

Zobacz https://docs.python.org/3/library/typing.html

 -4
Author: cherah30,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-24 09:21:42