gpt4 book ai didi

python - 具有相同参数的函数的全局变量与参数

转载 作者:行者123 更新时间:2023-11-28 21:56:36 25 4
gpt4 key购买 nike

我正在阅读“Making games with Python&Pygame”,我注意到,由于作者使用了很多函数来分解代码,所以他使用了很多全局变量,如GRIDSIZEBACKGROUNDCOLOR。我总是被告知全局函数通常是不好的,但是没有它们,每个绘图函数都会有10个重复的参数——而且我也被告知重复是不好的。那么,我想知道,对于大多数(绘图)函数中出现的参数,作者使用globals是正确的,还是应该使用更多的重复参数。

最佳答案

Globals通常是不好的,因为在大型程序中很难跟踪值。这在Python中有点不那么糟糕,因为“global”变量是模块级的,但即使在这种情况下,也建议您避免使用它们:您的模块可能变得很大(使全局变量难以跟踪),模块级变量容易被其他模块更新等。
我不是说你不应该使用它们-你应该在需要的时候使用它们。需要共享状态和常量是两种常见的情况。
用于共享状态的模块级变量
例如,模块级变量是存储通过所有模块甚至整个程序共享的状态的最佳方式。假设我们要实现一个游戏的渲染器;它应该存储所有程序共享的所有图像的地图。所以在我们的模块中,我们可以这样做:

# map_renderer.py

_map = [
[None, None, None, None],
[None, None, None, None],
[None, None, None, None],
[None, None, None, None]
]

def put_sprint(sprint, x, y):
_map[x][y] = sprint

def get_sprint(x, y):
return _map[x][y]

现在您甚至可以编写这样的模块:
# background.py
import map_renderer as mr

def draw_background(background_images):
for i, row in enumerate(background_images):
for j, image in enumerate(row):
put_sprint(image, i, j)

…在另一个模块中做类似的事情
# npc.py
import map_renderer as mr

def draw_npc(npc, x, y):
image = npc.image
put_sprint(image, x, y)

由于两个模块应该更新相同的映射,因此可以使用模块级变量来完成它。
注意:对于那些更面向设计模式的,我们可以说模块级变量是实现单例的非常有效和简单的方法。
模块级变量作为常量
然而,您书中的代码是使用模块级变量的另一种好方法的示例:常量。(我认为这些全局变量实际上是常量,因为它们遵循 PEP 8中常量的样式)
例如,考虑 BACKGROUNDCOLOR变量。我想它是一个值,在整个模块中,也许在整个程序中都是一样的。假设这个值是 0xFA2BEE。然后你有一些选择:
你可以(理论上)在任何地方写下它的值:
def paint_frame(image, x, y, h, w, fx, fy):
paint_background(0xFA2BEE, fx, fy)
spring = slice_image(image, x, y, x+w, y+h)
paint(image, px, py)

def clear_frame(fx, fy):
paint_background(0xFA2BEE, fx, fy)

不过,这显然是个坏主意。首先,frick是什么?任何读过你的代码的人——甚至你将来——都会被它搞糊涂。另外,如果背景应该改成,让我们说, 0xFA2BEE,会怎么样?现在您必须在代码中找到所有 0xB2BAA3,确保它是背景值,而不是相同的其他值,然后替换它。不是很好,对吧?
如果这不好,你可以想:好吧,既然我应该避免“全局”变量,但原始值不好用,我可以把它们作为参数传递!
def paint_frame(image, x, y, h, w, fx, fy, background):
paint_background(background, fx, fy)
spring = slice_image(image, x, y, x+w, y+h)
paint(image, px, py)

def clear_frame(fx, fy, background):
paint_background(background, fx, fy)

好吧,至少现在你 0xFA2BEE作为 0xFA2BEE/ paint_frame的最后一个参数是背景值。但是,您在一些已经很复杂的函数中添加了另一个参数。此外,如果更改背景,则必须在整个代码库中找到所有对 clear_frame/ paint_frame的调用。不酷,兄弟。
相反,你可以。。。
…创建常量!事实上,正是作者所做的:
BACKGROUND = 0xFA2BEE

def paint_frame(image, x, y, h, w, fx, fy):
paint_background(BACKGROUND, fx, fy)
spring = slice_image(image, x, y, x+w, y+h)
paint(image, px, py)

def clear_frame(fx, fy):
paint_background(BACKGROUND, fx, fy)

现在,您1)不需要猜测 clear_frame是背景值还是其他值,2)您的函数保持简单,3)您可以轻松地只在一个位置更改背景值。如您所见,模块级变量的使用在这里得到了很好的回报。即使您需要在大多数地方(而不是所有地方)使用相同的背景值,常量也会有帮助:只需将其设置为 0xFA2BEE参数的默认值:
BACKGROUND = 0xFA2BEE

def paint_frame(image, x, y, h, w, fx, fy, background=BACKGROUND):
paint_background(background, fx, fy)
spring = slice_image(image, x, y, x+w, y+h)
paint(image, px, py)

def clear_frame(fx, fy, background=BACKGROUND):
paint_background(background, fx, fy)

现在您调用,让我们说大部分时间 background只在需要时传递一个后台参数
常量也适合作为全局变量/模块级变量,因为它们不会改变。全局变量特别讨厌,因为您应该跟踪它们的值。但是,如果值不变,这就不是问题了,对吧?
注意:这些变量按惯例是常量,可以更新。Python没有只读变量,但是您可以遵循代码标准来避免问题。)
唯一普遍的规则是“视情况而定”
你会发现很多人说“不要用X”,“不要用Y”,“总是用Z”等等。好吧,大多数时候这些建议都是正确的,但你可能总是会发现上下文不适用。“不使用全局”规则就是这样。在某些情况下,使用global是最佳选择。即使在C语言中也有这样的情况,Python还有很多其他的情况可以做到,因为模块级变量仍然比全局变量更安全。
避免全局变量(或模块级变量)的建议是一个很好的建议,特别是对于新手。然而,正如你所看到的,有些情况下最好不要遵循它。

关于python - 具有相同参数的函数的全局变量与参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21054775/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com