是否有一种简单的方法可以使函数中的所有变量全局化?
我在一个函数中有20个奇怪的变量,并且逐个命名它们并不是很好的代码......无论如何......)
答案 0 :(得分:46)
在正常的日常编程过程中,没有正当理由做以下事情。请查看此问题的其他答案,以获得更实际的替代方案。
我几乎无法想象你为什么要这样做,但这是一种方法:
def f(a, b, c):
d = 123
e = 'crazy, but possible'
globals().update(locals())
def g():
print a, b, c, d ,e
>>> globals()
{'g': <function g at 0x875230>, 'f': <function f at 0x8751b8>, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, '__name__': '__main__', '__doc__': None}
>>> g()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in g
NameError: global name 'a' is not defined
>>> f(10, 20, 'blah')
>>> g()
10 20 blah 123 crazy, but possible
>>> globals()
{'a': 10, 'c': 'blah', 'b': 20, 'e': 'crazy, but possible', 'd': 123, 'g': <function g at 0x875230>, 'f': <function f at 0x8751b8>, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, '__name__': '__main__', '__doc__': None}
答案 1 :(得分:15)
没有办法将它们全部声明为全局,而你真的不想这样做。这20个变量可能应该变成一个具有20个属性的对象。
答案 2 :(得分:12)
执行此操作的pythonic方法是将变量保持在局部范围内(即在每个函数中定义它们)并将它们作为参数/返回值在函数之间传递;或者将变量保存为在该类中创建“函数”方法的对象或类的属性。无论哪种方式都可以,但global
关键字专门设计用于让您以您描述的方式使用它。全局变量不仅仅是“坏的风格”,而且它们使代码很难维护,因为需要在每个函数中检查变量需要遵守的任何不变量。
以下是良好风格(带功能)的示例:
def quads(a, b, c):
x1 = (-1.0 * b + math.sqrt(b * b - 4.0 * a * c)) / (2.0 * a)
x2 = (-1.0 * b - math.sqrt(b * b - 4.0 * a * c)) / (2.0 * a)
return x1, x2
def pretty(a, b, c, x1, x2):
eqn = "%fx^2 + %fx + %c" % (a, b, c)
print "The first solution to the equation %s is: %f" % (eqn, x1)
print "The second solution to the equation %s is: %f" % (eqn, x2)
return
def main():
a = 100
b = 200
c = 300
x1, x2 = quads(a, b, c)
pretty(a, b, c, x1, x2)
return
if __name__ == '__main__':
main()
这是一个好样式的例子(使用OOP):
class Quadratic(object):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
self.x1 = None
self.x2 = None
self.solve() # Set x1 and x2 to correct values
# To maintain the invariant between a, b, c and x1, x1
# we should override __setattr__ or use descriptors or
# properties so that self.solve() is called every time
# a, b, or c are updated.
return
def solve(self):
self.x1 = (-1.0 * self.b +
math.sqrt(self.b * self.b - 4.0 * self.a * self.c)) / (2.0 * self.a)
self.x2 = (-1.0 * self.b -
math.sqrt(self.b * self.b - 4.0 * self.a * self.c)) / 2.0 * self.a
return
def pretty(self):
eqn = "%fx^2 + %fx + %c" % (self.a, self.b, self.c)
print "The first solution to the equation %s is: %f" % (eqn, self.x1)
print "The second solution to the equation %s is: %f" % (eqn, self.x2)
return
def main():
quad = Quadratic(100, 200, 300)
quad.pretty()
return
if __name__ == '__main__':
main()
答案 3 :(得分:4)
最简单的解决方案是只有一个全局 - 或者更好的是,弄清楚如何将其传递给函数。将它作为全局使用看起来像这样(再次,我展示了最简单的可能情况,不一定是Python的最佳用法):
class Info(object): # or whatever you want to name the container
"""Holder for global information."""
info = Info() # single instance we will use
def my_function():
print "Here is some info:"
print info.a, info.b, info.c
info.a = 3
info.b = 8
info.c = []
if __name__ == '__main__':
my_function()
同样,我可能会将info
传递给函数。但由于你的问题是关于全球性的,所以它在这里显示为全球性的。
答案 4 :(得分:0)
我想做的一个小众例子:使用函数进行导入。*
def temp():
a = "stays local value"
old_locs = locals().copy()
b = "is global value"
import math
new_locs = locals()
new_vars = {k: new_locs[k] for k in set(new_locs) - set(old_locs)
if k != 'old_locs'}
globals().update(new_vars)
temp()
print(b)
print(math.sqrt(3))
print(a)
给予
is global value
1.7320508075688772
NameError: name 'a' is not defined
这样,只有特定的 20 个左右的变量会更新全局命名空间,而函数中的中间变量名称不会。
*我需要从 .ipynb 文件导入,这样做的过程取决于是从 google Collaboratory、桌面 .ipynb 还是桌面 .py 文件调用;这涉及使用魔法,在不会调用这些分支的情况下,这些魔法被视为无效语法,因此通过导入我的导入函数,我可以避免这个问题。