Bepaal het type object?

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


Antwoord 1, autoriteit 100%

Er zijn twee ingebouwde functies die u helpen het type object te identificeren. U kunt type()gebruiken als u het exacte type object nodig hebben, en isinstance()om het type van een object tegen iets te controleren. Meestal wil je isinstance()meestal gebruiken omdat het erg robuust is en ook type-overerving ondersteunt.


Om het werkelijke type van een object te krijgen, gebruikt u de ingebouwde type()functie. Als een object als enige parameter wordt doorgegeven, wordt het type object van dat object geretourneerd:

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

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

Houd er rekening mee dat type()alleen het directe type van het object retourneert, maar u niet kan vertellen over typeovererving.

>>> type(b) is Test1
False

Om dat te dekken, moet u de isinstancegebruiken 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 beste manier om het type van een object te garanderen, omdat het ook afgeleide typen accepteert. Dus tenzij je het type object echt nodig hebt (om welke reden dan ook), heeft het gebruik van isinstance()de voorkeur boven type().

De tweede parameter van isinstance()accepteert ook een aantal typen, dus het is mogelijk om op meerdere typen tegelijk te controleren. isinstancezal dan true retourneren, als het object van een van deze typen is:

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

Antwoord 2, autoriteit 9%

Je kunt dat doen met type():

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

Antwoord 3, autoriteit 2%

Het is misschien Pythonischer om een tryexcept-blok te gebruiken. Op die manier, als je een klas hebt die kwaakt als een lijst, of kwaakt als een dictee, zal deze zich correct gedragen, ongeacht wat het type echtis.

Om te verduidelijken, is de voorkeursmethode voor “het verschil vertellen” tussen variabele typen is met iets dat eend typen : Zolang de methoden (en retourtypen) die een variabele reageert op zijn wat uw subroutine verwacht, behandel het als wat u verwacht. Als u bijvoorbeeld een klasse hebt die de beugelexploitanten overbelast met getattren setattr, maar gebruikt een grappig interne regeling, zou het passend zijn om zich te gedragen als een woordenboek Als dat is wat het probeert te emuleren.

Het andere probleem met de type(A) is type(B)controleren is dat als Aeen subklasse is van B, IT Evalueert naar FalseWanneer u programmatisch hopen dat het Truezou zijn. Als een object een subklasse van een lijst is, zou het moeten werken als een lijst: het controleren van het type zoals gepresenteerd in het andere antwoord zal dit voorkomen. (isinstanceWerkt echter).


Antwoord 4, Autoriteit 2%

Over instanties van object, heb je ook de:

__class__

attribuut. Hier is een monster uit 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'>

Let op dat in python 3.x en in New-Style klassen (optioneel verkrijgbaar vanaf Python 2.6) klasse en type zijn samengevoegd en dit kan soms tot onverwachte resultaten leiden. Vooral om deze reden is mijn favoriete manier om typen/klassen te testen de isinstanceingebouwde functie.


Antwoord 5

Bepaal het type van een Python-object

Bepaal het type object met type

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

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

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

typecontrole

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

Nou, 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 dekt het geval waarin uw gebruiker iets slims of verstandigs doet door strte subclasseren – volgens het principe van Liskov Substitution, wilt u subklasse-instanties kunnen gebruiken zonder uw code te breken – en isinstanceondersteunt dit.

Abstracties gebruiken

Nog beter, je zou kunnen zoeken naar een specifieke abstracte basisklasse uit collectionsof 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 type-check

Of, misschien het beste van alles, gebruik duck-typing en typ uw code niet expliciet in. Duck-typen ondersteunt Liskov Substitution 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 typeom de klasse van een instantie daadwerkelijk op te halen.
  • Gebruik isinstanceom expliciet te controleren op daadwerkelijke subklassen of geregistreerde abstracties.
  • En vermijd typecontrole waar dat zinvol is.

Antwoord 6

U kunt type()of isinstance()gebruiken.

>>> type([]) is list
True

Wees gewaarschuwd dat je listof een ander type kunt bedriegen door een variabele in het huidige bereik met dezelfde naam toe te wijzen.

>>> 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 dictopnieuw wordt toegewezen aan een string, daarom de test:

type({}) is dict

…mislukt.

Om dit te omzeilen en type()voorzichtiger te gebruiken:

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

