Python-在函数外部创建的对象在函数内部完全可访问?
我在理解变量范围时遇到一些问题。对于普通变量,我理解它,但如果我定义了一个对象,我会感到困惑。请查看此代码:Python-在函数外部创建的对象在函数内部完全可访问?,python,Python,我在理解变量范围时遇到一些问题。对于普通变量,我理解它,但如果我定义了一个对象,我会感到困惑。请查看此代码: 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
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']
默认情况下,类测试中的对象似乎是全局的。是这样吗
谢谢,
安迪简短回答: 在函数外部或全局范围内声明的任何变量(表示该变量不在任何类型的范围内,例如类、方法、条件语句等)称为全局变量 长时间调试的答案: 实际上,您的对象被声明为全局对象
p=test()
p.var="good bye"
p.arr = []
p.num = 5
在上面的代码片段中,p
对象声明在方法的范围之外,这允许所有方法都访问它。方法也在测试
类范围之外声明。实际上,没有任何东西阻止他们访问它。如果希望调试更好地理解,请将p
对象移动到其中一个方法中,如:
然后重新运行代码,这将产生:
before change: object text good bye
before change: object number 5
before change: basic text hi there
before change: basic num 1
然后出现以下错误:
回溯(最近一次调用last):文件“t.py”,第35行,在
change()文件“t.py”,第29行,在change中
p、 num=10 name错误:未定义全局名称“p”
但是,如果您想从模块或方法内部访问对象,可以使用关键字global
,如文档所建议的:
这是因为当您对作用域中的变量进行赋值时,该变量将成为该作用域的局部变量,并在外部作用域中隐藏任何类似命名的变量。由于foo中的最后一条语句为x赋值,编译器将其识别为局部变量。因此,当较早的print x尝试打印未初始化的局部变量并导致错误时,您可以通过声明外部作用域变量为全局变量来访问它
闭包就是这样工作的。当您在之后定义函数
output\u时,它会将变量text=“hi there”
置于该函数的变量范围内。这个变量只能在函数内部更改
但如果您想拥有全局变量,则需要使用global
construction:
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\u时,我们复制所有当前上下文(对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))
您可以看到num和text的引用已更改。这与Python中的任何其他变量一样。函数首先在本地名称空间中检查变量。由于对象不是在函数内部定义的,因此它会检查外部名称空间,即您实际定义它的全局名称空间
对于变量num/text,在change()
中使用num=5
。这将创建一个名为num
的局部变量,并为其赋值5。它不会更改全局变量。如果要全局更改,则可以使用全局关键字:
def change():
global text,num
num = 5 #Global num is changed
只需将对象p想象为任何其他基本类型。两者的规则是一样的
由于您在函数之外声明了对象,因此此对象的范围不受限制。另一方面,如果在一个函数上声明它,则无法访问这些函数之外的对象,因为此对象的作用域现在仅限于此函数。(当然,你可以明确地将其全球化。但这可能超出了这个问题目前的范围)
上述代码将失败,因为p在change()和output_after()中不是未知的。因此对象p以及变量text和num都在外部声明。为什么访问my object p时没有全局关键字,但变量必须有全局关键字?您的变量也可以访问。通过在任何方法中打印文本或num
变量进行调试。感谢您的帮助。我的目标是理解这里的范围。我在外部声明了对象p和变量text和num。为什么访问我的对象p时没有全局关键字,但变量必须有全局关键字?因为p是可变对象,文本和num是不可变的。@xsanders我添加了更多说明。@OleksandrYarushevskyi为什么文本和num是不可变的?@RohithS98 CPython的实现
def change():
global text,num
num = 5 #Global num is changed
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()