为了账号安全,请及时绑定邮箱和手机立即绑定

Python-在函数外部创建的对象是否可以在内部完全访问?

Python-在函数外部创建的对象是否可以在内部完全访问?

海绵宝宝撒 2021-04-08 14:15:59
我在理解变量范围时遇到一些问题。对于普通变量,我理解这一点,但是如果我定义一个对象,那么事情会使我感到困惑。请看下面的代码:class test():    passtext="hi there"num=1p=test()p.var="good bye"p.arr = []p.num = 5def 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 ", numdef 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 ", numdef 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.arrfor i in range(5):    change()print p.arr这给了我这个输出:before change: object text  good byebefore change: object number  5before change: basic text  hi therebefore change: basic num  1after change: object text  good nightafter change: object number  10after change: basic text  hi thereafter change: basic num  1['sleep well']['sleep well', 'sleep well', 'sleep well', 'sleep well', 'sleep well', 'sleep well']默认情况下,来自类测试的对象似乎是全局的。这是正确的吗 ?
查看完整描述

3 回答

?
慕码人2483693

TA贡献1860条经验 获得超9个赞

这就是闭包的工作方式。定义函数时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))

您可以看到num和text的引用已更改。


查看完整回答
反对 回复 2021-04-27
?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

简短答案:在函数外部或全局范围内声明的任何变量(意味着该变量不在任何类型的范围内,例如类,方法,条件语句等)都称为全局变量。


长调试的答案:


实际上,您的对象被声明为全局对象。


p=test()

p.var="good bye"

p.arr = []

p.num = 5

在上面的代码片段中,该p对象在方法范围之外进行了声明,从而允许所有对象都可以访问它。方法也在test类范围之外声明。实际上,没有什么阻止他们访问它。如果要更好地理解调试,请将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

并重新运行您的代码,将产生:


before change: object text  good bye

before change: object number  5

before change: basic text  hi there

before change: basic num  1

然后出现以下错误:


追溯(最近一次呼叫最近):change()中的文件“ t.py”,第35行,更改中的文件“ t.py”,第29行,p.num = 10 NameError:未定义全局名称“ p”


但是,如果要从模块或方法内部访问对象,则可以使用关键字global,并且如文档所建议的那样:


这是因为当您对作用域中的变量进行赋值时,该变量将成为该作用域的局部变量,并在外部作用域中隐藏任何类似命名的变量。由于foo中的最后一条语句为x分配了一个新值,因此编译器将其识别为局部变量。因此,当较早的打印x尝试打印未初始化的局部变量并导致错误时,可以通过将其声明为全局变量来访问外部作用域变量


查看完整回答
反对 回复 2021-04-27
?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

就像Python中的其他任何变量一样。该函数首先在本地名称空间中检查变量。由于未在函数内部定义对象,因此它将检查外部命名空间,即您实际定义其的全局命名空间。


对于变量num /文本,您使用num = 5在change()。这将创建一个名为的局部变量,num并为其分配5。它不会更改全局变量。如果要全局更改它,则可以使用global关键字:


def change():

    global text,num

    num = 5  #Global num is changed


查看完整回答
反对 回复 2021-04-27
  • 3 回答
  • 0 关注
  • 231 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信