找回密码
 立即注册
搜索
热搜: 活动 交友
查看: 223|回复: 6

求助!关于 python global 关键字的困惑

[复制链接]

1

主题

3

回帖

51

积分

提示词程序员

积分
51
发表于 4-18-2025 12:43:42 | 显示全部楼层 |阅读模式
本帖最后由 void 于 4-18-2025 12:45 编辑

我最近在研究和更新 ppball 游戏程序代码,我想统计小球的碰撞次数,但却遇到了个困惑。
首先我在代码文件开头声明了一个 collide_times 的变量,然后在 CLS_ball 的 collide 方法增加了 collide_times += 1 的语句,结果却报了错。

class CLS_ball(object):
    ...

    def collide(self, pad):
        global gameStatus
        global server
        if gameStatus == 1:
            return
        if self.spdX < 0:
            distance = abs(pad.x + pad.w - self.x)
        else:
            distance = abs(self.x + self.w - pad.x)
        if distance <= ACCURACY:
            if pad.y <= self.y + self.h // 2 <= pad.y + pad.h:
                self.spdX *= -1
                self.spdY += pad.spdY * pad.friction
                soundPong4.play()
            elif pad.type == 0:
                gameStatus = 1
                if self.spdX < 0:  # paddleR win
                    if server == paddleR:
                        paddleR.score += 1
                        server = paddleL  # switch server
                        RT_show_txt(screen, "server: paddleL", font64, SCREEN_W // 2, SCREEN_H // 2.5, (0, 0, 255))
                        print("server= R")
                if self.spdX > 0:
                    if server == paddleL:
                        paddleL.score += 1
                        server = paddleR  # switch server
                        RT_show_txt(screen, "server: paddleR", font64, SCREEN_W // 2, SCREEN_H // 2.5, (0, 0, 255))
                        print("server= L")
        collide_times += 1


    ...
    collide_times += 1
    ^^^^^^^^^^^^^
UnboundLocalError: cannot access local variable 'collide_times' where it is not associated with a value
解决方法我猜应该是加个 global collide_times 就行,结果也确实如此。
但这个时候我就困惑了,因为我依稀记得有时候,函数内部在调用全局变量的时候并不需要带上 global 关键字,而这里却要带上,为此我就很不清楚什么时候要 global 而什么时候不要。

var = 0x1bf52
def test():
    print(var)

test()

我自己尝试了下,就比如这种代码就可以,感觉好复杂... 求解答


7

主题

8

回帖

290

积分

版主

积分
290
发表于 4-18-2025 16:20:06 | 显示全部楼层
本帖最后由 littleblackLB 于 4-18-2025 16:21 编辑

Python 在函数内部对变量的访问,遵循 Local → Enclosing → Global → Built‑in (简称 LEGB)顺序进行名称解析。
  • 读取全局变量:如果函数中仅有对变量的读取操作,不进行赋值,则该变量会被解释为全局变量,直接从全局作用域取值。
  • 赋值操作:只要在函数内部出现对某个名字的赋值,Python 就会将其视为局部变量。如果此时再去读取同名全局变量,就会因“局部变量尚未绑定”而报 UnboundLocalError。

  1. collide_times = 0
  2. class CLS_ball(object):
  3.     def collide(self, pad):
  4.         # ...
  5.         collide_times += 1</font>
复制代码

由于函数体中出现了 collide_times += 1(相当于 collide_times = collide_times + 1),Python 将 collide_times 视为局部变量。而在计算右侧表达式时,又试图读取同名全局变量,却因局部变量还未被赋值而导致错误。
因此,
无需 global的情况是当函数内部只“读取”全局变量,不含任何赋值语句;
必须 global的情况是当函数内部“写入”或“增量赋值”全局变量时,必须在最开始声明。

2

主题

17

回帖

199

积分

中级程序员

积分
199
发表于 4-18-2025 17:53:16 | 显示全部楼层
import pygame, sys, random
SCREEN_W, SCREEN_H = 1024, 600
BORDER_W = 10
ACCURACY = 2 #add in V1.0
G = 0.01 #重力加速度 add in V1.1
SPEED_Y_MAX = 3 #add in V1.1


上面是中A ppball的代码,我想知道,程序开始这些大写定义的变量,函数里要使用的话,需要global说明吗?
为什么需要?又为什么不需要?
我看老师给的代码里没有用global,函数里就是直接用

2

主题

17

回帖

199

积分

中级程序员

积分
199
发表于 4-18-2025 17:55:22 | 显示全部楼层
littleblackLB 发表于 4-18-2025 16:20
Python 在函数内部对变量的访问,遵循 Local → Enclosing → Global → Built‑in (简称 LEGB)顺序进行 ...

还有,DL上面贴代码是怎么贴的,还有行号呢,我搞不出.......好厉害的样子......

1

主题

3

回帖

51

积分

提示词程序员

积分
51
 楼主| 发表于 4-18-2025 23:06:24 | 显示全部楼层
littleblackLB 发表于 4-18-2025 16:20
Python 在函数内部对变量的访问,遵循 Local → Enclosing → Global → Built‑in (简称 LEGB)顺序进行 ...

谢谢回复,受教了!

1

主题

3

回帖

51

积分

提示词程序员

积分
51
 楼主| 发表于 4-18-2025 23:11:34 | 显示全部楼层
本帖最后由 void 于 4-18-2025 23:22 编辑
tiger 发表于 4-18-2025 17:53
import pygame, sys, random
SCREEN_W, SCREEN_H = 1024, 600
BORDER_W = 10

根据版主的回复的话,我的理解是对于这些大写定义不变的常量,在函数中被使用的时候不需要写 global 语句(当然也可以写),因为只有当函数内部“写入”或“增量赋值”全局变量时,才需要 global 语句,这也达到了常量不可变的效果。如果只需要读取全局变量的值,就不用写global,python会自己往 Local → Enclosing → Global → Built‑in 逐级寻找。
同时,在这种情况下,如果有这类语句 G=9.8 实际不会影响到全局变量。

7

主题

8

回帖

290

积分

版主

积分
290
发表于 4-19-2025 12:44:05 | 显示全部楼层
本帖最后由 littleblackLB 于 4-19-2025 12:45 编辑
tiger 发表于 4-18-2025 17:55
还有,DL上面贴代码是怎么贴的,还有行号呢,我搞不出.......好厉害的样子...... ...


点开这个把代码粘贴到里面就可以了~ 代码行号只有在最终呈现的时候才有。

本帖子中包含更多资源

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

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

本版积分规则

Archiver|手机版|小黑屋|RealDevClub ( 沪ICP备2024093864号-1 )

GMT+8, 5-10-2025 23:49 , Processed in 0.064858 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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