2017-07-07 114 views
-1

我有以下程序和问题变量(字典)是player_info存储玩家信息(名称和目标)。为了解决目前出现的错误,我只需要将player_info设置为全局变量,但是我想知道是否stackoverflow专家可以建议或讨论解决此问题的替代方法的可能性不使用全局变量。具体示例:是否可以避免使用全局变量?

代码

#FOOTBALL COACH app 

#The program allows a user to enter a number of players (their names and goals scored) and then search for a player, returning their average goals for the three matches 


import sys 
def main(): 
mainmenu() 

def mainmenu(): 

    print("=====WELCOME to the MAIN MENU=============") 
    print(""" 
    1..........Add New Players & Goals 
    2..........Search by Players 
    3..........Quit 

    ========================================= 
    """) 

    choice=int(input("Enter choice:")) 
    if choice==1: 
    addplayers() 
    elif choice==2: 
    searchplayer(player_info) 
    elif choice==3: 
    sys.exit() 
    else: 
    print("You must make a valid choice - 1, 2 or 3") 


def addplayers(): 


    player_info= {} #create a dictionary that stores the player name: player goals 

    num_players = int(input("Please enter number of players you wish to enter:")) 
    print ("You are entering %s players" %num_players) 
    player_data = ['Match 1 goals : ', 'Match 2 goals : ', 'Match 3 goals : '] 
    for i in range(0,num_players): 
     player_name = input("Enter Player Name :") 
     player_info[player_name] = {} 
     for entry in player_data: 
      player_info[player_name][entry] = int(input(entry)) #storing the marks entered as integers to perform arithmetic operations later on. 


    mainmenu() 


def searchplayer(): 
    print("===============SEARCH by player: Calculate average goals==================") 
    name = input("Player name : ") 
    if name in player_info.keys(): 
    #print student_info 
     print ("Average player goals : ", str(sum(player_info[name].values())/3.0)) 
    else: 
     print("Please enter a valid player name:") 

main() 

如前所述,我知道,在addplayer()子重写,这将解决这个问题:

global player_info 
player_info = {} #create a dictionary that stores the player name: player goals 

...我期待找出解决问题的方法,而不使用全局变量。

更新:

一个答案下面使用回报player_info就是我想一起去的,但它并不相当,但工作。另外,每次添加播放器时,我都需要返回主菜单,不太确定如何操作,而且每次都没有mainmenu调用。有什么建议么? https://repl.it/JRl5/1

+0

['return'](https://docs.python.org/3/reference/simple_stmts.html#grammar-token-return_stmt)字典 – DavidG

回答

2

您可以在函数中使用return以避免使用全局变量。一个简单的例子如下所示:

def addplayers(): 

    player_info= {} 

    name = input("Enter Name: ") 
    test = int(input("Enter a number: ")) 

    player_info[name] = test 

    return player_info 


player_info = addplayers() 

然后,如果您想使用这个在其他功能你只需在字典作为参数传递给函数:

def searchplayers(player_info): 

    print (player_info) 

注:一个有趣的答案在 “Why are global variables evil?

编辑:

addplayers()打电话mainmenu()其本身是是在mainmenu()内拨打电话。这是一个递归函数,除非有很好的理由,否则最好避免这些。我会将mainmenu的内容放入while循环中,直到满足某些条件。完整的代码如下所示(我已删除了main功能,因为它并没有真正做任何事情):

def mainmenu(): 

    stop = False 

    while stop == False: 

     print("=====WELCOME to the MAIN MENU=============") 
     print(""" 
     1..........Add New Players & Goals 
     2..........Search by Players 
     3..........Quit 

     ========================================= 
     """) 

     choice=int(input("Enter choice:")) 
     if choice==1: 
      player_info = addplayers() 
     elif choice==2: 
      searchplayer(player_info) 
     elif choice==3: 
      print ("Exit the main menu") 
      stop = True 
     else: 
      print("You must make a valid choice - 1, 2 or 3") 


def addplayers(): 


    player_info= {} #create a dictionary that stores the player name: player goals 

    num_players = int(input("Please enter number of players you wish to enter:")) 
    print ("You are entering %s players" %num_players) 
    player_data = ['Match 1 goals : ', 'Match 2 goals : ', 'Match 3 goals : '] 

    for i in range(0,num_players): 
     player_name = input("Enter Player Name :") 
     player_info[player_name] = {} 

     for entry in player_data: 
      player_info[player_name][entry] = int(input(entry)) #storing the marks entered as integers to perform arithmetic operations later on. 

    return player_info 


def searchplayer(player_info): 
    print("===============SEARCH by player: Calculate average goals==================") 
    name = input("Player name : ") 
    if name in player_info.keys(): 
     #print student_info 
     print ("Average player goals : ", str(sum(player_info[name].values())/3.0)) 
    else: 
     print("Please enter a valid player name:") 


mainmenu() 
+0

谢谢 - 作为一个有效的学习问题,我不确定为什么这个问题是downvoted !!!!! :( – MissComputing

+0

我没有downvote,但在你的问题中有相当多的代码,你可以用一小段代码来代码,它可以重现你所遇到的问题,而不是发布所有的代码 – DavidG

+0

我可以问一下player_info = addplayers()是做什么的吗? – MissComputing

0

商店的一切,与游戏相关的数据结构中,例如字典,并一起传递,它在所有可以根据需要更新的功能中。写一个函数“newgame”来创建这个结构并初始化它。

从某种意义上说,这是面向对象的编程,不需要对类和对象使用Python的语法。也许,你会在课程/教程中稍后学习。

0

首先,总是可以避免使用全局变量。其次,全局变量在Python中可能是用词不当的; global将变量存储在本地全局变量中,通常是本地模块。这避免了像C这样的问题语言中的很大一部分与全局性问题相碰撞, Python每个模块都有一个名称空间。对于只有一个上下文的简单脚本,这可能很好。

您可能会使用的另一个命名空间是使用某个类的特定对象的名称空间。这可能是这样的:

class Game: 
    def mainmenu(self,...): 
     self.addplayers() 
    def addplayers(self): 
     self.player_info = {} 

有了诸如此类的代码,谁就实例Game可以使多个实例,使用时,每经过为self。这在很大程度上是语法糖为可变状态通过的类似的形式:

def mainmenu(): 
    state={} 
    addplayers(state) 
def addplayers(state): 
    state['player_info'] = {} 

对于某些形式的编程的,不可变的状态是远优选(特别是,多线程,其中数据是共享的,或来记录,其中你可以撤消步骤)。这同样做到,但你为每个调用一个新的状态:

def mainmenu(): 
    state = {} 
    state = addplayers(state) 
def addplayers(oldstate): 
    newstate = oldstate.copy() 
    newstate['player_info'] = {} 
    return newstate 

Python是不是专为这一点,并没有真正有一个模式,让你无意中修改可变类型。某些类型可以转换为类似的类型,这些类型是不可变的,如frozensettuple

我们可以做的一件怪事就是用一组不同的全局变量来调用一个Python函数。这可以被滥用来把你的现有功能,global报表和所有的,并让他们使用不同的变量:

fakeglobals = mainmenu.__globals__.copy() 
exec(addplayers.__code__, fakeglobals) 

你原来的代码有来电来回功能之间,虽然,而且每个都将重置其每个__globals__属性的全局变量。

你的代码还实现了一个使用尾递归的循环。这在Python中并未优化,最终会耗尽堆栈空间。在对尾递归进行优化的语言中,您可以连续传递状态作为参数,无需返回它。