簡體   English   中英

帶有模塊導入的命名空間

[英]Namespaces with Module Imports

盡管我已經學習Python大約一年了,但是我正在學習Python並仍然是一個初學者。 我正在嘗試編寫一個在主模塊中調用的功能模塊。 被調用模塊中的每個函數都需要math模塊才能運行。 我想知道是否有一種方法可以不將數學模塊導入被調用模塊中。 這是我所擁有的:

main.py

from math import *
import module1

def wow():

    print pi


wow()
module1.cool()

module1.py

def cool():

    print pi

運行main.py我得到:

3.14159265359

Traceback (most recent call last):
  File "Z:\Python\main.py", line 10, in <module>
    module1.cool()
  File "Z:\Python\module1.py", line 3, in cool
    print pi
NameError: global name 'pi' is not defined

我很難理解的是為什么在運行main.py時出現名稱錯誤。 我知道變量pi在導入時對主模塊變為全局,因為wow可以訪問它。 我也知道cool在導入時成為主模塊的全局對象,因為我可以打印module1.cool並獲取<function cool at 0x02B11AF0> 因此,由於cool在主模塊的全局命名空間中,因此程序不應該首先在變量cool內部查找pi ,然后在其中找不到它時,在main模塊內部查找 pi查找在那嗎?

解決此問題的唯一方法是將math模塊導入module1.py 我不喜歡這樣的想法,盡管因為它會使事情變得更復雜,並且我喜歡漂亮,簡單的代碼。 我覺得我即將掌握名稱空間,但是在這方面需要幫助。 謝謝。

如回溯所示,問題不在main.py ,而在module1.py

Traceback (most recent call last):
  File "Z:\Python\main.py", line 10, in <module>
    module1.cool()
  File "Z:\Python\module1.py", line 3, in cool
    print pi
NameError: global name 'pi' is not defined

換句話說, module1 ,沒有全局名稱pi ,因為您尚未將其導入。 from math import * main.py from math import * main.py ,這只是將所有內容從math模塊的命名空間導入到main模塊的命名空間中,而不是導入到每個模塊的命名空間中。

我認為您在這里缺少的關鍵是每個模塊都有自己的“全局”名稱空間。 剛開始時這可能有點令人困惑,因為在諸如C之類的語言中,所有extern變量和函數共享一個全局名稱空間。 但是一旦您克服了這個假設,Python的方式就很有意義了。

所以,如果你想使用pimodule1 ,你所要做的from math import *module1.py (或者,您可以找到其他方式注入它—例如, module1.py可以from main import * ,或者main.py可以進行module1.pi = pi ,等等。或者您可以將pi塞入神奇的builtins / __builtin__模塊,或使用其他各種技巧。但顯而易見的解決方案是在要import位置進行導入。)


附帶說明一下,您通常不希望from foo import *進行交互交互式解釋器或頂級腳本之外的任何操作。 也有例外(例如,一些模塊明確設計為以這種方式使用),但經驗法則是import foo或使用from foo import bar, baz

“顯式勝於隱式”是Python的創建者做出的設計決定(啟動python並運行import this )。

因此,當您運行module1.cool() ,Python不會在main模塊中查找未定義的pi


每當需要使用數學模塊時,都必須顯式導入它-這就是Python的工作方式。

另外,您應避免from X import * -style導入,這也是一種不好的做法。 在這里,您可以執行以下操作: from math import pi

@abarnert的注釋中提到的exec (python 3)或execfile (python 2)的簡單方法可能對某些工作流程很有用。 所需要做的就是將導入行替換為:

exec( open("module1.py").read() )       # python 3

然后您可以簡單地使用cool()而不是module1.cool()調用函數。 cool() ,變量pi行為將像全局變量一樣,如OP最初期望的那樣。

簡而言之,這只是隱藏了一個函數定義,否則該函數定義將出現在主程序的頂部,並且具有優點和缺點。 對於具有多個模塊和導入的大型項目,使用exec (而不是適當的名稱空間)可能是一個錯誤,因為您通常不希望在單個全局名稱空間中保留太多內容。

但是對於簡單的情況(例如使用Python作為shell腳本), exec提供了一種簡單明了的方法來隱藏共享函數,同時讓它們共享全局名稱空間。 請注意,在這種情況下,您可能需要進一步考慮函數的命名方式(例如,使用v1_coolv2_cool來跟蹤不同的版本,因為您無法執行v1.coolv2.cool )。

在這里使用exec一個不太明顯的缺點是,盡管您可以解決此問題,但是執行的代碼中的錯誤可能不會顯示錯誤的行號: 如何在Python中從exec或execfile獲取錯誤的行號

就像其他人所說的那樣,您的module1實際上沒有全局pi 一個很好的解決方案是,它僅從math導入pi一次,並明確確保您獲取的pi是從module1獲取的pi

main.py

import module1

def wow():
    print module1.pi

wow()
module1.cool()

module1.py

from math import pi

def cool():
    print pi

在模塊內部,您可以簡單地from math import pi定義,這只會from math import pi ,而不是整個math模塊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM