获取Python中对象的完全限定类名

201 投票
13 回答
143624 浏览
提问于 2025-04-15 17:45

为了记录日志,我想获取一个Python对象的完整类名。(这里的完整类名是指包括包和模块名称的类名。)

我知道可以用 x.__class__.__name__ 来获取类名,但有没有简单的方法可以获取包和模块的信息呢?

13 个回答

33

这里有一个基于Greg Bacon很棒的回答,但增加了一些额外的检查:

__module__ 可能是 None(根据文档说明),而且对于像 str 这样的类型,它的值可能是 __builtin__(你可能不希望这个出现在日志或其他地方)。下面的代码检查了这两种情况:

def fullname(o):
    module = o.__class__.__module__
    if module is None or module == str.__class__.__module__:
        return o.__class__.__name__
    return module + '.' + o.__class__.__name__

(可能有更好的方法来检查 __builtin__。上面的代码只是依赖于 str 始终可用,并且它的模块总是 __builtin__

59

提供的答案没有涉及到嵌套类。

从 Python 3.3 开始(具体可以参考PEP 3155),你可以使用类的 __qualname__,而不是 __name__。否则,像下面这样的类

class Foo:
    class Bar: # this one
        pass

只会显示为 Bar,而不是 Foo.Bar

(你仍然需要单独将 __module__ 附加到 qualname,因为 __qualname__ 本身并不包含模块名。)

219

下面这个程序

#!/usr/bin/env python

import foo

def fullname(o):
    klass = o.__class__
    module = klass.__module__
    if module == 'builtins':
        return klass.__qualname__ # avoid outputs like 'builtins.str'
    return module + '.' + klass.__qualname__

bar = foo.Bar()
print(fullname(bar))

还有 Bar 这个类是这样定义的

class Bar(object):
  def __init__(self, v=42):
    self.val = v

运行后会得到这样的输出

$ ./prog.py
foo.Bar

如果你还在用 Python 2,那你需要用 __name__ 代替 __qualname__,不过 __name__ 对于嵌套类的信息就没那么详细了——比如一个类 Bar 嵌套在另一个类 Foo 里面,输出会显示为 Bar,而不是 Foo.Bar

def fullname(o):
    klass = o.__class__
    module = klass.__module__
    if module == '__builtin__':
        return klass.__name__ # avoid outputs like '__builtin__.str'
    return module + '.' + klass.__name__

撰写回答