如何在Python中获取完整类型名?
在Python中,使用type()
函数打印结果时,有时候会显示一些在当前环境中并不存在的类型名称。例如,下面的代码会显示"<type 'frame'>"
import inspect
a = inspect.currentframe()
print( type( a ) )
但是在当前环境中并没有frame
这个类型!如果我在交互式解释器中尝试使用它,就会出现错误:
>>> frame
NameError: name 'frame' is not defined
那么有没有办法获取一个“完整的”类型名称,比如“inspect.something.frame”,这样我就可以在我的代码中引用它呢?
更新
不幸的是,__module__
也不起作用:
>>> type( a ).__module__
'__builtin__'
3 个回答
unutbu的回答已经包含了所有具体的细节,但我们可以稍微退后一步来看。
你想做的事情,从整体上来说,是不可能的。这不仅仅是针对框架来说,对于任何东西都是如此。
print(x)
实际上是隐式地打印出 str(x)
的结果。如果你运气好,这个结果和 repr(x)
是一样的,但通常它给你的是人类可读的内容,而不是计算机能直接使用的。
当然,你可以通过使用 repr(x)
来绕过这个问题,而不是 str(x)
。但这 仍然 不能解决问题。
一个简单的经验法则是,repr(a)
要么给你一些包裹在尖括号里的无用信息,要么给你一些可以用 eval
重新计算回原值的内容,使得 == a
成立。但即便如此,这也不能完全依赖;这只是一个经验法则。
在这种情况下,一旦你得到了 <type 'frame'>
,这显然是第一种 repr
的情况,而它是无用的。
但好消息是:你只需要保留 x
,而不是保留 repr(x)
然后试图在后面重建 x
。
或者,在这个例子中,保留 type(a)
,这样你就得到了框架的类型。
这件事没有简单的方法来解决。一般来说,你可以直接使用:
x.__module__ + '.' + x.__name__
不过,如果这个对象在它的模块中不可访问,这种方法就不管用了;比如说,如果模块使用了del
来把这个对象从它的命名空间中删除,就会出现这种情况。
对于类的方法,PEP 3155引入了__qualname__
这个属性;但在这种情况下也没有帮助。type(a).__module__
的值是'__builtin__'
,但是frame
并不是__builtin__
模块中的一个名称。这种情况在用C语言实现的类型中比较常见。
在这种情况下,你需要知道frame
类型是在types
模块中的:
from types import FrameType as frame
"What's in a name? That which we call a frame
By any other name would smell as sweet."
如果你想找到一个框架对应的Python对象类型,可以使用:
In [38]: import types
In [39]: types.FrameType
Out[39]: <type 'frame'>
当然,这其实就是另一种写法,跟 type(a)
是一样的:
In [42]: import inspect
In [43]: a = inspect.currentframe()
In [44]: types.FrameType == type(a)
Out[44]: True
如果你查看一下 types
模块,你会发现 types.FrameType
是这样定义的:
try:
raise TypeError
except TypeError:
tb = sys.exc_info()[2]
TracebackType = type(tb)
FrameType = type(tb.tb_frame)
del tb
他们所做的就是找到一个 frame
的实例,然后把 FrameType
定义为这个实例的 type
。
这其实就是你在定义的时候所做的事情。
MyFrameType = type(a)
所以结论就是:要获取一个实例的类型,只需调用 type(obj)
。你不需要事先知道其他任何东西。