鱼C论坛

 找回密码
 立即注册
查看: 1932|回复: 5

[已解决]只是多了一个print语句,咋就报错了呢?

[复制链接]
发表于 2023-6-25 21:48:04 | 显示全部楼层 |阅读模式

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

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

x
代码1:
>>> x = 880
>>> def myfunc():
        x = 520
        print(x)

        
>>> myfunc()
520

代码2:
>>> def myfunc():
        print(x)
        x = 520
        print(x)

        
>>> myfunc()
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    myfunc()
  File "<pyshell#12>", line 2, in myfunc
    print(x)
UnboundLocalError: local variable 'x' referenced before assignment

代码2 相比 代码1 ,只是多了一个print(x)语句, 咋就报错了呢? 感觉是变量作用域的问题,但是不知道错在哪里了, 请老师指点。
最佳答案
2023-6-26 14:19:25
wbzxz 发表于 2023-6-26 14:16
非常感谢您的指点。
您看我能不能这样理解,其实这个问题的关键时由于我使用了赋值语句,所以造成python ...

你的理解是正确的!在函数中,只要我们对一个变量进行赋值操作,无论这个赋值操作在哪里,Python 都会认为这个变量是局部的,除非你明确地用  global  或  nonlocal  声明它。如果在赋值之前就试图访问这个变量,就会遇到  UnboundLocalError  错误。

这是因为在编译函数的时候,Python 会决定变量是全局的还是局部的。在函数体中,任何在赋值语句( = )左侧的变量,都会被认为是局部变量,除非明确地声明为全局变量或非局部变量。

对于你的第二个问题,其实不仅仅是赋值语句会引起这个问题,任何试图修改一个变量的操作都会让 Python 将这个变量视为局部的,如果没有明确声明它是全局的。例如:
x = 880

def myfunc():
    x += 1    # This is effectively an assignment operation
    print(x)

myfunc()

这段代码也会抛出  UnboundLocalError  错误,因为  x += 1  本质上是  x = x + 1 ,是一种赋值操作。Python 认为  x  是局部的,但是在赋值之前已经引用了  x ,导致错误。

所以总的来说,只要在函数内部修改变量的值,如果不想让 Python 将其视为局部变量,就需要使用  global  或  nonlocal  关键字明确声明。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-6-25 22:14:40 | 显示全部楼层
这个错误确实是因为变量作用域的问题。

在 Python 中,当你在函数内部对一个变量进行赋值操作的时候,这个变量会被 Python 解释器认为是一个局部变量,除非你明确地声明它是全局的。这就是为什么在你的第二个例子中,当你试图在赋值之前打印变量 x 的时候,Python 会抛出一个错误。因为在这个时间点,x 还没有在局部作用域内定义。

你的代码1中,函数 myfunc() 内部有个局部变量x,与全局变量x是完全不同的两个变量。所以在函数内部先给x赋值520,然后打印x,结果自然是520。

但在代码2中,函数内部的print(x)在x=520之前,也就是在局部变量x被定义之前就要求打印x,所以就会报错。

如果你想在函数内部使用全局变量x,你需要使用 global 关键字,如下所示:
x = 880

def myfunc():
    global x
    print(x)
    x = 520
    print(x)

myfunc()
在这个例子中, global x 告诉 Python:在这个函数内,我想要使用全局的 x,而不是创建一个新的局部变量 x。所以函数首先会打印出全局变量x的值880,然后将全局变量x赋值为520,并打印出520。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2023-6-26 06:07:37 | 显示全部楼层
isdkz 发表于 2023-6-25 22:14
这个错误确实是因为变量作用域的问题。

在 Python 中,当你在函数内部对一个变量进行赋值操作的时候,这 ...

谢谢您,但是我还没有理解透彻。

您的意思是不是说,出错的原因,是局部变量x没有定义就要求打印,所以才报错。但是为什么下面的代码不会出错呢?(代码中变量x没有被定义,也是直接打印x)
>>> x = 880
>>> def myfunc():
        print(x)

        
