>>> type([]) is list
True
>>> type({}) is dict
True
>>> type('') is str
True
>>> type(0) is int
True
>>> type({})
<type 'dict'>
>>> type([])
<type 'list'>
这当然也适用于自定义类型:
>>> class Test1 (object):
pass
>>> class Test2 (Test1):
pass
>>> a = Test1()
>>> b = Test2()
>>> type(a) is Test1
True
>>> type(b) is Test2
True
那个's a different question, don'吨使用类型 - 使用 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)
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)
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)
结论
使用 type 实际获取实例的类 .
使用 isinstance 显式检查实际的子类或注册的抽象 .
并且只是避免在有意义的地方进行类型检查 .
3
虽然这些问题很老,但我偶然发现了一个正确的方法,我认为它仍然需要澄清, at least for Python 2.x (没有检查Python 3,但是因为问题出现在经典类中,这个版本已经消失了,这可能没关系) .
在这里我_1972829的问题: how can I determine the type of an arbitrary object ?关于使用或不使用isinstance的其他建议在很多评论和答案中都很好,但我并没有解决这些问题 .
type() 方法的主要问题是 it doesn't work properly with old-style instances :
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
#!/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
9 回答
要获取对象的类型,可以使用内置的type()函数 . 将对象作为唯一参数传递将返回该对象的类型对象:
这当然也适用于自定义类型:
请注意,
type()
将仅返回对象的直接类型,但无法告诉您类型继承 .为了解决这个问题,您应该使用isinstance函数 . 这当然也适用于内置类型:
isinstance()
通常是确保对象类型的首选方法,因为它也接受派生类型 . 因此,除非您确实需要类型对象(无论出于何种原因),否则使用isinstance()
优先于type()
.isinstance()
的第二个参数也接受一个类型元组,因此可以一次检查多个类型 . 如果对象属于以下任何类型,则isinstance
将返回true:您可以使用
type()
执行此操作:您可以使用
type()
或isinstance()
.请注意,您可以通过在同一名称的当前范围内分配变量来破坏
list
或任何其他类型 .上面我们看到
dict
被重新分配给一个字符串,因此测试:...失败 .
为了解决这个问题,请谨慎使用
type()
:除了之前的答案之外,值得一提的是collections.abc的存在,其中包含几个补充鸭子类型的抽象基类(ABCs) .
例如,而不是显式检查某些内容是否为列表:
你可以,如果你只想看看你所拥有的物品是否允许获取物品,请使用collections.abc.Sequence:
如果你对允许获取,设置和删除项目(即可变序列)的对象严格感兴趣,你可以选择
collections.abc.MutableSequence
.在那里定义了许多其他ABC,
Mapping
用于可用作 Map 的对象,Iterable
,Callable
等 . 所有这些的完整列表可以在the documentation for collections.abc.中看到小心使用isinstance
但是输入
在对象的实例上你也有:
属性 . 以下是从Python 3.3控制台获取的示例
请注意,在python 3.x和New-Style类(可选择从Python 2.6中可用)中,类和类型已合并,这有时会导致意外结果 . 主要是出于这个原因,我最喜欢的测试类型/类的方法是内置函数_197803 .
确定Python对象的类型
使用
type
确定对象的类型尽管它有效,但要避免使用双重下划线属性,例如
__class__
- 它们在语义上不公开,并且虽然在这种情况下可能不是这样,但内置函数通常具有更好的行为 .类型检查
那个's a different question, don'吨使用类型 - 使用
isinstance
:这涵盖了用户可能通过子类化
str
做一些聪明或明智的事情 - 根据Liskov Substitution的原则,您希望能够在不破坏代码的情况下使用子类实例 - 并且isinstance
支持这一点 .使用抽象
更好的是,您可能会从
collections
或numbers
中查找特定的抽象基类:或者只是不要明确地进行类型检查
或者,也许最重要的是,使用duck-typing,并且不要显式地键入 - 检查您的代码 . 鸭子打字支持Liskov替换更优雅和更少的冗长 .
结论
使用
type
实际获取实例的类 .使用
isinstance
显式检查实际的子类或注册的抽象 .并且只是避免在有意义的地方进行类型检查 .
虽然这些问题很老,但我偶然发现了一个正确的方法,我认为它仍然需要澄清, at least for Python 2.x (没有检查Python 3,但是因为问题出现在经典类中,这个版本已经消失了,这可能没关系) .
在这里我_1972829的问题: how can I determine the type of an arbitrary object ?关于使用或不使用isinstance的其他建议在很多评论和答案中都很好,但我并没有解决这些问题 .
type()
方法的主要问题是 it doesn't work properly with old-style instances :执行此代码段将产生:
我认为,这不是大多数人所期望的 .
__class__
方法是最接近正确性的方法,但它在一个关键的情况下不起作用:当传入的对象是旧式类(不是实例!)时,因为那些对象缺乏这样的属性 .这是我能想到的最小代码片段,它以一致的方式满足这样的合法问题:
使用
try
...except
块可能更像Pythonic . 这样,如果你有一个像列表那样嘎嘎叫的类,或者像dict一样嘎嘎叫,那么无论它的类型是什么,它都会表现得很好 .为了澄清,变量类型之间的首选方法是duck typing:只要变量响应的方法(和返回类型)是您的子例程所期望的,就像对待它一样对待它 . 例如,如果你有一个用
getattr
和setattr
重载括号运算符的类,但是使用了一些有趣的内部方案,那么如果's what it'试图模拟它,它就适合表现为字典 .type(A) is type(B)
检查的另一个问题是,如果A
是B
的子类,则在编程方面,当您希望它是true
时,它将计算为false
. 如果一个对象是列表的子类,它应该像列表一样工作:检查另一个答案中显示的类型将阻止这种情况 . (isinstance
会起作用) .