python 中的变量类型检测

Variable type detection in python

我正在研究在 python (2.5+) 中检测变量类型(列表与字符串)的方法,并遇到了一些看起来过于复杂的其他答案。

我找到了一个可以做到的

x.__class__.__name__

获取包含 class 名称的字符串。如果有的话,这有什么问题吗?它不是便携式的吗?什么时候会失败?

旧式会失败类; isinstance() 工作正常:

>>> class OldStyle: pass
...
>>> OldStyle.__class__.__name__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: class OldStyle has no attribute '__class__'
>>> isinstance(OldStyle(), OldStyle)
True

注意最好用isinstance(),接受sub类,包括virtual sub类(via abstract base classes).不要将您的代码绑定到特定类型。

例如,当您可以使用 isinstance(obj, numbers.Number) 时,您不想测试 obj.__class__.__name__ in ('int', 'float', 'complex');这样你的代码也将接受 decimal.Decimal 个对象。

问题是不同的 class 可以有相同的名称。

最简单的例子是针对在不同模块中定义的 classes(例如,考虑通用的通用名称,例如 NodeConnection)。

但是,即使在单个模块中也很容易证明这个问题:

class A(object): pass
B = A
class A(object): pass
C = A

b = B()
c = C()
b.__class__.__name__ == c.__class__.__name__
=> True
type(b) == type(c)
=> False

如果您不需要 class 的字符串表示形式,只需使用通过调用 type(obj).

返回的 type 对象

当然,根据您的用途,最好使用 isinstance 而不是直接处理 type 对象。

检测 Python 2.x 中的字符串的一个常见缺陷是混淆了 strunicode 类型。

assert isinstance("", str) is True
assert isinstance(u"", str) is True  # AssertionError!
assert isinstance(u"", unicode) is True
assert isinstance(u"", unicode) is True
assert isinstance("", unicode) is True  # AssertionError!
# Both lines below are always correct
assert isinstance("", basestring) is True
assert isinstance(u"", basestring) is True

如您所见,所有字符串都来自相同的基 class - 这就是允许统一类型检查的原因。 class 名称字符串查找是不可能的。

>>> "".__class__.__name__
'str'
>>> u"".__class__.__name__
'unicode'

你真的不应该调用 magic 函数,你可以只使用 type()isinstance()。两者之间的主要区别是 isinstance() 支持继承,所以如果你的 类 继承自其他 类 你可能想使用 isinstance().