>>> myfunc()
880

谢谢您,请多指点。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-26 08:49:09 | 显示全部楼层
wbzxz 发表于 2023-6-26 06:07
谢谢您,但是我还没有理解透彻。

您的意思是不是说,出错的原因,是局部变量x没有定义就要求打印,所 ...


当你在一个函数内部引用一个变量,Python 会按照以下顺序来查找这个变量:

1. 首先,它会在当前函数的局部作用域内查找。
2. 如果在局部作用域内找不到,它会在任何封闭的作用域内查找,从内到外。封闭的作用域可能是在一个外部函数或者是一个类定义的范围内。
3. 如果在封闭的作用域内也找不到,Python 会在全局作用域内查找。
4. 最后,如果在全局作用域内也找不到,Python 会在内建的作用域内查找。

在你给出的新代码示例中,你只是引用了变量  x  而没有尝试在  myfunc  的局部作用域内对其进行赋值。因此,Python 会按照上述规则查找变量  x ,它先在局部作用域查找,找不到后在全局作用域找到了  x ,因此  print(x)  可以正确打印出  x  的值。

然而,在你的第二个代码示例中,你尝试在  myfunc  的局部作用域内对  x  进行赋值。这导致 Python 将  x  视为一个局部变量,而不再去全局作用域查找。然后,当你在赋值之前尝试打印  x  时,由于  x  在此时还未被定义,因此 Python 抛出了  UnboundLocalError  错误。

我希望这个解释可以帮助你更好地理解 Python 的作用域规则!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-26 14:16:38 | 显示全部楼层
isdkz 发表于 2023-6-26 08:49
当你在一个函数内部引用一个变量,Python 会按照以下顺序来查找这个变量:

1. 首先,它会在当前函数 ...

非常感谢您的指点。
您看我能不能这样理解,其实这个问题的关键时由于我使用了赋值语句,所以造成python以为 myfunc 函数中x变量一定是局部变量,不会按照LEGB规则进行查找啦。而在x变量赋值之前,使用了print(x)语句,python就认为没有复制就引用啦,所以出现错误啦。

而在代码一中,虽然也使用了赋值语句,python也认为函数内部的x变量是局部变量。由于没有在赋值前访问x变量,而是先给变量赋了值,这样就不会出错啦。

您看我这样理解对不,但我的描述肯定不准确,除了赋值语句会引起这个问题, 还有什么语句会引起类似错误呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-26 14:19:25 | 显示全部楼层    本楼为最佳答案   
wbzxz 发表于 2023-6-26 14:16
非常感谢您的指点。
您看我能不能这样理解,其实这个问题的关键时由于我使用了赋值语句,所以造成python ...

你的理解是正确的!在函数中,只要我们对一个变量进行赋值操作,无论这个赋值操作在哪里,Python 都会认为这个变量是局部的,除非你明确地用  global  或  nonlocal  声明它。如果在赋值之前就试图访问这个变量,就会遇到  UnboundLocalError  错误。

这是因为在编译函数的时候,Python 会决定变量是全局的还是局部的。在函数体中,任何在赋值语句( = )左侧的变量,都会被认为是局部变量,除非明确地声明为全局变量或非局部变量。

对于你的第二个问题,其实不仅仅是赋值语句会引起这个问题,任何试图修改一个变量的操作都会让 Python 将这个变量视为局部的,如果没有明确声明它是全局的。例如:
x = 880

def myfunc():
    x += 1    # This is effectively an assignment operation
    print(x)

myfunc()

这段代码也会抛出  UnboundLocalError  错误,因为  x += 1  本质上是  x = x + 1 ,是一种赋值操作。Python 认为  x  是局部的,但是在赋值之前已经引用了  x ,导致错误。

所以总的来说,只要在函数内部修改变量的值,如果不想让 Python 将其视为局部变量,就需要使用  global  或  nonlocal  关键字明确声明。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-9-22 17:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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