Determine the type of an object?

后端 未结 13 2180
余生分开走
余生分开走 2020-11-22 05:50

Is there a simple way to determine if a variable is a list, dictionary, or something else? I am getting an object back that may be either type and I need to be able to tell

相关标签:
13条回答
  • 2020-11-22 06:00

    You can use type() or isinstance().

    >>> type([]) is list
    True
    

    Be warned that you can clobber list or any other type by assigning a variable in the current scope of the same name.

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

    Above we see that dict gets reassigned to a string, therefore the test:

    type({}) is dict
    

    ...fails.

    To get around this and use type() more cautiously:

    >>> import __builtin__
    >>> the_d = {}
    >>> type({}) is dict
    True
    >>> dict =""
    >>> type({}) is dict
    False
    >>> type({}) is __builtin__.dict
    True
    
    0 讨论(0)
  • 2020-11-22 06:04

    It might be more Pythonic to use a try...except block. That way, if you have a class which quacks like a list, or quacks like a dict, it will behave properly regardless of what its type really is.

    To clarify, the preferred method of "telling the difference" between variable types is with something called duck typing: as long as the methods (and return types) that a variable responds to are what your subroutine expects, treat it like what you expect it to be. For example, if you have a class that overloads the bracket operators with getattr and setattr, but uses some funny internal scheme, it would be appropriate for it to behave as a dictionary if that's what it's trying to emulate.

    The other problem with the type(A) is type(B) checking is that if A is a subclass of B, it evaluates to false when, programmatically, you would hope it would be true. If an object is a subclass of a list, it should work like a list: checking the type as presented in the other answer will prevent this. (isinstance will work, however).

    0 讨论(0)
  • 2020-11-22 06:06

    be careful using isinstance

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

    but type

    type(True) == bool
    True
    >>> type(True) == int
    False
    
    0 讨论(0)
  • 2020-11-22 06:06

    For the sake of completeness, isinstance will not work for type checking of a subtype that is not an instance. While that makes perfect sense, none of the answers (including the accepted one) covers it. Use issubclass for that.

    >>> class a(list):
    ...   pass
    ... 
    >>> isinstance(a, list)
    False
    >>> issubclass(a, list)
    True
    
    0 讨论(0)
  • 2020-11-22 06:09

    There are two built-in functions that help you identify the type of an object. You can use type() if you need the exact type of an object, and isinstance() to check an object’s type against something. Usually, you want to use isistance() most of the times since it is very robust and also supports type inheritance.


    To get the actual type of an object, you use the built-in type() function. Passing an object as the only parameter will return the type object of that object:

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

    This of course also works for custom types:

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

    Note that type() will only return the immediate type of the object, but won’t be able to tell you about type inheritance.

    >>> type(b) is Test1
    False
    

    To cover that, you should use the isinstance function. This of course also works for built-in types:

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

    isinstance() is usually the preferred way to ensure the type of an object because it will also accept derived types. So unless you actually need the type object (for whatever reason), using isinstance() is preferred over type().

    The second parameter of isinstance() also accepts a tuple of types, so it’s possible to check for multiple types at once. isinstance will then return true, if the object is of any of those types:

    >>> isinstance([], (tuple, list, set))
    True
    
    0 讨论(0)
  • 2020-11-22 06:10

    In many practical cases instead of using type or isinstance you can also use @functools.singledispatch, which is used to define generic functions (function composed of multiple functions implementing the same operation for different types).

    In other words, you would want to use it when you have a code like the following:

    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
    

    Here is a small example of how it works:

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

    Additionaly we can use abstract classes to cover several types at once:

    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!
    
    0 讨论(0)
提交回复
热议问题