2013-03-01 81 views
2

在Python中打印結果type()有時會顯示不在當前範圍內的類型名稱。例如,下面的代碼將顯示"<type 'frame'>"如何在Python中獲得完整的類型名稱?

import inspect 
a = inspect.currentframe() 
print(type(a)) 

但沒有frame類型在當前範圍內!如果我嘗試在交互式解釋器中使用它,我得到一個錯誤:

>>> frame 
NameError: name 'frame' is not defined 

因此,它是沒有辦法得到一個「完全合格」類型的名稱,比如「inspect.something.frame」這樣我就可以參考它在我的代碼?

UPDATE

不幸的是,__module__是不是工作壓力太大:

>>> type(a).__module__ 
'__builtin__' 
+0

你是指'>>> frame'而不是'>>> type'? – mgilson 2013-03-01 19:13:06

+0

@mgi是的,當然,謝謝! – grigoryvp 2013-03-01 19:13:55

+0

我不認爲這是可行的。下面的答案中提到'__module__'屬性可能有助於獲得部分解決方案,但一般情況下是不可解的。 – entropy 2013-03-01 19:21:06

回答

2
"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)。你不需要知道aprior其他的東西。

+0

我正在尋找一種方法來找出沒有** types.FrameType的** foreknowledge的對象類型。只給出我的例子中的一個''對象,**沒有**知識'frame'是'types.FrameType' - 你怎麼能解決這個問題? – grigoryvp 2013-03-01 19:25:21

+1

使用'type(a)'沒有什麼錯誤。一個對象是一個對象,並且你已經找到了你想要的對象。只要* define *'FrameType = type(a)'如果你願意的話。沒有必要知道關於'types.FrameType'的* aprior *。如果你看一下'types'模塊,你可能會很震驚地發現這基本上是他們如何定義'types.FrameType'。 – unutbu 2013-03-01 19:27:52

+0

鑑於'frame' - 你怎麼能發現它在'types'裏面並且被稱爲'FrameType'? – grigoryvp 2013-03-01 19:32:47

0

有沒有簡單的方法來做到這一點。一般情況下,你可以使用:

x.__module__ + '.' + x.__name__ 

但是,如果對象不是來自它的模塊訪問,這將不起作用;例如,如果模塊使用del從其名稱空間中刪除對象,則會發生這種情況。

對於類方法,PEP 3155介紹了__qualname__屬性;但這在這種情況下也無濟於事。 type(a).__module__'__builtin__',但frame不是__builtin__模塊中的名稱。這與在C中實現的類型相當常見

在這種情況下,你必須知道的是,frame類型是types模塊:

from types import FrameType as frame 
+0

這不公平:)。我無法「知道」「框架」實際上是來自「類型」的「框架類型」。有沒有預知未知的方法來解決這個問題? – grigoryvp 2013-03-01 19:23:45

+0

@EyeofHell:你不需要知道,因爲你永遠不需要動態地發現'types.FrameType'。當你知道你需要一個FrameType時,那個定義就在那裏,並且需要知道它是什麼類型。另一方面,如果你已經有一個框架'a',你所需要的只是'type(a)'來獲得類型。重讀unutbu的答案;它詳細解釋了一切。 – abarnert 2013-03-01 19:37:45

0

unutbu的回答已經包含了所有的具體細節在這裏,但讓我們退一步一點。

你想要做的是,一般來說,是不可能的。不只是框架,而是任何東西

print(x)隱式打印出str(x)。如果你幸運的話,這與repr(x)相同,但它通常會給你一些人類可讀的東西,而不是電腦可用的東西。

當然,您可以通過僅使用repr(x)而不是str(x)來解決此問題。但是仍然沒有幫助。

這是一個很好的經驗法則,repr(a)給你一個無用的東西括在尖括號,或者可以eval返回到值== a。但即使如此也不能依賴;這只是一個經驗法則。

而在這種情況下,一旦得到<type 'frame'>,這顯然是第一種repr,並且它是無用的。

但是有一個好消息:你需要做的就是保持x左右,而不是保持repr(x)左右,並在稍後嘗試重建x

或者,在這種情況下,請保留type(a),並且您有幀類型。

+0

Instanciating堆棧跟蹤只是爲了檢查給定對象的類型似乎對我來說不是非常pythonic :(.' isinstance(something,types.FrameType)'讀取更好,但它需要預知'frame'隱藏的地方 – grigoryvp 2013-03-01 20:10:31

+0

@EyeofHell:是的,如果你事先靜態地知道你想檢查框架,可以使用'types.FrameType',並且你通過閱讀文檔的方式來找到它,只有當你想動態地執行你需要的東西時以編程方式解決它。 – abarnert 2013-03-01 20:19:23

相關問題