具有相同参数的函数的全局变量与参数 [英] Globals vs Parameters for Functions with the Same Parameters

查看:40
本文介绍了具有相同参数的函数的全局变量与参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读使用 Python 和 Pygame 制作游戏",我注意到由于作者使用了大量绘图函数来分解他的代码,因此他使用了许多全局变量,例如 GRIDSIZE 或 <代码>背景色.我总是被告知全局变量通常很糟糕,但如果没有它们,每个绘图函数都会有十多个重复参数——而且我也被告知重复是糟糕的.那么,我想知道作者对大多数(绘图)函数中出现的参数使用全局变量是否正确,或者应该使用更多重复参数.

I am reading through "Making games with Python & Pygame" and I have noticed that because the author uses lots of functions with drawing in to break his code up, he uses lots of globals such as GRIDSIZE or BACKGROUNDCOLOR. I was always told that globals were generally bad, but without them, every drawing function would have ten more, repeating parameters - and I have also been told that repetition is bad. I wondered, then, is the author is correct in using globals for parameters that appear in most (drawing) functions, or should have just used more, repetitive parameters.

推荐答案

全局变量通常很糟糕,因为在大型程序中很难跟踪值.这在 Python 中不那么糟糕,因为全局"变量是模块级的,但即使在这种情况下,你也最好避免它们:你的模块可能变得很大(使全局变量难以跟踪),模块级变量是容易被其他模块等更新

Globals are generally bad because it is difficult to keep track of the values in a huge program. This is a bit less bad in Python because "global" variables are module-level, but even in this case you are well advised to avoid them: your modules can became huge (making global variables hard to track), module-level variables are prone to be updated by other modules etc.

我并不是说你不应该使用它们 - 你应该在需要它们时使用它们.需要它的两种常见情况是共享状态常量.

I don't mean you should not use them - you should use them when they are needed. Two common cases when it is needed are sharing state and constants.

例如,模块级变量是存储通过所有模块甚至整个程序共享的状态的最佳方式.假设我们要实现一个游戏的渲染器;它应该存储所有程序共享的所有图像的映射.所以在我们的模块中,我们可以做这样的事情:

For example, module-level variables are the best way of storing a state shared through all the module, or even through all the program. Let's suppose we are going to implement the renderer of a game; it should store a map of all images that is shared by all the program. So at our module we can do something like this:

# 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]

现在你甚至可以编写这样的模块:

Now you can even write a module like this:

# 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)

...然后在另一个模块中做这样的事情

...and in another module do something like this

# npc.py
import map_renderer as mr

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

因为两个模块都应该更新同一个地图,所以你可以使用模块级变量来完成它.

Since both modules should update the same map, you can use module-level variables to accomplish it.

注意:对于那些更面向设计模式的人,我们可以说模块级变量是实现单例的一种非常有效且简单的方法.

NOTE: For those more design pattern-oriented, we can say that module-level variables are a very effective and simple way of implementing singletons.

然而,您书中的代码是使用模块级变量的另一种好方法的示例:常量.(我想这些全局变量实际上是常量,因为它们遵循 PEP 8.)

The code in your book, however, are examples of another good way of using module level variables: constants. (I suppose these global variables are actually constants, because they follow the style for constants from PEP 8.)

BACKGROUNDCOLOR 变量为例.我想这是一个在所有模块中都相同的值,也许在所有程序中.假设这个值是0xFA2BEE.然后你有一些选择:

Consider, for example, the BACKGROUNDCOLOR variable. I suppose it is a value that will be the same through all the module, maybe through all the program. Suppose this value is 0xFA2BEE. Then you have some options:

  • 你可以(理论上)在任何使用它的地方写下这个值:

  • you could (in theory), write the value everywhere it is used:

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)

然而,这显然是个坏主意.首先,0xFA2BEE 是什么鬼?任何阅读你的代码的人——即使是你未来的人——都会被它弄糊涂.另外,如果背景应该更改为,让我们说,0xB2BAA3?现在你必须在你的代码中找到所有 0xFA2BEE确保它是背景的值而不是相同的其他值然后替换它.不太好,对吧?

