python - 我在 Pygame 中创建了一个 Toggle Box 类,但它没有修改我作为参数传递给它的原始布尔值
问题描述
我正在开发一个简单的 Pygame 项目,在选项菜单中,我有几个用于关闭声音和动画的切换框。这些的布尔变量存储在单独的设置类中。
虽然这不是真的必要,但我想我会尝试制作一个 ToggleButton 类,它采用以下参数:
ToggleButton(game_instance, boolean, text, xpos, ypos, width, height)
我给了它一个draw()方法和一个toggle()方法。我想从我的主游戏程序中传递我的self.settings.sounds_on或self.settings.animations_on布尔值,以便打开和关闭切换框将打开和关闭声音和动画。
在对此进行测试时,我创建了 ToggleButton 类的两个实例:
ToggleButton(self, self.game_instance, self.settings.sounds_on, "Sounds", 50, 100, 25, 25)
ToggleButton(self, self.game_instance, self.settings.animations_on, "Animations", 50, 150, 25, 25)
切换框绘制屏幕,并且可以与之交互。
然而,虽然toggle()方法改变了类实例中的布尔值,但它似乎并没有连接到作为参数传递给实例的原始布尔值(我希望我使用的是这里的术语正确,我还在学习)。因此,虽然切换框的外观会根据布尔值是 True 还是 False 而发生变化,但它实际上对声音和动画的设置根本没有任何影响。
这是按钮代码的链接,也是一个简短的示例程序,它只在屏幕上绘制一个切换框,每次单击它时,它都会打印原始布尔值的状态,以及实例内的布尔值。您可以清楚地看到原始布尔值始终为 False,而切换框的self.boolean参数发生了变化。
https://github.com/ElJuanito82/ToggleBox/blob/main/example
因此,似乎在实例化按钮时,它会获取当前状态下的布尔值的副本,而不是创建直接链接,以便在一个更改时另一个更改。我在这里有正确的想法吗?
我在这里缺少什么可以使它起作用的东西吗?
解决方案
布尔参数是按值传递的,不能以这种方式修改它。最好的解释可能是这个问答集 -如何通过引用传递变量?. 相当多的“教程”在细节上是不正确的,甚至说“一切都是通过引用传递的”——这是错误的。通常基本类型是按值传递的——布尔值、数字、元组、字符串。对象和列表之类的大多数其他内容都是通过引用传递的——这意味着可以在函数中更改这些内容。
考虑这个 python 会话:
Python 3.8.5 (default, Jul 28 2020, 12:59:40)
>>> x = True
>>> def f( boolval ):
... boolval = False
...
>>> f(x)
>>> x
True # <-- Still the original value
x
不会更改,因为它是作为值传递的。现在考虑同样的事情,但使用列表参数:
>>> y = [ 'apple', 'banana', 'cherry' ]
>>> def f2( fruit_list ):
... fruit_list.append( 'durian' )
...
>>> f2( y )
>>> y
['apple', 'banana', 'cherry', 'durian'] # <-- Changed!
这里传递了一个列表作为引用,因此可以在函数中对其进行修改。如果您打算像这样进行编码,重要的是要知道哪些类型是可变的,哪些不是。
因此,对于您的ToggleButton
,显然现在我们知道布尔参数是不可变的,因此不会被更改。但是您可以并且确实更改对象内部的值。所以添加辅助函数来设置和查询它。
这是在面向对象的 GUI 控件中实现此类功能的常用方法,而不是直接询问成员变量。
例如:
class ToggleButton:
def __init__(self, game_instance, boolean, text, xpos, ypos, width, height):
"""Initialise the toggle box attributes."""
self.game_instance = game_instance
self.boolean = boolean
# [...]
def isToggled( self ):
""" Return True if the toggle is selected """
return self.boolean
def setToggled( self, value ):
""" Set the state of the Toggle """
self.boolean = value
### TODO: cause a re-draw, iff necessary
撇开:boolean
不是一个变量的好名字,因为它不是描述性的。类似 , 或 的东西.is_set
可能.checked
会.selected
更好,因为它描述了内容所代表的内容。
推荐阅读
- r - 使用 azuremlsdk 的 azure 机器学习 Web 服务的分数/条目文件
- java - 填充瞬态字段休眠
- python - 使用相同的代理抓取下一页
- pandas - 合并相似组上的两个数据框
- ruby-on-rails - Stimulus Rails 与 Ajax 调用有关的问题
- amazon-web-services - 从 API Gateway (HTTP API) 的 lambda 授权方获取自定义响应
- reactjs - 在 React Typescript 中创建上下文时出错
- perl - 在 perl dancer2 MVC 框架中将 html 文件作为路由传递
- javascript - 检查 Js 中未定义的变量
- dart - Dart 中是否有类似属性观察者的东西?