class test():
pass
text="hi there"
num=1
p=test()
p.var="good bye"
p.arr = []
p.num = 5
def output_before():
print "before change: object text " ,p.var
print "before change: object number ", p.num
print "before change: basic text " ,text
print "before change: basic num ", num
def output_after():
print "after change: object text " ,p.var
print "after change: object number ", p.num
print "after change: basic text " ,text
print "after change: basic num ", num
def change():
text = "whats up"
num=5
p.num=10
p.var="good night"
p.arr.append ("sleep well")
output_before()
change()
output_after()
print p.arr
for i in range(5):
change()
print p.arr
哪个给我这个输出:
before change: object text good bye
before change: object number 5
before change: basic text hi there
before change: basic num 1
after change: object text good night
after change: object number 10
after change: basic text hi there
after change: basic num 1
['sleep well']
['sleep well', 'sleep well', 'sleep well', 'sleep well', 'sleep well', 'sleep well']
默认情况下,来自类测试的对象似乎是全局的。是这样吗?
谢谢, 安迪
答案 0 :(得分:1)
简短答案: 在函数外部或全局范围内声明的任何变量(意味着该变量不在任何范围内,例如类,方法,条件语句等)都称为全局变量。
长期调试的答案:
实际上,您的对象被声明为全局对象。
logging.get_logger()
在上面的代码段中,<uses-feature android:name="android.hardware.camera" />
对象在方法范围之外声明,从而使所有对象都可以访问它。方法也声明在p=test()
p.var="good bye"
p.arr = []
p.num = 5
类范围之外。实际上,没有什么阻止他们访问它。如果您想调试以便更好地理解,请将p
对象移至其中一种方法中,例如:
test
然后重新运行您的代码,它将产生:
p
然后出现以下错误:
回溯(最近一次通话最后一次):文件“ t.py”,第35行,在 change()文件“ t.py”,第29行,处于更改中 p.num = 10 NameError:未定义全局名称'p'
但是,如果要从模块或方法内部访问对象,则可以使用关键字def output_before():
p=test()
p.var="good bye"
p.arr = []
p.num = 5
print "before change: object text " ,p.var
print "before change: object number ", p.num
print "before change: basic text " ,text
print "before change: basic num ", num
,并按照文档建议:
这是因为当您对作用域中的变量进行赋值时,该变量将成为该作用域的局部变量,并在外部作用域中隐藏任何类似命名的变量。由于foo中的最后一条语句为x分配了一个新值,因此编译器将其识别为局部变量。因此,当较早的print x尝试打印未初始化的局部变量并导致错误时,您可以通过声明全局变量来访问外部作用域变量
答案 1 :(得分:1)
这是闭包的工作方式。定义函数output_after
时,它将在此函数的变量范围内使用变量text="hi there"
。而且只能在函数内部更改此变量。
但是,如果要使用全局变量,则需要使用global
构造:
def output_after():
global text, num
print "after change: object text " ,p.var
print "after change: object number ", p.num
print "after change: basic text " ,text
print "after change: basic num ", num
众所周知,Python中的所有变量名称都被称为对值的引用。因此,当我们定义函数output_after
时,我们将复制所有当前上下文(对text,num,p对象的引用)。您可以使用id
函数检查对对象的引用。
当您更改文本和num的值时,引用将被更改,但对于对象p将会相同。
请检查以下内容:
def change():
print(id(text))
text = "whats up"
print(id(text))
print(id(num))
num=5
print(id(text))
print(id(p))
p.num=10
print(id(p))
您可以看到引用的数字和文本已更改。
答案 2 :(得分:0)
这与Python中的其他任何变量一样。该函数首先在本地名称空间中检查变量。由于未在函数内部定义对象,因此它将检查外部命名空间,即您实际定义其的全局命名空间。
对于变量num / text,您正在num = 5
中使用change()
。这将创建一个名为num
的局部变量,并为其分配5。它不会更改全局变量。如果要全局更改,则可以使用global关键字:
def change():
global text,num
num = 5 #Global num is changed
答案 3 :(得分:0)
只需将您的对象p视为其他任何原始类型。两者的规则相同。
由于在函数之外声明了对象,因此该对象的范围不受限制。另一方面,如果在函数中声明它,则您将无法访问这些函数之外的对象,因为此对象的范围现在仅限于此函数。 (当然,您可以明确地将此设置为全局。但是,此问题目前可能超出范围)
class test():
pass
text="hi there"
num=1
def output_before():
#p is now local
p=test()
p.var="good bye"
p.arr = []
p.num = 5
print("before change: object text " ,p.var)
print("before change: object number ", p.num)
print("before change: basic text " ,text)
print("before change: basic num ", num)
print(b)
def output_after():
print("after change: object text " ,p.var) #should fail because p is not known
print("after change: object number ", p.num)
print("after change: basic text " ,text)
print("after change: basic num ", num)
def change():
text = "whats up"
num=5
p.num=10
p.var="good night"
p.arr.append ("sleep well")
output_before()
change()
output_after()
上面的代码将失败,因为在change()和output_after()中p是未知的。