2012-03-09 65 views
3

對不起,如果這是一個非常新手的問題,我只是想知道一件事。圍繞Python導入嗎?

當在python中,你的代碼被分割成多個文件時,你會如何避免同一件事情上的大量進口?

說我有2個文件。主要和內容。

主營:

import pygame 
from pygame.locals import * 
pygame.display.init() 
blah 

內容:

import pygame 
from pygame.locals import * 
pygame.display.init() 
load content and stuff 

pygame導入兩次,display.init被調用了兩次。這在其他地方是有問題的。無論如何要解決這個問題,還是隻有進口和進口?

我能想到的一種情況是:每次導入文件時寫入文件的腳本。這樣,如果它被導入3次,它會運行3次,因此寫入文件3次。

在此先感謝!

回答

3

您應該避免在導入時發生任何事情(除非另有說明)。一個python文件首先是一個模塊,所以它可以並且應該被其他python模塊使用。如果在python文件的導入階段出現「發生」,那麼當該文件被另一個模塊導入時,它可能會以不希望的方式發生。

每個模塊應該只是定義要使用事情:類,函數,常量,只是等待別的東西來使用它們。


很顯然,如果沒有腳本在進口不斷的話,那麼這是不可能的事情真正得到使用,使東西「發生」。對於模塊直接調用的不尋常情況,有一個特殊的習慣用法。每個python文件都有一個變量,__name__用它被導入的模塊名稱自動創建。當您從命令行運行腳本時(或者您已經啓動它),它不會被導入,並且沒有名稱,因此__name__變量將具有特殊值"__main__",表示它是腳本正在執行。您可以檢查此條件,並採取相應的行動:

# main.py 
import pygame 
from pygame.locals import * 

import content 

def init(): 
    pygame.display.init() 

def stuff(): 
    content.morestuff() 

if __name__ == '__main__': 
    init() 
    stuff() 
# content.py 
import pygame 
from pygame.locals import * 

def init(): 
    pygame.display.init() 

def morestuff(): 
    "do some more stuff" 

if __name__ == '__main__': 
    init() 
    morestuff() 

這種方式; init(),因此pygame.display.init()只能由用戶運行的腳本調用一次。假設已經調用init()的代碼被分解爲另一個函數,並根據主腳本的需要進行調用(無論發生什麼)

+0

比弗朗西斯更具描述性的答案。 – SuperDisk 2012-03-09 01:34:48

6

您誤解了import的功能。這與include不一樣。加載模塊是單身人士,他們的相應文件不會被評估兩次。

也就是說,構造良好的模塊不會對導入產生副作用。這就是if __name__=='__main__'成語的目的。

不要試圖「清理」您的進口。從文件中導入需要使用的所有內容。您可以減少使用import *,但這純粹是爲了代碼的可讀性和可維護性。

+0

對(另請參見[早先類似的問題](http://stackoverflow.com/questions/2029523/how-to-prevent-a-module-from-being-imported-twice)),雖然有奇怪的角落在這種情況下,你可以愚弄Python,認爲兩個模塊實際上是相同的;看[koichitamura博客條目](http://koichitamura.blogspot.com/2009/07/ill-show-you-case-where-one-file.html)。 – torek 2012-03-09 01:29:09

+1

@francis減少使用「import *」的建議非常重要 - 然而,「pygame.locals」模塊是一種特殊情況,它被設計爲像這樣工作 - 它只包含綁定到大寫變量的數字常量,如鍵代碼,視頻模式等等。 – jsbueno 2012-03-09 04:02:11

0

import語句應該是您正在使用的某些語句的聲明另一個模塊。不應該使用它們來引起某些事情發生(如寫入文件)。正如弗朗西斯阿維拉指出的那樣,Python會盡量不要多次執行模塊的代碼。

這樣做的結果是,給定的import語句是否會導致發生任何事情,在運行時應用程序的屬性是全局;你不能僅僅從模塊的導入語句和源代碼中知道,因爲它取決於項目中其他任何其他代碼是否已經導入了該模塊。

因此,執行模塊時「執行某些操作」通常是實現應用程序的一種非常脆弱的方式。雖然沒有硬性和快速的「做某事」的定義,因爲顯然這個模塊需要創建其他模塊從它導入的所有東西,這可能涉及讀取配置文件,甚至可能寫入日誌文件或任何數量的其他事情。但是任何看起來像你的程序的「動作」,而不是僅僅「設置」從模塊導入的東西,通常不應該在模塊範圍內完成。