来自不同文件Python的全局变量

时间:2010-08-03 20:28:55

标签: python

所以我有两个不同的文件:

file1.py

from file2 import *
foo = "bar";
test = SomeClass();

file2.py

class SomeClass :
    def __init__ (self):
        global foo;
        print foo;

但是我似乎无法让file2识别来自file1的变量,即使它已经导入到file1中。如果以某种方式可行,这将是非常有用的。

9 个答案:

答案 0 :(得分:43)

file2中导入file1.py会使file2中绑定的全局(即模块级别)名称可用于file1中的以下代码 - 唯一的此类名称为{ {1}}。 执行相反的操作:当SomeClass导入file1时,file2中的代码无法用于file1中的代码。即使你以正确的方式导入正确的方式(file2,而不是你正在做的那种可怕的,可怕的方式)(如果太阳下的每个人都忘记了它的存在),情况也是如此。构建import file2,生活将所以对每个人都好得多。)

显然,您希望将from ... import *中定义的全局名称用于file1 中的代码,反之亦然。这被称为“循环依赖”,并且是一个可怕的想法(在Python或其他任何地方)。

所以,我不是要向你展示难以置信的脆弱,通常难以维护的黑客(在某种程度上相似)Python中的循环依赖,我宁愿讨论你可以避免这种可怕的结构。

例如,您可以将第三个​​模块中的两个模块都需要可用的全局名称(例如file2),以继续您的命名连胜;-)并导入第三个将模块分配到其他两个模块中file3.pyimport file3中的file1,然后使用file2等,即限定名称,为了从其他模块中的任何一个或两个模块访问或设置这些全局名称,裸名称。)

当然,如果你澄清(通过编辑你的Q)确切地为什么你认为你需要一个周期性的依赖(只是一个简单的预测:无论是什么让你),可以提供越来越多的具体帮助认为你需要一个周期性的依赖,你错了; - )。

答案 1 :(得分:11)

写作时

from file2 import *

它实际上file2中定义的名称复制到file1的命名空间中。因此,如果您通过编写

file1中重新分配这些名称
foo = "bar"

例如,它只会在file1而不是file2进行更改。请注意,如果您要更改foo属性,请执行

foo.blah = "bar"

然后该更改将反映在file2中,因为您正在修改名称foo引用的现有对象,而不是用新对象替换它。

您可以在file1.py中执行此操作,获得所需的效果:

import file2
file2.foo = "bar"
test = SomeClass()

(请注意,您应该删除from foo import *)尽管我建议您仔细考虑是否确实需要这样做。从另一个模块中更改一个模块的变量并不常见。

答案 2 :(得分:9)

from file2 import *正在制作副本。你想这样做:

import file2
print file2.foo
print file2.SomeClass()

答案 3 :(得分:4)

global在Python中有点用词不当,module_namespace会更具描述性。

foo的完全限定名称是file1.foo,并且最好避免全局声明,因为通常有更好的方法来完成您想要做的事情。 (我无法从你的玩具示例中分辨出你想做什么。)

答案 4 :(得分:1)

搜索后,我得到了以下提示:https://instructobit.com/tutorial/108/How-to-share-global-variables-between-files-in-Python

关键是:如果激活了某个功能,则打开该功能以调用设置为全局的variabel。

然后从该文件再次导入variabel。

我给你一个困难的例子,这样你就可以理解:

文件chromy.py

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

def opennormal():
    global driver
    options = Options()
    driver = webdriver.Chrome(chrome_options=options)

def gotourl(str):
    url = str
    driver.get(url)

文件tester.py

from chromy import * #this command call all function in chromy.py, but the 'driver' variable in opennormal function is not exists yet. run: dir() to check what you call.

opennormal() #this command activate the driver variable to global, but remember, at the first import you not import it

#then do this, this is the key to solve:
from chromy import driver #run dir() to check what you call and compare with the first dir() result.

#because you already re-import the global that you need, you can use it now

url = 'https://www.google.com'
gotourl(url)

这就是调用函数中设置的全局变量的方式。干杯 别忘了给予信用

答案 5 :(得分:0)

我得出的结论是,您可以导入全局变量,但一旦导入就无法更改它们。唯一的例外是如果您将它们作为参数传递。我很想在这方面出错,所以让我知道是否有办法有效地重新导入更新的全局变量。下面的两个代码将运行。

from b import *  # import all from b.py

global alpha  # declare globals
global bravo
global charlie

alpha = 10  # assign values to globals
bravo = 20
charlie = 15


def run_one():
    one(alpha)  # pass the global to b.py


def run_two():
    two()  # rely on import statement in b.py


def run_three():
    global charlie  # declare the global to change it
    charlie = 40  # change the value for charlie
    print("charlie:", charlie, " --> global value changed in a.py run_three()")


def run_three_again():  # print charlie again from b.py
    three()


