Determine the type of an object?

后端 未结 13 2188
余生分开走
余生分开走 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:12

    Determine the type of a Python object

    Determine the type of an object with type

    >>> obj = object()
    >>> type(obj)
    
    

    Although it works, avoid double underscore attributes like __class__ - they're not semantically public, and, while perhaps not in this case, the builtin functions usually have better behavior.

    >>> obj.__class__ # avoid this!
    
    

    type checking

    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 the difference.

    Well that's a different question, don't use type - use 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)
    

    This covers the case where your user might be doing something clever or sensible by subclassing str - according to the principle of Liskov Substitution, you want to be able to use subclass instances without breaking your code - and isinstance supports this.

    Use Abstractions

    Even better, you might look for a specific Abstract Base Class from collections or 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)
    

    Or Just Don't explicitly Type-check

    Or, perhaps best of all, use duck-typing, and don't explicitly type-check your code. Duck-typing supports Liskov Substitution with more elegance and less verbosity.

    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)
    

    Conclusion

    • Use type to actually get an instance's class.
    • Use isinstance to explicitly check for actual subclasses or registered abstractions.
    • And just avoid type-checking where it makes sense.

提交回复
热议问题