簡體   English   中英

通過模塊/文件導入的Python中的全局變量

[英]Global variables in Python through modules/file import

問題

我試圖找到一種不太笨拙的方式來使用(或完成類似於)全局變量的方法。 現在,我將所有全局變量存儲在文件g.py中 ,因此我使用g.var訪問它們。

我想在代碼中使用var而不是g.var ,因為我認為它看起來更干凈。

詳細資料

我現在有3個文件:

  • main.py :解決PDE的小代碼
  • functions.py :定義用於應用邊界條件的functions.py的文件
  • g.py :一個文件,該文件具有在調用來自functions.py的函數時修改的變量

g.py

import numpy as np
# variables
ap  = np.float64(0.0)
awx = np.float64(0.0)
aex = np.float64(0.0)
rhs = np.float64(0.0)

functions.py

import g

def bc_Neumann(i,m,nx):
    m[0]=int(i); m[1]=int(i-1); m[2]=int(i+1);
    if i==0:
        m[1]=nx-1
        g.ap=g.ap+g.awx
        g.awx=0.0
    if i==nx-1:
        m[2]=0
        g.ap=g.ap+g.aex
        g.aex=0.0
    return m

並且main.py在某個時候調用bc_Neumann()

有沒有更好的方法來訪問g.apg.awx等? 我只想將這些全局變量引用為apawx等。

可以直接導入變量,即:

from g import ap, awx, aex, rhs

然后在函數中將它們聲明為全局變量(否則將它們視為本地變量,並且在重新綁定它們時會收到UnboundLocalError):

def bc_Neumann(i,m,nx):
    global ap, awx, aex, rhs
    # your code here

但是當您重新綁定apawx等時,這不會相應地更新g.apg.awx等變量。其原因是通過導入變量使名稱在functions模塊中本地化,從而從中重新綁定它們函數中的內容僅影響functions模塊的名稱空間。

如果還不清楚,則將模塊的作用域視為變量名稱為鍵的命令。 如果您有兩個字典A和B,例如:

A = {"ap":[], "aw":[]}
B = {}

functions執行以下操作:

from g import ap, aw

好像你在做

B["ap"] = A["ap"]
B["aw"] = A["aw"]

在此階段, AB鍵指向相同的對象,因此,如果您對B["ap"]突變(即,通過在其后面添加一些內容),也將在A看到它:

B["ap"].append(1)
print A["ap"]

但是,如果改為將B [“ ap”] 重新綁定到新列表,則A["ap"]不會受到影響,並且B["ap"]A["ap"]現在將引用兩個不同的對象:

B["ap"] = [42, 43]
print A["ap"]

FWIW,模塊名稱空間正是這樣:字典。

因此,總而言之:這將無法按預期工作...因此,您要么必須將所有變量與使用它們的函數移到同一模塊(並在使用它們的函數中將它們聲明為全局變量)或與g.ap等一起g.ap

話雖這么說:無論變量在哪里, 全局變量都是一個可怕的主意 如果您有一組處理(變異和重新綁定)同一組變量的函數,那么您通常會希望將整個事情變成一個類:

class Whatever(object):
    def __init__(self):
        self.ap  = np.float64(0.0)
        self.awx = np.float64(0.0)
        self.aex = np.float64(0.0)
        self.rhs = np.float64(0.0)

   def bc_neumann(self, i,m,nx):
      m[0] = int(i) 
      m[1] = int(i-1) 
      m[2] = int(i+1)
      if i == 0:
          m[1] = nx - 1
          self.ap = self.ap + self.awx
          self.awx = 0.0
      if i == nx-1:
          m[2] = 0
          self.ap = self.ap + self.aex
          self.aex = 0.0
      return m


w = Whatever()
w.bc_neumann(1, [], 42)
from g import ap, awx, aex, rhs
print(ap, awx, aex, rhs)

如果您不想顯式聲明變量名,則可以使用from g import * ,但是通常不建議這樣做。 原因是,明確說明變量名稱可以清楚地表明哪些變量來自何處。 如果from g import *from h import *開始說,然后開始使用它們的某些變量,那么在不讀取其他文件的情況下很難分辨出哪個來自哪個。 即使僅從一個文件導入,也最好在讀取文件之前(通過讀取文件頂部)知道其他地方的名字。

編輯:如果要使用此樣式,但又希望能夠修改g內包含的值,則需要將這些變量設置為可變對象。 您可以使用數組執行此操作。

g.py:

import numpy as np
# variables, dtype is float64 by default
ap = np.array([0.0])
awx = np.array([0.0])
aex = np.array([0.0])
rhs = np.array([0.0])

functions.py:

from g import ap, awx, aex, rhs

def bc_Neumann(i, m, nx):
    m[0] = int(i)
    m[1] = int(i-1)
    m[2] = int(i+1)
    if i == 0:
        m[1] = nx-1
        ap[0] = ap + awx
        awx[0] = 0.0
    if i == nx-1:
        m[2] = 0
        ap[0] = ap + aex
        aex[0] = 0.0
    return m

如果您希望apawx等保持為不可變對象(如float),則您的代碼應保持不變,例如使用g.ap

使變量成為字典的一部分(如果括號引起您注意,則請輸入SimpleNameSpace)。

g.py

import numpy as np
# variables
G = dict(ap  = np.float64(0.0),
         awx = np.float64(0.0),
         aex = np.float64(0.0),
         rhs = np.float64(0.0))

然后可以在functions.py中將其導入為

from g import G

現在,您可以訪問/更新變量G ['ap'],G ['awx']等。

這是可行的,因為字典和列表始終被視為引用。

暫無
暫無

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

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