鱼C论坛

 找回密码
 立即注册
查看: 1185|回复: 10

关于局部变量的作用域问题

[复制链接]
发表于 2022-3-12 19:42:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
def outside():
    var = 5
    def inside():
        print(var)
        var = 3      #但是令人非常不解的是,把这句话删了,就不会报错,就可以访问外部变量了,输出值是5

    inside()

outside()

这个会报错 说我没有定义var

我的困惑是 print(var)比var = 3率先执行,此时为什么不能去访问外部变量呢,打印5,而是报错呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-3-12 19:44:51 | 显示全部楼层
哎,你在打印 var 变量时,它以为是要打印外层的那个 var,
可你在后面又定义了 var ,就屏蔽了它, 上面那条语句自然也就不知到该输出哪个 var 了!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-12 19:46:30 | 显示全部楼层
因为你在函数里面对这个变量赋值的话,它就把这个变量当成了局部变量,

所以在这个变量定义之前使用就会报错了,你如果希望不把它当成局部变量的话,就加个 nonlocal 声明
def outside():
    var = 5
    def inside():
        nonlocal var
        print(var)
        var = 3      

    inside()

outside()

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-3-12 19:55:46 | 显示全部楼层
python爱好者. 发表于 2022-3-12 19:44
哎,你在打印 var 变量时,它以为是要打印外层的那个 var,
可你在后面又定义了 var ,就屏蔽了它, 上面 ...

但是var是在print后面定义的 print不应该先执行吗 所以我的理解是print执行的时候不知道我后面定义了var?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-12 19:59:43 | 显示全部楼层
看你的代码出错的地方应该是var=3这一句,出错的原因是修改局部变量的值。默认情况下Python不允许在函数内修改全局变量的值,函数内定义的子函数也不允许修改外部函数的局部变量。print(var)这一句是可以运行的,因为它只是访问了局部变量var的值而没有修改它,但是var=3这一句就是在修改局部变量var的值了,这种行为违反了语法所以报错。

你可以这样修改inside这个函数
def inside():
    nonlocal var
    print(var)
    var = 3

所以概括来说就是如果不用global或者nonlocal关键字声明,则只能在函数内访问全局变量或局部变量的值,但是不能修改它们的值。

更多例子:
# 全局变量
var = 'hello'

# 访问但不修改
def access_global():
    print(var)

# 错误修改全局变量
de wrong_modify_global():
    var = 10  # 报错
    print(var)

# 正确修改全局变量
def right_modify_global():
    global var  # 声明var为全局变量,不是局部变量
    var = 10
    print(var)

# 访问局部变量
def access_local():
    var = 233
    def inside():
        print(var)  # 只访问但不修改
    inside()

# 正确修改局部变量
def right_modify_local():
    var = 233
    def inside():
        nonlocal var  # 声明var为局部变量
        var = 666
        print(var)
    inside()
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-12 20:05:56 | 显示全部楼层
Jerry~Mouse 发表于 2022-3-12 19:55
但是var是在print后面定义的 print不应该先执行吗 所以我的理解是print执行的时候不知道我后面定义了var ...


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-3-12 22:22:47 | 显示全部楼层

啊?既然改变变量的操作在后面执行 那就不应该报错啊 我执行print的时候 var = 3 这条语句还没有开始执行 所以应该打印5 为啥报错呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-3-12 22:23:38 | 显示全部楼层
isdkz 发表于 2022-3-12 19:46
因为你在函数里面对这个变量赋值的话,它就把这个变量当成了局部变量,

所以在这个变量定义之前使用就会 ...

改变变量的操作在后面执行 那就不应该报错啊 我执行print(var)的时候 var = 3 这条语句还没有开始执行 所以应该采用外部变量 打印5 但是为啥报错呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-13 00:57:58 | 显示全部楼层
Jerry~Mouse 发表于 2022-3-12 22:23
改变变量的操作在后面执行 那就不应该报错啊 我执行print(var)的时候 var = 3 这条语句还没有开始执行  ...


因为变量要讲"自由"啊,哈哈  

当你 将var=3,写在print(var)之后,var就不再是"自由变量",就无法"向外找/向上找"了。  

当然即使你将var=3写在print(var)之前,它也不是"自由变量",而是"本地变量/局部变量"。
总之,你可以看做赋值等号=,是一种约束,一旦你进行了赋值,它就失去了"自由",就无法再"向上找"了。

^_
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-3-13 13:07:13 | 显示全部楼层
阿奇_o 发表于 2022-3-13 00:57
因为变量要讲"自由"啊,哈哈  

当你 将var=3,写在print(var)之后,var就不再是"自由变量",就无法" ...

那在print的时候 还没有执行到var = 3 这条语句 所以print那条语句中的var应该还是自由的?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-3-13 15:56:39 | 显示全部楼层
本帖最后由 阿奇_o 于 2022-3-13 15:57 编辑
Jerry~Mouse 发表于 2022-3-13 13:07
那在print的时候 还没有执行到var = 3 这条语句 所以print那条语句中的var应该还是自由的?


这里的"自由",不是从表面的语句执行顺序来考虑的,而是从它能否"向外找"来判断。
"自由变量"这个概念不完全是你想的那样。具体定义你自己搜吧。 反正,语法规则它不允许你这样操作。

你可以多查查资料,再试试不同的情况,应该可以理解。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-6 16:29

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表