Python函数间全局变量访问异常:已赋值变量未被识别
问题分析与解决方案
首先,咱们来拆解你遇到的问题:你在room17函数里碰到的"变量未赋值引用"错误,核心原因是Python对全局变量和局部变量的处理规则,再加上代码里几个容易忽略的细节:
1. 为什么combat在room17里报错?
当你在room17里写combat = combat + 1时,Python会默认把combat当成这个函数的局部变量。那在这行之前的combat17 = combat * fight17就会出错——因为局部变量combat还没被赋值,就被拿来计算了。
同样的问题也出现在stealth、health这些变量上:
stealth根本没在全局初始化,也没在chose_class里声明为global,所以即使你在选职业时赋值了,其他函数也看不到它。health在chose_class里是局部变量,全局根本没有这个变量,room17里直接用肯定会报错。
2. 快速修复:正确使用global声明
要解决这个问题,你需要在room17里也声明所有要访问/修改的全局变量,同时补全chose_class里的stealth全局声明,还要初始化全局的health:
import random import time # 初始化所有全局属性,包括之前遗漏的stealth和health combat = 0 strength = 0 agility = 0 magic = 0 intelligence = 0 stealth = 0 health = 0 def chose_class(): # 一次性声明所有需要修改的全局变量 global strength, combat, agility, magic, intelligence, stealth, health health = 10 print("Chose your class:") print("Warrior: 1") print("Wizard: 2") print("Philosopher: 3") print("Thief: 4") print("Help: 5") dog1 = int(input(":")) if dog1 ==1: strength = 7 combat = 7 agility = 5 stealth = 3 magic = 1 intelligence = 1 elif dog1 == 2: strength = 3 combat = 1 agility = 3 stealth = 3 magic = 8 intelligence = 6 elif dog1 == 3: strength = 3 combat = 1 agility = 3 stealth = 3 magic = 2 intelligence = 8 elif dog1 == 4: strength = 2 combat = 4 agility = 6 stealth = 8 magic = 1 intelligence = 6 elif dog1 == 5: print("Warrior Dog:") print(" Warrior Dogs possess great strength and combat ability") print(" they have medium agility, but low stealth, magic and") print(" intelligence.") print("\n"*2) print("Wizard Dog:") print(" Wizard Dogs have low strength, combat, and agility,") print(" they have medium stealth and high magic capabilities.") print("\n"*2) print("Philosopher Dog:") print(" Philosopher Dogs are highly intelligent, while they") print(" have low strength, they have medium combat ability.") print(" Their agility, stealth, and magic start low but can") print(" rapidly improve by finding hidden objects on quests.") print("\n"*2) print("Thief Dogs") print(" Thief Dogs have high agility and stealth, as well as") print(" average intelligence and combat. They have low combat,") print(" magic, and strength.") # 打印帮助后重新调用选择,避免用户选5后直接退出导致变量未赋值 chose_class() else: print("Invalid choice, please try again!") chose_class() def room17(): # 声明要使用/修改的全局变量 global combat, stealth, health print("**Description**") print("Do you want to fight the cat guard or sneak past it?") print("Fight: 1") print("Sneak Past: 2") choice17 = input(":") # 直接判断字符串是否为"1"或"2"更简单直观 if choice17 == "1": fight17 = random.randint(0,5) combat17 = combat * fight17 if combat17 <= 20: print("You were successful") combat = combat + 1 else: print("You lost the fight and had to retreat") health = health - 1 # 假设room1是其他房间函数,这里先注释避免报错,你可以自己补全 # room1() elif choice17 == "2": sneak17 = random.randint(0,5) stealth17 = sneak17 * stealth if stealth17 <= 20: print("You snuck past the guard") stealth = stealth + 1 else: print("The guard caught you, he attacks and you have to retreat") health = health - 2 stealth = stealth - 1 # room1() else: print("Invalid choice, please pick 1 or 2!") room17() chose_class() print("Combat:", combat) room17()
3. 更优方案:用类封装玩家属性
全局变量虽然能解决当前问题,但在游戏开发里很容易出问题(比如变量被意外修改、代码难以维护)。作为自学的话,正好可以学习用类来管理玩家状态,这是更专业的做法:
import random import time class Player: def __init__(self): self.health = 10 self.strength = 0 self.combat = 0 self.agility = 0 self.magic = 0 self.intelligence = 0 self.stealth = 0 def chose_class(self): print("Chose your class:") print("Warrior: 1") print("Wizard: 2") print("Philosopher: 3") print("Thief: 4") print("Help: 5") dog1 = int(input(":")) if dog1 ==1: self.strength = 7 self.combat = 7 self.agility = 5 self.stealth = 3 self.magic = 1 self.intelligence = 1 elif dog1 == 2: self.strength = 3 self.combat = 1 self.agility = 3 self.stealth = 3 self.magic = 8 self.intelligence = 6 elif dog1 == 3: self.strength = 3 self.combat = 1 self.agility = 3 self.stealth = 3 self.magic = 2 self.intelligence = 8 elif dog1 == 4: self.strength = 2 self.combat = 4 self.agility = 6 self.stealth = 8 self.magic = 1 self.intelligence = 6 elif dog1 == 5: self.show_class_help() self.chose_class() else: print("Invalid choice, please try again!") self.chose_class() def show_class_help(self): print("Warrior Dog:") print(" Warrior Dogs possess great strength and combat ability") print(" they have medium agility, but low stealth, magic and") print(" intelligence.") print("\n"*2) print("Wizard Dog:") print(" Wizard Dogs have low strength, combat, and agility,") print(" they have medium stealth and high magic capabilities.") print("\n"*2) print("Philosopher Dog:") print(" Philosopher Dogs are highly intelligent, while they") print(" have low strength, they have medium combat ability.") print(" Their agility, stealth, and magic start low but can") print(" rapidly improve by finding hidden objects on quests.") print("\n"*2) print("Thief Dogs") print(" Thief Dogs have high agility and stealth, as well as") print(" average intelligence and combat. They have low combat,") print(" magic, and strength.") def room17(player): print("**Description**") print("Do you want to fight the cat guard or sneak past it?") print("Fight: 1") print("Sneak Past: 2") choice17 = input(":") if choice17 == "1": fight17 = random.randint(0,5) combat17 = player.combat * fight17 if combat17 <= 20: print("You were successful") player.combat += 1 else: print("You lost the fight and had to retreat") player.health -= 1 # room1(player) elif choice17 == "2": sneak17 = random.randint(0,5) stealth17 = sneak17 * player.stealth if stealth17 <= 20: print("You snuck past the guard") player.stealth += 1 else: print("The guard caught you, he attacks and you have to retreat") player.health -= 2 player.stealth -= 1 # room1(player) else: print("Invalid choice, please pick 1 or 2!") room17(player) # 创建玩家对象 player = Player() player.chose_class() print("Combat:", player.combat) room17(player)
这个版本把所有玩家属性都放在Player类里,通过对象来访问和修改,完全不需要全局变量,代码结构更清晰,也不容易出错。
额外小建议
- 递归调用
chose_class虽然能实现重新选择,但如果用户多次输入错误,可能会导致递归深度过大报错,换成while循环会更稳妥。 - 输入处理时可以加一些异常捕获,比如用户输入非数字时不会崩溃。
内容的提问来源于stack exchange,提问作者Jonathan Farrow
相关产品推荐
相关产品推荐

