Wat is de canonieke manier om te controleren op type in Python?

Wat is de beste manier om te controleren of een bepaald object van een bepaald type is? Hoe zit het met het controleren of het object erft van een bepaald type?

Stel dat ik een object oheb. Hoe controleer ik of het een stris?


Antwoord 1, autoriteit 100%

Om te controleren of oeen instantie is van strof een subklasse van str, gebruikt u isinstance(dit zou de “canonieke” manier zijn):

if isinstance(o, str):

Om te controleren of het type oexact stris (subklassen uitsluiten):

if type(o) is str:

Het volgende werkt ook, en kan in sommige gevallen nuttig zijn:

if issubclass(type(o), str):

Zie Ingebouwde functiesin de Python Library Reference voor relevante informatie.

Nog een opmerking: in dit geval, als je Python 2 gebruikt, wil je misschien het volgende gebruiken:

if isinstance(o, basestring):

omdat hiermee ook Unicode-tekenreeksen worden opgevangen (unicodeis geen subklasse van str; zowel strals unicodezijn subklassen van basestring). Merk op dat basestringniet meer bestaat in Python 3, waar een strikte scheidingvan tekenreeksen (str) en binaire gegevens (bytes).

Als alternatief accepteert isinstancemeerdere klassen. Dit geeft Trueterug als oeen instantie is van een subklasse van een van (str, unicode):

if isinstance(o, (str, unicode)):

Antwoord 2, autoriteit 13%

De meestPythonische manier om het type van een object te controleren is… niet om het te controleren.

Aangezien Python eendentypenaanmoedigt, moet je gewoon try...exceptom de methoden van het object te gebruiken zoals u ze wilt gebruiken. Dus als uw functie op zoek is naar een beschrijfbaar bestandsobject, nietcontroleren of het een subklasse is van file, probeer gewoon de .write()methode!

Natuurlijk gaan deze mooie abstracties soms stuk en is isinstance(obj, cls)wat je nodig hebt. Maar gebruik het met mate.


Antwoord 3, autoriteit 4%

isinstance(o, str)retourneert Trueals oeen stris of van een type is dat erft van str.

type(o) is strgeeft Trueterug als en alleen als oeen str is. Het retourneert Falseals ovan een type is dat erft van str.


Antwoord 4, autoriteit 2%

Nadat de vraag was gesteld en beantwoord, werden typehints toegevoegd aan Python. Met typehints in Python kunnen typen worden gecontroleerd, maar op een heel andere manier dan statisch getypte talen. Typhints in Python associëren de verwachte typen argumenten met functies als runtime-toegankelijke gegevens die zijn gekoppeld aan functies en dit maakt het mogelijkom typen te controleren. Voorbeeld van type hint syntaxis:

def foo(i: int):
    return i
foo(5)
foo('oops')

In dit geval willen we dat er een fout wordt geactiveerd voor foo('oops')aangezien het geannoteerde type van het argument intis. De toegevoegde typehint veroorzaakt nieteen fout wanneer het script normaal wordt uitgevoerd. Het voegt echter attributen toe aan de functie die de verwachte typen beschrijft die andere programma’s kunnen opvragen en gebruiken om te controleren op typefouten.

Een van deze andere programma’s die kan worden gebruikt om de typefout te vinden, is mypy:

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

(Mogelijk moet u mypyinstalleren vanuit uw pakketbeheerder. Ik denk niet dat het met CPython wordt geleverd, maar het lijkt een zekere mate van “officieel” te hebben.)

Typecontrole op deze manier verschilt van typecontrole in statisch getypeerde gecompileerde talen. Omdat typen dynamisch zijn in Python, moet typecontrole tijdens runtime worden uitgevoerd, wat kosten met zich meebrengt – zelfs voor correcte programma’s – als we erop staan dat dit bij elke kans gebeurt. Expliciete typecontroles kunnen ook restrictiever zijn dan nodig en onnodige fouten veroorzaken (bijv. moet het argument echt van het list-type zijn of is iets itereerbaar voldoende?).

Het voordeel van expliciete typecontrole is dat het fouten eerder kan opvangen en duidelijkere foutmeldingen kan geven dan eend typen. De exacte vereisten van een eendtype kunnen alleen worden uitgedrukt met externe documentatie (hopelijk is het grondig en nauwkeurig) en fouten van incompatibele soorten kunnen ver van hun oorsprong voorkomen.

De typehints van Python zijn bedoeld om een compromis te bieden waarbij typen kunnen worden gespecificeerd en gecontroleerd, maar er zijn geen extra kosten tijdens de gebruikelijke uitvoering van code.

