【问题标题】:Variable type detection in pythonpython中的变量类型检测
【发布时间】:2015-11-27 09:42:46
【问题描述】:

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

我发现有人可以做

x.__class__.__name__

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

【问题讨论】:

  • AFAIK 没问题,但使用 isinstance() 有什么问题?
  • type() 方法呢?
  • @doublep 绝对没有——这只是突出了我的误解 :)

标签: python typechecking duck-typing runtime-type


【解决方案1】:

旧式课程会失败; 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() 并接受子类,包括虚拟 子类(通过abstract base classes)。不要将您的代码绑定到特定类型。

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

【讨论】:

    【解决方案2】:

    问题是不同的类可以有相同的名字。

    简单的例子是定义在不同模块中的类(例如,考虑通用的通用名称,例如 Node 或 Connection)。

    但是,即使在单个模块中也很容易演示此问题:

    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
    

    如果您不需要类的字符串表示,只需使用调用type(obj) 返回的type 对象。

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

    【讨论】:

    • 谢谢,类型对象是我在这里混淆的部分原因。
    【解决方案3】:

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

    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__.__name__
    'str'
    >>> u"".__class__.__name__
    'unicode'
    

    【讨论】:

      【解决方案4】:

      你真的不应该调用 magic 函数,你可以使用 type() 或 isinstance()。两者的主要区别在于isinstance() 支持继承,因此如果您的类继承自其他类,您可能需要使用isinstance()。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-24
        • 1970-01-01
        • 2019-07-24
        • 1970-01-01
        相关资源
        最近更新 更多