That, however, is clearly a bad idea. First, what the frick is 0xFA2BEE? Anyone reading your code - even you in the future - will get confused by it. Also, what if the background should be changed to, let us say, 0xB2BAA3? Now you have to find all 0xFA2BEE in your code, make sure it is the value of the background instead of same other value and then replace it. Not nice, right?

如果这不好,你可以想:好吧,既然我应该避免使用全局"变量,但原始值不好用,我可以将它们作为参数传递!

If that is bad, you can think: well, since I should avoid "global" variables but the raw values are not good to use, I can pass them as parameters!

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 作为 paint_frame/clear_frame 的最后一个参数是背景的值.但是,您在一些已经很复杂的函数中添加了另一个参数.此外,如果您更改背景,则必须在整个代码库中找到对 paint_frame/clear_frame 的所有调用.不酷,兄弟.

Well, at least now you 0xFA2BEE as the last argument of paint_frame/clear_frame is the value of the background. However, you put another argument in some already complicated functions. Also, if you change the background, you already have to find all calls to paint_frame/clear_frame in your entire codebase. Not cool, bro.

相反,你可以...

...创建常量!其实作者是这么干的:

...create constants! In fact, it is what the author does:

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) 无需猜测 0xFA2BEE 是背景值还是其他值,2) 您的函数保持更简单,3) 您可以轻松地一次更改背景值只有地方.如您所见,模块级变量的使用在这里得到了很好的回报.即使您需要在大多数并非所有的地方使用相同的背景值,该常量也会有所帮助:只需将其设为background<的默认值/code> 参数:

Now, you 1) don't need to guess if 0xFA2BEE is a background value or something else, 2) your functions are kept simpler and 3) you can easily change the background value at one place only. As you can see, the use of module-level variables payed well here. Even if you need to use the same background value in most but not all places, the constant will be helpful: just make it the default value of the background parameter:

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)

现在你调用,让我们说 paint_frame(img, i, j, FRAME_SIZE, FRAME_SIZE, k*FRAME_SIZE, l*FRAME_SIZE) 大部分时间并且只在需要时传递背景参数

Now you call, let us say paint_frame(img, i, j, FRAME_SIZE, FRAME_SIZE, k*FRAME_SIZE, l*FRAME_SIZE) most of the time and only passes a background argument when needed

常量适合作为全局变量/模块级变量,因为它们不会改变.全局变量特别讨厌,因为您应该跟踪它们的值.但是,如果值不发生变化,这将不是问题,对吗?

Constants are suitable to be global variables/module-level variables also because they do not change. Global variables are specially nasty because you should keep track of their values. If the values does not change, however, this will not be a problem, right?

注意:这些变量按照惯例是常量,可以更新.Python 没有只读变量,但你可以按照代码标准避免问题.)

NOTE: these variables are constants by convention and can be updated. Python has no kind of read-only variable but you can avoid problems by following the code standard.)

你会发现很多人说不要使用 X"、不要使用 Y"、总是使用 Z"等等.好吧,大多数时候这些建议是正确的,但你可能永远找到它们不适用的上下文.不使用全局变量"规则就是这种情况.在某些情况下,使用 global 是最佳选择.即使在 C 中也有这样的情况,而 Python 有许多其他情况可以做到,因为模块级变量仍然比全局变量更安全.

You will find a lot of people saying "don't use X", "don't do Y", "always use Z" etc. Well, most of the time these suggestions are correct, but you probably will always find contexts where they do not apply. This is the case with the "do not use globals" rule. There are situations where the use of global is the best choice. Even in C there are such cases, and Python have many other situations where you can do it since module-level variables are still safer than globals.

避免全局变量(或模块级变量)的建议很好,特别适合新手.但是,如您所见,有些情况下最好不要遵循.

The suggestion of avoiding globals (or module-level variables) is a good one, specially for a novice. However, as you can see, there are cases where it is better to not follow it.

这篇关于具有相同参数的函数的全局变量与参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