我写了一个看起来像这样的测试程序:
#!/usr/bin/python
def incrementc():
c = c + 1
def main():
c = 5
incrementc()
main()
print c
我认为,因为我在main的主体内调用了incrementc,所以main中的所有变量都会传递给incrementc。但是当我运行这个程序时,我得到了
Traceback (most recent call last):
File "test.py", line 10, in <module>
main()
File "test.py", line 8, in main
incrementc()
File "test.py", line 4, in incrementc
c = c + 1
UnboundLocalError: local variable 'c' referenced before assignment
为什么c不通过?如果我想让一个变量被多个函数引用,我是否必须全局声明它?我在某处看到全局变量很糟糕。
谢谢!
答案 0 :(得分:6)
你在考虑dynamic scoping。动态范围的问题是incrementc
的行为将取决于先前的函数调用,这使得很难推断代码。相反,大多数编程语言(也使用Python)使用静态作用域:c
仅在main
内可见。
要完成您想要的任务,您可以使用全局变量,或者更好地传递c
作为参数。现在,因为Python中的原语是不可变的,所以传递一个整数是不能改变的(它实际上是通过值传递的),因此你必须将它打包到一个容器中,就像列表一样。像这样:
def increment(l):
l[0] = l[0] + 1
def main():
c = [5]
increment(c)
print c[0]
main()
或者,甚至更简单:
def increment(l):
return l + 1
def main():
c = 5
print increment(c)
main()
通常,全局变量很糟糕,因为它们使得编写难以理解的代码变得非常容易。如果你只有这两个函数,你可以继续使c
全局化,因为代码的作用仍然很明显。如果你有更多的代码,最好将变量作为参数传递;通过这种方式,您可以更轻松地查看谁依赖于全局变量。
答案 1 :(得分:3)
当一个变量被赋值给一个作用域时,Python认为它是整个作用域的本地变量,除非你另有说明。
因此,为了让您按照自己的想法行事,您需要使用两个global
语句:
#!/usr/bin/python
def incrementc():
global c
c = c + 1
def main():
global c
c = 5
incrementc()
main()
print c
否则,你在谈论两种情况下名为c
的局部变量。
解决此问题的正常方法是,不涉及global
。
#!/usr/bin/python
def incrementc(c):
c = c + 1
return c
def main():
c = 5
c = incrementc(c)
return c
c = main()
print c
此处,在每个函数和全局范围中,c
引用不同的变量,您将其作为参数传递并返回值。如果您想只有一个c
,请使用类:
class Foo:
def __init__(self, c):
self.c = c
self.incrementc()
def incrementc(self):
self.c = self.c + 1
foo = Foo(5)
print foo.c
答案 2 :(得分:2)
变量c未通过,因为您没有将对c的任何引用传递给函数incrementc。
您在这里看到的是3个范围,全局范围以及函数main和incrementc中的范围。在main中你已经正确定义了一个变量c,但是增量c不知道这个 - 所以尝试增加它会失败。即使这两个函数成功,尝试打印c也会在全局范围内失败,因为它不知道你在main中定义的c。
您有几个选择。一种方法:
def incrementc(c):
c = c + 1
return c
def main():
c = 5
c = incrementc(c)
return c
c = main()
print c
注意c是如何被传递的。当然,名称不必保留,你很可能这样写:
def increment(z):
z = z + 1
return z
def main():
bar = 5
bar = increment(bar)
return bar
foo = main()
print foo
许多人可能不喜欢的另一个选择(有充分理由)是使用全局变量。在那种情况下:
def incrementc():
global c # indicate intention to write to this global, not just read it
c = c + 1
def main():
global c # declares c in global space
c = 5
incrementc()
main()
print c
您希望修改c的GLOBAL实例的任何函数,您需要通知该函数。所以你说'全球c'。您可以在不执行此操作的情况下从全局读取。如果您决定在函数的本地空间中使用一个值,这将确保(在某种程度上)您不会出错并用类似的名称无意中覆盖全局空间中的值。
希望这很清楚,但随时可以要求澄清任何一点(如果我错误地描述了这一点,我也愿意纠正。)
答案 3 :(得分:-1)
全局变量很糟糕。
就像朋友和敌人一样。让你的朋友保持亲密,但让你的爱人更近。
函数main最后一个局部变量c,赋值为5 然后调用函数inc..C。 main中的c现在已超出范围,因此您尝试使用不在范围内的c值 - 因此出错。