关于何时应该在函数中使用全局变量的经验法则

Ann*_*Zen 3 python function global-variables turtle-graphics python-turtle

当我用函数编码游戏时,我经常对全局变量的哪个变量感到困惑。

我听说全球化变量不是一种很好的做法,所以我尝试通过不全球化任何变量来最小化数量,并且只全球化错误消息告诉我的变量。但是这样做很烦人,而且浪费时间。

有人能告诉我什么时候应该在函数中全局变量的经验法则,

什么时候不需要?

这是我的意思的示例(功能):

import turtle
from random import randint as rd
from time import sleep
delay = 0.1

wn = turtle.Screen()
wn.setup(400,400)
wn.tracer(0)

player = turtle.Turtle('square')
player.penup()
player.goto(0,-170)

rock = turtle.Turtle('circle')
rock.shapesize(0.5,0.5)
rock.penup()
rock.goto(rd(-190,190),200)

rocks = [rock]

pen = turtle.Turtle(visible=False)
pen.penup()
pen.goto(0,150)

def go_left(): # No globalizing here
    if player.xcor() >= -170:
        player.setx(player.xcor()-10)

def go_right(): # No globalizing here
    if player.xcor() <= 170:
        player.setx(player.xcor()+10)

def move_rocks(): # No globalizing here
    for rock in rocks:
        rock.sety(rock.ycor()-rd(0,2))

def loop_rocks():
    global count # rocks not globalized here
    for rock in rocks:
        if rock.ycor() < -200:
            count += 1
            rock.goto(rd(-190,190),200)

def add_rocks():
    global count # rocks not globalized here
    if count == len(rocks) and len(rocks) <= 15:
        rock = turtle.Turtle('circle')
        rock.shapesize(0.5,0.5)
        rock.penup()
        rock.goto(rd(-190,190),200)
        rocks.append(rock)
        count = 0

def write_score():
    global time,score,high_score # pen not globalized here
    time += 1
    if time == 500:
        score += 1
        time = 0
    if score > high_score:
        high_score = score

    pen.clear()
    pen.write(f'Score: {score}   High Score: {high_score}',align='center',font=('Arial',10,'bold'))

def hit(): # No globalizing here
    for rock in rocks:
        if player.distance(rock) < 15:
            return True

def die():
    global score,rocks # player not globalized here
    sleep(1)
    for rock in rocks:
        rock.goto(300,300)
    rocks = rocks[:1]
    rocks[0].goto(rd(-190,190),200)
    player.goto(0,-170)
    score = 0

wn.listen()
wn.onkeypress(go_left,'Left')
wn.onkeypress(go_right,'Right')

score = 0
high_score = 0
count = 0
time = 0

while True:
    if hit():
        die()
    move_rocks()
    loop_rocks()
    add_rocks()
    write_score()
    wn.update()
Run Code Online (Sandbox Code Playgroud)

cdl*_*ane 7

样式规则不是语言规则。即你不应该使用eval(),但它在语言中。

告诉我什么时候应该在函数中全局变量的经验法则,什么时候不需要?

何时使用和何时不使用的规则global很简单,但即使是网络上的教程也会出错。

  1. global关键字应用于创建全局变量。

(是的,这部分是样式规则。)当您在函数外定义顶级变量时,Python 会将其设为全局变量。(您global为此使用关键字。)当您分配给函数内的变量时,Python 假定它是函数的局部变量。只有global当您想更改后面的假设时才需要关键字,以便您可以从函数内重新分配 (=) 全局变量。您不需要global声明来检查全局变量。您不需要它来调用可能会更改其内部状态或内容的全局变量上的方法:

  1. global当您想在函数内重新分配 (=) 全局变量时才需要关键字。

global声明用于任何重新分配全局变量的函数。它位于对变量、访问或赋值的第一次引用之前。为了简单和风格,全局语句放在函数的开头。

像“你永远不应该使用全局变量”这样的声明是一种风格规则,并且适用于大多数编程语言——如果/在可以的时候应用它。如果您绝对不能,请不要为此感到难过,只需:

  1. 注释您正确使用的所有全局变量。

全局常量不是问题:

  1. 如果全局常量确实是常量,则它们永远不需要global 关键字。

@juanpa.arrivillaga 将附加值go_left()作为参数而不是全局变量的示例没有考虑到这go_left()是一个回调,并且乌龟事件分配函数不提供附加参数。(他们应该,但他们没有。)我们可以使用lambda表达式(或partial来自functools 的函数)来解决这个问题,但是当以这种方式使用时,lambda也不是特别好的风格,恕我直言。

@martineau 的“使它们成为类的方法可以访问的类的属性”(又名类变量)的建议很好,但没有说的是这意味着子类化Turtle 或用另一个类包装海龟实例。

我个人对可变全局变量的问题是它们在多线程世界中是有问题的。