繁体   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