简体   繁体   English

通过模块/文件导入的Python中的全局变量

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

Problem : 问题

I am trying to find a less clunky way to use (or accomplish something similar to) global variables. 我试图找到一种不太笨拙的方式来使用(或完成类似于)全局变量的方法。 Right now I have all of my global variables in a file g.py , so I access them using g.var . 现在,我将所有全局变量存储在文件g.py中 ,因此我使用g.var访问它们。

I would love to use var instead of g.var in my code, because I think it looks cleaner. 我想在代码中使用var而不是g.var ,因为我认为它看起来更干净。

Details : 详细资料

I have 3 files right now: 我现在有3个文件:

  • main.py : a small code for solving a PDE main.py :解决PDE的小代码
  • functions.py : a file that defines functions for applying boundary conditions functions.py :定义用于应用边界条件的functions.py的文件
  • g.py : a file that has the variables that are modified when functions from functions.py are called g.py :一个文件,该文件具有在调用来自functions.py的函数时修改的变量

g.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 : 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

And main.py calls bc_Neumann() at some point. 并且main.py在某个时候调用bc_Neumann()

Is there a better way to access g.ap , g.awx , etc.? 有没有更好的方法来访问g.apg.awx等? I would like to just reference these global variables as ap , awx , etc. 我只想将这些全局变量引用为apawx等。

You could import the variables directly, ie: 可以直接导入变量,即:

from g import ap, awx, aex, rhs

and then declare them as globals in your function (else they're considered locals and you'll get an UnboundLocalError when rebinding them): 然后在函数中将它们声明为全局变量(否则将它们视为本地变量,并且在重新绑定它们时会收到UnboundLocalError):

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

BUT this won't update the g.ap , g.awx etc variables accordingly when you rebind ap , awx etc. The reason why is that by importing your variables that way you make the names local to your functions module, so rebinding them from within your function only affects the functions module namespace. 但是当您重新绑定apawx等时,这不会相应地更新g.apg.awx等变量。其原因是通过导入变量使名称在functions模块中本地化,从而从中重新绑定它们函数中的内容仅影响functions模块的名称空间。

If that's not quite clear, think of module's scopes as dicts where the variable names are the keys. 如果还不清楚,则将模块的作用域视为变量名称为键的命令。 If you have two dicts A and B such as: 如果您有两个字典A和B,例如:

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

when in functions you do: functions执行以下操作:

from g import ap, aw

it's as if you were doing 好像你在做

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

at this stage, keys in A and B refers to the same objects so if you mutate B["ap"] (ie by appending something to it), it will be seen in A too: 在此阶段, AB键指向相同的对象,因此,如果您对B["ap"]突变(即,通过在其后面添加一些内容),也将在A看到它:

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

BUT if instead you rebind B["ap"] to a new list, then A["ap"] won't be affected and B["ap"] and A["ap"] will now refer to two different objects: 但是,如果改为将B [“ ap”] 重新绑定到新列表,则A["ap"]不会受到影响,并且B["ap"]A["ap"]现在将引用两个不同的对象:

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

FWIW, modules namespaces are exactly this: dicts. FWIW,模块名称空间正是这样:字典。

So to make a long story short: this won't work as expected... So you'll either have to move all your variables to the same module as the functions using them (and declare them as globals in the functions using them) or live with g.ap etc. 因此,总而言之:这将无法按预期工作...因此,您要么必须将所有变量与使用它们的函数移到同一模块(并在使用它们的函数中将它们声明为全局变量)或与g.ap等一起g.ap

This being said: global variables are a terrible idea , wherever they live. 话虽这么说:无论变量在哪里, 全局变量都是一个可怕的主意 If you have a set of functions working on (mutating and rebinding) the same set of variables, you most often want to make the whole thing a class: 如果您有一组处理(变异和重新绑定)同一组变量的函数,那么您通常会希望将整个事情变成一个类:

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)

If you don't want to explicitly state the variable names, you can use from g import * , but this is generally not recommended. 如果您不想显式声明变量名,则可以使用from g import * ,但是通常不建议这样做。 The reason is that explicitly stating the variable names makes it clear what variables are coming from where. 原因是,明确说明变量名称可以清楚地表明哪些变量来自何处。 If you said from g import * and from h import * and then started using some of their variables, it would be difficult to tell which comes from which without reading other files. 如果from g import *from h import *开始说,然后开始使用它们的某些变量,那么在不读取其他文件的情况下很难分辨出哪个来自哪个。 Even when only importing from one file, it's good to know before reading the file (by reading the top of the file) what names come from somewhere else. 即使仅从一个文件导入,也最好在读取文件之前(通过读取文件顶部)知道其他地方的名字。

Edit: If you want to use this style but also want to be able to modify the values contained inside g , you need these variables to be mutable objects. 编辑:如果要使用此样式,但又希望能够修改g内包含的值,则需要将这些变量设置为可变对象。 You can do this with arrays. 您可以使用数组执行此操作。

g.py: 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: 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

If you want ap , awx etc. to stay as an immutable object like a float, then your code should stay as-is, using eg g.ap . 如果您希望apawx等保持为不可变对象(如float),则您的代码应保持不变,例如使用g.ap

Make your variables a part of a dictionary (Or SimpleNameSpace, if brackets bother you). 使变量成为字典的一部分(如果括号引起您注意,则请输入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))

Then in functions.py you can import it as 然后可以在functions.py中将其导入为

from g import G

Now you can access/update the variables as G['ap'], G['awx'] etc. 现在,您可以访问/更新变量G ['ap'],G ['awx']等。

This works because Dictionaries and Lists are always treated as references. 这是可行的,因为字典和列表始终被视为引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM