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 o
heb. Hoe controleer ik of het een str
is?
Antwoord 1, autoriteit 100%
Om te controleren of o
een instantie is van str
of een subklasse van str
, gebruikt u isinstance(dit zou de “canonieke” manier zijn):
if isinstance(o, str):
Om te controleren of het type o
exact str
is (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 (unicode
is geen subklasse van str
; zowel str
als unicode
zijn subklassen van basestring
). Merk op dat basestring
niet meer bestaat in Python 3, waar een strikte scheidingvan tekenreeksen (str
) en binaire gegevens (bytes
).
Als alternatief accepteert isinstance
meerdere klassen. Dit geeft True
terug als o
een 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...except
om 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 True
als o
een str
is of van een type is dat erft van str
.
type(o) is str
geeft True
terug als en alleen als o
een str is. Het retourneert False
als o
van 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 int
is. 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 mypy
installeren 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 typing
pakket 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 Iterable
en Callable
voor 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)
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 AttributeError
opvangen. 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 list
in 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`)