def run_four():  # re import charlie in b.py
    four()


if __name__ == "__main__":  # prevent the code from being executed when b.py imports a.py
    run_one()  # run through all the functions in a.py
    run_two()
    run_three()
    run_three_again()
    run_four()

还有:

from a import *  # import all from a.py


def one(alpha):
    print("alpha:  ", alpha, " --> global passed as arguement in one()")


def two():
    print("bravo:  ", bravo, " --> global imported from a.py in two()")


def three():
    print("charlie:", charlie, " --> global imported from a.py in three() but is not changed")


def four():
    from a import charlie  # re import charlie from a.py
    print("charlie:", charlie, " --> global re-imported in four() but does not change")

打印语句的输出如下:

alpha:   10  --> global passed as argument in one()
bravo:   20  --> global imported from a.py in two()
charlie: 40  --> global value changed in a.py run_three()
charlie: 15  --> global imported from a.py in three() but is not changed
charlie: 15  --> global re-imported in four() but does not change

答案 6 :(得分:0)

当我按照@robertspierre 的想法进行测试时,将所有全局变量放在一个 glv.py 文件中,然后将其导入到其他使用它的文件中,下面给出了演示代码,希望对您有所帮助:

>
  1. 全局变量文件,glv.py:
# glv.py
glvB = True
glvA = 100
glvS = "tiger"
glvList = [1, 2, 3]
glvTuple = (1, "a")
glvDict = {"Name": "tiger", "age": 100}
  1. sub1.py,这是一个将导入 glv.py 文件的文件。 glv.py中定义了两个函数来显示和改变全局变量数据,showData()和changeData(),
# sub1.py
import glv


def showData():
    print(f"*****glv in sub1*****\n"
          f"glvB={glv.glvB}\n"
          f"glvA={glv.glvA}\n"
          f"glvS={glv.glvS}\n"
          f"glvList={glv.glvList}\n"
          f"glvTuple={glv.glvTuple}\n"
          f"glvDict={glv.glvDict}\n")


def changeData():
    glv.glvB = False
    glv.glvA = 200
    glv.glvS = "bactone"
    glv.glvList = [4, 5, 6]
    glv.glvTuple = (2, "b")
    glv.glvDict = {"Name": "bactone", "age": 0}
  1. sub2.py 是另一个文件:
# sub2.py

import glv


def showData():
    print(f"*****glv in sub2*****\n"
          f"glvB={glv.glvB}\n"
          f"glvA={glv.glvA}\n"
          f"glvS={glv.glvS}\n"
          f"glvList={glv.glvList}\n"
          f"glvTuple={glv.glvTuple}\n"
          f"glvDict={glv.glvDict}\n")


def changeData():
    glv.glvB = True
    glv.glvA = 300
    glv.glvS = "bactone"
    glv.glvList = [7, 8, 9]
    glv.glvTuple = (3, "c")
    glv.glvDict = {"Name": "bactone1", "age": 10}
  1. 最后我们在 main.py 中测试全局变量:
import glv
import sub1
import sub2


def showData():
    print(f"*****initial global variable values*****\n"
          f"glvB={glv.glvB}\n"
          f"glvA={glv.glvA}\n"
          f"glvS={glv.glvS}\n"
          f"glvList={glv.glvList}\n"
          f"glvTuple={glv.glvTuple}\n"
          f"glvDict={glv.glvDict}\n")


if __name__ == "__main__":

    showData()  # show initial global variable
    sub1.showData()  # show global variable in sub1
    sub1.changeData()  # change global variable in sub1
    sub2.showData()  # show global variable in sub2
    sub2.changeData()  # change global variable in sub2
    sub1.showData()  # show global variable in sub1 again

结果是:

*****initial global variable values*****
glvB=True
glvA=100
glvS=tiger
glvList=[1, 2, 3]
glvTuple=(1, 'a')
glvDict={'Name': 'tiger', 'age': 100}

*****glv in sub1*****
glvB=True
glvA=100
glvS=tiger
glvList=[1, 2, 3]
glvTuple=(1, 'a')
glvDict={'Name': 'tiger', 'age': 100}

*****glv in sub2*****
glvB=False
glvA=200
glvS=bactone
glvList=[4, 5, 6]
glvTuple=(2, 'b')
glvDict={'Name': 'bactone', 'age': 0}

*****glv in sub1*****
glvB=True
glvA=300
glvS=bactone
glvList=[7, 8, 9]
glvTuple=(3, 'c')
glvDict={'Name': 'bactone1', 'age': 10}

我们可以看到各种数据类型都有效,并且全局变量的变化会自动重新加载。

答案 7 :(得分:-1)

将您的全局变量放入要导入的文件中。

答案 8 :(得分:-2)

所有给出的答案都是错误的。在单独的文件中将函数内的变量全局化是不可能的。