为何无法为pygame.Surface对象添加新属性?
问题:为什么Pygame Surface对象无法动态添加属性?
当创建普通Python对象时,可为其分配__init__()方法中未定义的属性:
class Test: pass test = Test() test.Something = 0
但使用Pygame的Surface对象时却无法实现,代码如下:
import pygame pygame.init() screen = pygame.display.set_mode() print(type(screen)) red = (255, 0, 0) blue = (0, 0, 255) screen.turn = 0 while True: if (screen.turn): screen.fill(blue) else: screen.fill(red) screen.turn = 1 - screen.turn pygame.event.pump() pygame.display.update()
运行后抛出AttributeError异常,输出如下:
pygame 2.1.2 (SDL 2.0.18, Python 3.9.13) Hello from the pygame community. https://www.pygame.org/contribute.html Traceback (most recent call last): File "/Users/armaho/Programs/Python/main.py", line 10, in <module> screen.turn = 0 AttributeError: 'pygame.Surface' object has no attribute 'turn' <class 'pygame.Surface'>
解答
核心原因在于两类对象的实现机制不同:
- 你自定义的
Test类是纯Python实现的类,这类类默认会给每个实例分配__dict__属性,专门用于存储实例的动态属性,因此可以随意添加未预先定义的属性。 - 而
pygame.Surface是C扩展实现的类(属于Python的扩展类型),这类类出于性能优化或设计规范的考虑,默认不会为实例提供__dict__,自然无法动态添加新属性。只有当扩展类开发者特意在类定义中启用__dict__支持,或者实现了__setattr__方法时,才能动态添加属性。
解决思路很简单:不要试图给Surface对象附加状态,单独用变量管理你的自定义状态即可,修改后的代码示例:
import pygame pygame.init() screen = pygame.display.set_mode() print(type(screen)) red = (255, 0, 0) blue = (0, 0, 255) turn = 0 # 单独用变量管理状态 while True: if turn: screen.fill(blue) else: screen.fill(red) turn = 1 - turn pygame.event.pump() pygame.display.update()
内容的提问来源于stack exchange,提问作者Armaho
相关产品推荐
相关产品推荐