Het typingpakket biedt typevariabelen die gebruikt kunnen worden in typehints om gewenst gedrag uit te drukken zonder dat er bepaalde typen nodig zijn. Het bevat bijvoorbeeld variabelen zoals Iterableen Callablevoor hints om de behoefte aan elk type met dat gedrag te specificeren.

Hoewel typehints de meest Pythonische manier zijn om typen te controleren, is het vaak nog Pythonischer om helemaal geen typen te controleren en te vertrouwen op duck-typering. Typehints zijn relatief nieuw en de jury is er nog niet uit wanneer ze de meest Pythonische oplossing zijn. Een relatief oncontroversiële maar zeer algemene vergelijking: typehints bieden een vorm van documentatie die kan worden afgedwongen, waardoor code eerder en gemakkelijker te begrijpen fouten kan genereren, fouten kunnen opvangen die eendtypering niet kan en statisch kunnen worden gecontroleerd (in een ongebruikelijke zin, maar het is nog steeds buiten runtime). Aan de andere kant is duck-typen al heel lang de Python-manier, legt het niet de cognitieve overhead van statisch typen op, is minder uitgebreid en accepteert alle haalbare typen en nog wat.


Antwoord 5

Hier is een voorbeeld waarom het typen van eenden slecht is zonder te weten wanneer het gevaarlijk is.
Bijvoorbeeld: hier is de Python-code (mogelijk zonder het juiste inspringen), merk op dat dit:
situatie kan worden vermeden door te zorgen voor isinstance en issubclassof functies om ervoor te zorgen dat wanneer je echt een eend nodig hebt, je geen bom krijgt.

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

Antwoord 6

Je kunt het type van een variabele controleren met __name__ van een type.

Bijvoorbeeld:

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

Antwoord 7

isinstance(o, str)

Link naar documenten


Antwoord 8

Het leuke aan het gebruik van een dynamische taal als Python vind ik dat je zoiets echt niet hoeft te controleren.

Ik zou gewoon de vereiste methoden op uw object aanroepen en een AttributeErroropvangen. Later kun je hiermee je methoden aanroepen met andere (schijnbaar niet-gerelateerde) objecten om verschillende taken uit te voeren, zoals het bespotten van een object om te testen.

Ik heb dit veel gebruikt bij het ophalen van gegevens van het web met urllib2.urlopen()die een bestand alsobject retourneert. Dit kan op zijn beurt worden doorgegeven aan bijna elke methode die uit een bestand leest, omdat het dezelfde read()methode implementeert als een echt bestand.

Maar ik weet zeker dat er een tijd en plaats is om isinstance()te gebruiken, anders zou het er waarschijnlijk niet zijn 🙂


Antwoord 9

Voor complexere typevalidaties hou ik van typeguard‘s benadering van validatie op basis van python-type hintannotaties:

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

U kunt zeer complexe validaties uit te voeren in zeer schoon en leesbare manier.

check_type('foo', [1, 3.14], List[Union[int, float]])
# vs
isinstance(foo, list) and all(isinstance(a, (int, float)) for a in foo) 

10

Om Hugo:

U bedoelt waarschijnlijk listin plaats van array, maar dat wijst naar het hele probleem met type checking – je niet wilt weten of het object in kwestie is een lijst, wilt u weten of het een soort van sequentie of als het een enkel object. Dus probeer om het te gebruiken als een reeks.

Stel dat je wilt om het object toe te voegen aan een bestaande reeks, of als het een opeenvolging van objecten, voeg ze allemaal

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

Een truc met dit is als u werkt met strijkers en / of sequenties van strings – dat is lastig, als een string wordt vaak gezien als een enkel object, maar het is ook een reeks tekens. Erger dan dat, want het is echt een reeks van single-lengte snaren.

ik meestal kiezen om mijn API zo te ontwerpen dat het accepteert alleen een enkele waarde of een reeks – het maakt het wat makkelijker. Het is niet moeilijk om een ​​[ ]om je enkele waarde als u deze doorgeven in als dat nodig is.

(Hoewel deze fouten kunnen veroorzaken met strijkers, als ze eruit zien doen zoals (zijn) sequenties.)


11

Python 3.10 , kunt u |in isinstance

>>> isinstance('1223', int | str) 
True
>>> isinstance('abcd', int | str) 
True

Antwoord 12

Een eenvoudige manier om het type te controleren, is door het te vergelijken met iets waarvan u het type kent.

>>> a  = 1
>>> type(a) == type(1)
True
>>> b = 'abc'
>>> type(b) == type('')
True

Antwoord 13

Ik denk dat de beste manier is om je variabelen goed te typen. U kunt dit doen door gebruik te maken van de “typing” bibliotheek.

Voorbeeld:

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

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

Other episodes