在Python中从其他文件调用变量

3 投票
5 回答
11229 浏览
提问于 2025-04-17 12:55

我正在尝试导入文件,情况是这样的。

file1.py 文件里包含:

from file2 import *
username = "steven"

action()

file2.py 文件里包含:

def action():
    print username 

但是我无法打印用户名,因为变量 'username' 在 file1 中声明,但在 file2 中没有(因为函数使用了这个变量)。

这不是实际的代码,但我不能在 file2 的函数中使用 file1 的变量吗?

5 个回答

1

但是,file2.py并没有导入file1.py,那它怎么会知道username这个东西存在呢?


顺便说一下,我尽量避免在我的代码中出现循环依赖(也就是说,模块x导入模块y,而模块y又导入模块x),所以单纯地把file1导入到file2可能不是最好的解决办法。

2

你想要的那种方式,需要文件1导入文件2,同时文件2也要导入文件1。这样做在代码中会导致循环导入,这种情况是行不通的。

除此之外,如果你在一个文件中的函数、类或方法需要知道另一个文件中的数据,正确的做法是把这些数据作为函数的参数传进去。

在你的例子中,你的“action”函数应该是:

def action(username):
    print username 

然后在文件1中:

from file2 import action
username = "steven"

action(username)

(你还应该避免使用“import *”,因为这样会让人不清楚名字是从哪里来的,读代码时会很难维护)

当然,Python有它自己的方式来解决你想要的事情——你可以创建一个特殊的装饰器,用在你导入的函数上,这样可以从另一个文件重建你的函数,并指向当前模块的全局变量,但这样做其实没什么意义。

在面向对象编程(OOP)中,有一种比较特殊的情况,和你想做的有点像——就是一个方法使用类的属性。如果这个属性在子类中被重写了,那么这个方法(即使是原来的父类方法)也会使用新的属性值,比如:

class A(object):
    username = ""
    def action(self):
         print self.__class__.username

而类B可以在其他文件中定义,正如你所想的那样:

from file2 import A
class B(A):
    username = "Mike"

b = B()
b.action()

现在,为了给你一个完整的答案,这里有一些代码可以实现你想要的功能——但_不要这样做_,请修改你的函数,让它们接收参数。

可以做的是创建一个函数来读取调用它的地方的全局变量。这不仅仅是“不好的做法”,而且是错误的,除非在一些文档非常完善的框架中使用了“魔法变量名”来进行配置。即使我发现一个框架有这样的坏习惯,我也倾向于修补它的函数,以便我可以通过函数调用明确地传递配置。

from inspect import currentframe

def action():
    caller_frame = current_frame(1)
    caller_globals = caller_frame.f_globals
    print caller_globals["username"]
5

一个更好的方法是不要依赖其他模块中的全局变量,而是直接把名字传递给 file2.action() 这个函数:

file1.py

import file2

username = "steven"

file2.action(username)

file2.py

def action(name):
    print name 

撰写回答