2012-01-27 61 views
6

如果有疑問,我通常會將我的導入語句放在模塊的頂部。通常,這會減少重複,這很好。但是,在只有一個函數(或類)需要導入的情況下,是否存在性能下降?Python在函數級VS導入。模塊級別

只有在函數被調用時纔會導入以下內容:

 def func(): 
     from task import test 

如果是這樣,我想這可能是一個輕微的效率。我還假設你可以得到一些更快的垃圾收集和變量作用域的附加點,因爲導入的對象不會被添加到全局字典中。作爲另一張海報很好地說:

這主要是由於變量查找。在全局範圍內查找變量需要查找字典。相反,編譯器靜態地確定本地名稱並通過索引引用它們,因此不需要查找字典。

這些公平的假設是我完全脫離基地嗎?

感謝

+2

至於名稱查詢性能:**沒關係**在極少數情況下,您會發現代碼完成後,發現它太慢並且異形。 – delnan 2012-01-27 17:53:13

回答

4

函數中的導入只在函數運行時才導入。請記住,在Python中,所有語句都會在遇到時執行,而導入是像其他任何語句一樣的語句。導入模塊時導入頂級導入,因爲它們是模塊中的頂級語句。

您對名稱查找的擔心是錯誤的:差異可以忽略不計,只應在分析顯示問題時才考慮。

我只將模塊導入到函數作用域中,原因有兩個:1)修復循環導入問題,它可能可以通過重構以其他方式解決,或者2)如果模塊是可選的,並且函數不是被我的許多用戶使用。在2)的情況下,模塊可以完全丟失,除非有人調用該函數,否則不會有問題。

+0

這更像是一個理論問題。看起來有所不同,即使可以忽略不計。謝謝內德 – Ben 2012-01-27 18:43:07

+0

這是最pythonic的方式?我看到一些人在他們的模塊根目錄的__init__.py處輸入,並從那裏輸入所有內容。這可以用來解決某些循環進口? – radtek 2015-01-09 15:23:38

3

讓我們看看字節碼是什麼樣子以下兩個功能:

def func1(): 
    """ test imported each time function is run """ 
    from task import test 
    test() 

def func2(): 
    """ test was imported at top of module """ 
    test() 

正如你可以看到下面,func2()通過使用全球進口test功能節省了大量的步驟。

>>> dis.dis(func1) 
    3   0 LOAD_CONST    1 (-1) 
       3 LOAD_CONST    2 (('test',)) 
       6 IMPORT_NAME    0 (task) 
       9 IMPORT_FROM    1 (test) 
      12 STORE_FAST    0 (test) 
      15 POP_TOP 

    4   16 LOAD_FAST    0 (test) 
      19 CALL_FUNCTION   0 
      22 POP_TOP 
      23 LOAD_CONST    3 (None) 
      26 RETURN_VALUE 
>>> dis.dis(func2) 
    3   0 LOAD_GLOBAL    0 (test) 
       3 CALL_FUNCTION   0 
       6 POP_TOP 
       7 LOAD_CONST    1 (None) 
      10 RETURN_VALUE 

正如delnan的評論所指出的,考慮到這一點可能是不成熟的優化。

至於test位於全局命名空間中,這不太可能導致任何查找性能問題。我認爲你可以看到的最顯着的方式是,如果發生了test的散列衝突,並且你經常使用另一個名稱,導致第二個名字的查找花費更長的時間。再次,不成熟的優化考慮這種罕見的情況。

+1

但是請注意,它不會多次導入模塊 - 它只是檢查是否每次都調用它。 – delnan 2012-01-27 18:02:08

+0

感謝您這樣鋪設;這很有用。不熟悉DIS庫。 – Ben 2012-01-27 18:44:01

0

我認爲如果不會經常調用它,那麼將導入置於定義中是有意義的。