Antwoord 7

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

Hier probeer ik de vraag uit de titel te beantwoorden: hoe kan ik het type van een willekeurig object bepalen? Andere suggesties over het al dan niet gebruiken van isinstance zijn prima in veel opmerkingen en antwoorden, maar ik ga niet in op die zorgen.

Het belangrijkste probleem met de type()-aanpak is dat het niet goed werkt met instanties in oude stijl:

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 het volgende opleveren:

Are o and t instances of the same class? True

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

De __class__benadering komt het dichtst in de buurt van correctheid, maar zal niet werken in één cruciaal geval: wanneer het doorgegeven object een ouderwetse klasseis (geen instantie!), aangezien die objecten zo’n attribuut niet hebben.

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

Antwoord 8

wees voorzichtig met het gebruik van isinstance

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

maar typ

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

Antwoord 9

Zoals afgezien van de vorige antwoorden, is het de moeite waard om het bestaan ​​van collections.abcdie verschillende abstracte base-klassen (ABC’s) bevat die een aanvulling op een duck-typen.

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

isinstance(my_obj, list)

U kunt, als u alleen geïnteresseerd bent in het zien of het object dat u hebt kunt krijgen, gebruikt u collections.abc.Sequence:

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

Als u strikt geïnteresseerd bent in objecten die het krijgen, instellen, instellen en Items verwijderen (IE MUBABLE SEQUENCES), kunt u kiezen voor collections.abc.MutableSequence.

Veel andere ABC’s zijn daar gedefinieerd, Mappingvoor 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.


Antwoord 10

value = 12
print(type(value)) # will return <class 'int'> (means integer)

of u kunt zoiets doen

value = 12
print(type(value) == int) # will return true

Antwoord 11

type()is een betere oplossing dan isinstance(), vooral voor booleans:

Trueen Falsezijn slechts trefwoorden die 1en 0in python betekenen. Dus,

isinstance(True, int)

en

isinstance(False, int)

beide retourneren True. Beide booleans zijn een instantie van een geheel getal. type()is echter slimmer:

type(True) == int

retourneert False.


Antwoord 12

Over het algemeen kun je een string uit een object halen met de klassenaam,

str_class = object.__class__.__name__

en gebruiken om te vergelijken,

if str_class == 'dict':
    # blablabla..
elif str_class == 'customclass':
    # blebleble..

Antwoord 13

In veel praktische gevallen kunt u in plaats van typeof isinstanceook @functools.singledispatch, die wordt gebruikt om algemene functies(functie samengesteld uit meerdere functies die dezelfde bewerking voor verschillende typen implementeren).

Met andere woorden, je zou het willen gebruiken als je een code hebt zoals de volgende:

def do_something(arg):
    if isinstance(arg, int):
        ... # some code specific to processing integers
    if isinstance(arg, str):
        ... # some code specific to processing strings
    if isinstance(arg, list):
        ... # some code specific to processing lists
    ...  # etc

Hier is een klein voorbeeld van hoe het werkt:

from functools import singledispatch
@singledispatch
def say_type(arg):
    raise NotImplementedError(f"I don't work with {type(arg)}")
@say_type.register
def _(arg: int):
    print(f"{arg} is an integer")
@say_type.register
def _(arg: bool):
    print(f"{arg} is a boolean")
>>> say_type(0)
0 is an integer
>>> say_type(False)
False is a boolean
>>> say_type(dict())
# long error traceback ending with:
NotImplementedError: I don't work with <class 'dict'>

Bovendien kunnen we abstracte klassengebruiken om meerdere typen tegelijk te behandelen:

from collections.abc import Sequence
@say_type.register
def _(arg: Sequence):
    print(f"{arg} is a sequence!")
>>> say_type([0, 1, 2])
[0, 1, 2] is a sequence!
>>> say_type((1, 2, 3))
(1, 2, 3) is a sequence!

Antwoord 14

Voor de volledigheid: isinstance werktniet voor typecontrole van een subtype dat geen instantie is. Hoewel dat volkomen logisch is, dekt geen van de antwoorden (inclusief de geaccepteerde) het. Gebruik daarvoor issubclass.

>>> class a(list):
...   pass
... 
>>> isinstance(a, list)
False
>>> issubclass(a, list)
True

Other episodes