Vraag Bepaal het type van een object?


Is er een eenvoudige manier om te bepalen of een variabele een lijst, een woordenboek of iets anders is? Ik krijg een object terug dat een van beide typen kan zijn en ik moet het verschil kunnen zien.


1378
2018-02-08 21:37


oorsprong


antwoorden:


Om het type object te krijgen, kunt u de ingebouwde functie gebruiken type() functie. Als u een object doorgeeft als de enige parameter, wordt het typeobject van dat object geretourneerd:

>>> type([]) is list
True
>>> type({}) is dict
True
>>> type('') is str
True
>>> type(0) is int
True
>>> type({})
<type 'dict'>
>>> type([])
<type 'list'>

Dit werkt natuurlijk ook voor aangepaste typen:

>>> class Test1 (object):
        pass
>>> class Test2 (Test1):
        pass
>>> a = Test1()
>>> b = Test2()
>>> type(a) is Test1
True
>>> type(b) is Test2
True

Let daar op type() retourneert alleen het directe type van het object, maar kan u niet vertellen over typeovererving.

>>> type(b) is Test1
False

Om dat te dekken, zou u de isinstance functie. Dit werkt natuurlijk ook voor ingebouwde typen:

>>> isinstance(b, Test1)
True
>>> isinstance(b, Test2)
True
>>> isinstance(a, Test1)
True
>>> isinstance(a, Test2)
False
>>> isinstance([], list)
True
>>> isinstance({}, dict)
True

isinstance() is meestal de voorkeursmanier om het type object te garanderen, omdat het ook afgeleide typen accepteert. Dus tenzij je het type object eigenlijk nodig hebt (om welke reden dan ook), met isinstance() heeft de voorkeur boven type().

De tweede parameter van isinstance() accepteert ook een tuple van typen, dus het is mogelijk om meerdere typen tegelijkertijd te controleren. isinstance zal dan waar retourneren, als het object van een van die typen is:

>>> isinstance([], (tuple, list, set))
True

1603
2018-02-08 21:40



U kunt dat doen met type():

>>> a = []
>>> type(a)
<type 'list'>
>>> f = ()
>>> type(f)
<type 'tuple'>

141
2018-02-08 21:39



Het is misschien meer Pythonic om a te gebruiken try...except blok. Op die manier, als je een klasse hebt die kwaakt als een lijst, of kwaakt als een dictaat, zal het zich netjes gedragen, ongeacht zijn type werkelijk is.

Om te verduidelijken, de voorkeursmethode van "het verschil tussen variabele typen" is met iets genaamd eend typen: zolang de methoden (en retourtypen) waarop een variabele reageert, zijn wat uw subroutine verwacht, behandel deze dan zoals u verwacht. Als u bijvoorbeeld een klasse heeft waarmee de bracketoperators worden overbelast getattr en setattr, maar gebruikt een grappig intern schema, het zou gepast zijn om zich als een woordenboek te gedragen als dat is wat het probeert te emuleren.

Het andere probleem met de type(A) is type(B) controleren is dat als A is een subklasse van B, evalueert het naar false wanneer, programmatisch, zou je hopen dat het zou zijn true. Als een object een subklasse van een lijst is, zou het als een lijst moeten werken: het controleren van het type zoals gepresenteerd in het andere antwoord zal dit voorkomen. (isinstance zal echter werken).


37
2018-02-08 21:43



Bij instanties van objecten heb je ook de:

__class__

attribuut. Hier is een voorbeeld van de Python 3.3-console

>>> str = "str"
>>> str.__class__
<class 'str'>
>>> i = 2
>>> i.__class__
<class 'int'>
>>> class Test():
...     pass
...
>>> a = Test()
>>> a.__class__
<class '__main__.Test'>

Pas op dat in klasse python 3.x en in klassen met nieuwe stijlen (beschikbaar vanaf faciliteit Python 2.6) klasse en type zijn samengevoegd en dat dit soms tot onverwachte resultaten kan leiden. Vooral om deze reden is mijn favoriete manier om soorten / klassen te testen de isinstance ingebouwde functie.


30
2018-06-26 21:38



Bepaal het type van een Python-object

Bepaal het type van een object met type

>>> obj = object()
>>> type(obj)
<class 'object'>

Hoewel het werkt, vermijd dubbele underscore-kenmerken zoals __class__ - ze zijn niet semantisch openbaar en, hoewel misschien niet in dit geval, hebben de ingebouwde functies meestal beter gedrag.

>>> obj.__class__ # avoid this!
<class 'object'>

type controle

Is er een eenvoudige manier om te bepalen of een variabele een lijst, een woordenboek of iets anders is? Ik krijg een object terug dat een van beide typen kan zijn en ik moet het verschil kunnen zien.

Wel, dat is een andere vraag, gebruik geen type - gebruik isinstance:

def foo(obj):
    """given a string with items separated by spaces, 
    or a list or tuple, 
    do something sensible
    """
    if isinstance(obj, str):
        obj = str.split()
    return _foo_handles_only_lists_or_tuples(obj)

Dit heeft betrekking op het geval dat uw gebruiker iets slims of verstandigs doet door subclassering str - volgens het principe van Liskov Substitution, wil je subclass instances kunnen gebruiken zonder je code te breken - en isinstance ondersteunt dit.

Gebruik abstracties

