另一个给我带来问题的简单问题。
假设我有以下内容:
#!/usr/bin/python
ref = 30
def f(x):
print x + ref
f(50)
到目前为止,方便我的目的的一个方面是(我猜) ref 被函数 f 视为全局变量,因此不需要被指定为 f 的参数。
但是,当我想将 f 存储在一个单独的模块中时,我会遇到问题,例如 myfunctions :
#!/usr/bin/python
import myfunctions
ref = 30
myfunctions.f(50)
其中 myfunctions 包含 f 的定义,如上所述。尝试运行时,我得到的NameError是“未定义全局名称'ref'。”
我猜这是因为主模块和'myfunctions'模块有不同的全局命名空间,但有一个很好的方法围绕这个 - 不必包含 ref 作为参数˚F
答案 0 :(得分:2)
正如您所发现的那样,全局变量不能像那样工作 - 它们也不应该。以下是您可以做的一些事情,但不应该这样做。
myfunctions.py
ref = 30
def f(x):
print x + ref
our_caller.py
import myfunctions
myfunctions.f(10) # prints 40
myfunctions.ref = 50
myfunctions.f(10) # prints 60
但那么some_other_caller.py呢?
import myfunctions
myfunctions.f(20) # prints 50? prints 70?
这取决于你何时使用myfunctions模块中的全局变量搞砸了。
此外,作为一个思想实验,假设您上面发布的代码确实按预期工作(在某些语言中会有效)。在some_other_caller导入导入myfunctions的our_caller的情况下会发生什么。那么使用哪个参考?它可能更复杂,some_other_caller可以在our_caller中调用一个函数,而函数又调用myfunctions.f - 所以我们使用from_caller中的ref?所以如果some_other_caller直接调用myfunctions,行为可能会有所不同吗?
这不是一个任何人都想住的世界。
更好的方法更像是:
myfunctions.py
def f(x, ref=30):
print x + ref
our_caller.py
import myfunctions
myfunctions.f(10) # prints 40
myfunctions.f(10, ref=50) # prints 60
然后人们可以看到发生了什么 - 没有奇怪的状态在变化。全球国家真的最好避免。你会一次又一次地听到。在你自己的危险中忽略这个建议(以及后来必须支持你的代码的任何可怜的灵魂)。
编辑:除了您上面关于您的用例的评论之外,看到以下模式的情况并不罕见。
REF = 30
ref_count = 0
def f(x, ref=REF, other_thing=None):
if not other_thing:
other_thing = ref_count
print x + ref + other_thing
def add_ref(current_count=None):
global ref_count
if current_count is not None:
ref_count = current_count
ref_count += 1
您可以保留全局变量(REF更像是一个全局常量)。当您从外部调用f时,您可以选择为它们提供值或允许它们作为默认值。此外,您可以调用add_ref,为其提供一个新值,以用于模块中的全局副本。
同样,同样的规则适用 - 您已经为模块添加了可以由外部模块实现的全局状态。你需要非常小心谁在改变它,一个更好的架构会试图在第一时间避免这种情况。