[英]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.ap
, g.awx
等? 我只想将这些全局变量引用为ap
, awx
等。
您可以直接导入变量,即:
from g import ap, awx, aex, rhs
然后在函数中将它们声明为全局变量(否则将它们视为本地变量,并且在重新绑定它们时会收到UnboundLocalError):
def bc_Neumann(i,m,nx):
global ap, awx, aex, rhs
# your code here
但是当您重新绑定ap
, awx
等时,这不会相应地更新g.ap
, g.awx
等变量。其原因是通过导入变量使名称在functions
模块中本地化,从而从中重新绑定它们函数中的内容仅影响functions
模块的名称空间。
如果还不清楚,则将模块的作用域视为变量名称为键的命令。 如果您有两个字典A和B,例如:
A = {"ap":[], "aw":[]}
B = {}
在functions
执行以下操作:
from g import ap, aw
好像你在做
B["ap"] = A["ap"]
B["aw"] = A["aw"]
在此阶段, A
和B
键指向相同的对象,因此,如果您对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
如果您希望ap
, awx
等保持为不可变对象(如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.