Sterker nog, je zou kunnen zoeken naar een specifieke abstracte basisklasse uit collections of numbers:

from collections import Iterable
from numbers import Number

def bar(obj):
    """does something sensible with an iterable of numbers, 
    or just one number
    """
    if isinstance(obj, Number): # make it a 1-tuple
        obj = (obj,)
    if not isinstance(obj, Iterable):
        raise TypeError('obj must be either a number or iterable of numbers')
    return _bar_sensible_with_iterable(obj)

Of gewoon niet expliciet typecontrole

Of misschien het beste van alles, gebruik eendentypering en typ niet expliciet uw code. Eendentypering ondersteunt Liskov-substitutie met meer elegantie en minder breedsprakigheid.

def baz(obj):
    """given an obj, a dict (or anything with an .items method) 
    do something sensible with each key-value pair
    """
    for key, value in obj.items():
        _baz_something_sensible(key, value)

Conclusie

  • Gebruik type om de klasse van een instantie daadwerkelijk te krijgen.
  • Gebruik isinstance om expliciet te controleren op feitelijke subklassen of geregistreerde abstracties.
  • En vermijd gewoon typecontrole waar het zinvol is.

14
2018-03-14 21:12



Je kunt gebruiken type() of isinstance().

>>> type([]) is list
True

Wees gewaarschuwd dat je kunt kletsen list of een ander type door een variabele toe te wijzen in het huidige bereik van dezelfde naam.

>>> the_d = {}
>>> t = lambda x: "aight" if type(x) is dict else "NOPE"
>>> t(the_d) 'aight'
>>> dict = "dude."
>>> t(the_d) 'NOPE'

Hierboven zien we dat dict wordt opnieuw toegewezen aan een string, dus de test:

type({}) is dict

... mislukt.

Om dit te omzeilen en gebruiken type() voorzichtiger:

>>> import __builtin__
>>> the_d = {}
>>> type({}) is dict
True
>>> dict =""
>>> type({}) is dict
False
>>> type({}) is __builtin__.dict
True

10
2018-05-31 21:57



Hoewel de vragen vrij oud zijn, kwam ik dit tegen terwijl ik zelf een goede manier ontdekte, en ik denk dat het nog steeds verduidelijking behoeft, in ieder geval voor Python 2.x (niet gecontroleerd op Python 3, maar omdat het probleem zich voordoet bij klassieke klassen die in zo'n versie zijn verdwenen, maakt het waarschijnlijk niet uit).

Hier probeer ik de vraag van de titel te beantwoorden: hoe kan ik het type van een willekeurig object bepalen? Andere suggesties om al dan niet gebruik te maken van het antwoord zijn prima in veel reacties en antwoorden, maar ik ben niet bezig met die zorgen.

Het grootste probleem met de type() aanpak is dat het werkt niet goed met oude voorbeelden:

class One:
    pass

class Two:
    pass


o = One()
t = Two()

o_type = type(o)
t_type = type(t)

print "Are o and t instances of the same class?", o_type is t_type

Het uitvoeren van dit fragment zou opleveren:

Are o and t instances of the same class? True

Wat, denk ik, niet is wat de meeste mensen zouden verwachten.

De __class__ aanpak komt het dichtst bij de juistheid, maar het zal niet werken in één cruciaal geval: wanneer het ingeleverde object een oude stijl is klasse (niet een instantie!), omdat deze objecten een dergelijk attribuut missen.

Dit is het kleinste codefragment dat ik kon bedenken dat op een consistente manier aan zo'n legitieme vraag voldoet:

#!/usr/bin/env python
from types import ClassType
#we adopt the null object pattern in the (unlikely) case
#that __class__ is None for some strange reason
_NO_CLASS=object()
def get_object_type(obj):
    obj_type = getattr(obj, "__class__", _NO_CLASS)
    if obj_type is not _NO_CLASS:
        return obj_type
    # AFAIK the only situation where this happens is an old-style class
    obj_type = type(obj)
    if obj_type is not ClassType:
        raise ValueError("Could not determine object '{}' type.".format(obj_type))
    return obj_type

4
2018-06-17 08:35



Naast de vorige antwoorden is het vermelden waard het bestaan ​​van collections.abc die verschillende abstracte basisklassen (ABC's) bevat die een aanvulling vormen op het typen van eenden.

Bijvoorbeeld in plaats van expliciet te controleren of iets een lijst is met:

isinstance(my_obj, list)

je zou kunnen, als je alleen geïnteresseerd bent om te zien of het object dat je hebt toestaat om items te krijgen, gebruik collections.abc.Sequence:

from collections.abc import Sequence
isinstance(my_obj, Sequence) 

als je alleen maar geïnteresseerd bent in objecten die het krijgen, instellen toestaan en items verwijderen (d.w.z. veranderlijk sequenties), zou je kiezen voor collections.abc.MutableSequence.

Veel andere ABC's zijn daar gedefinieerd, Mapping voor objecten die kunnen worden gebruikt als kaarten, Iterable, Callable, et cetera. Een volledige lijst van al deze is te zien in de documentatie voor collections.abc.


3
2017-12-07 15:50



wees voorzichtig met behulp van isinstance

isinstance(True, bool)
True
>>> isinstance(True, int)
True

maar typ

type(True) == bool
True
>>> type(True) == int
False

2
2017-11-14 11:22