Can';t在Python中使用外部函数更改类变量
所以我做了一个游戏,我试图为玩家创建一个清单,我不能改变一个叫做“装备武器”的变量。我尝试了所有的方法,或者我得到了一个例外,或者当打印玩家的清单时,它显示了以前的武器。我也是初学者,所以如果我遗漏了什么,请告诉我Can';t在Python中使用外部函数更改类变量,python,python-3.x,class,variables,Python,Python 3.x,Class,Variables,所以我做了一个游戏,我试图为玩家创建一个清单,我不能改变一个叫做“装备武器”的变量。我尝试了所有的方法,或者我得到了一个例外,或者当打印玩家的清单时,它显示了以前的武器。我也是初学者,所以如果我遗漏了什么,请告诉我 # Existing items # Need a funtion to create a random item with random stats and a random name within a certain range. yes_list = ["yes", "yea
# Existing items
# Need a funtion to create a random item with random stats and a random name within a certain range.
yes_list = ["yes", "yeah", "sure", "why not"]
add_attack = "Attack:"
add_defense = "Defense:"
add_HP = "HP added:"
rarity = "Rarity"
weapon_rusty_sword = {
"Name:": "Rusty Sword",
add_attack: 1,
add_defense: 0,
rarity: 1
}
weapon_sword_wooden = {
"Name:": "Wooden Sword",
add_attack: 1.5,
add_defense: 0,
rarity: 1
}
weapon_sword_iron = {
"Name:": "Iron Sword",
add_attack: 2,
add_defense: 0,
rarity: 2
}
armor_chest_rusty_mail = {
"Name:": "Rusty Mail",
add_attack: 0,
add_defense: 1,
rarity: 1
}
armor_legs_adventurers = {
"Name:": "Adventurer's Leggings",
add_attack: 0,
add_defense: 1,
rarity: 1
}
armor_legs_rash_leggings = {
"Name:": "Rash Leggings",
add_attack: 0,
add_defense: 0.5,
rarity: 1
}
armor_head_rusty_cap = {
"Name:": "Rusty Cap",
add_attack: 0,
add_defense: 0.5,
rarity: 1
}
potion_hp = {
"Name:": "HP Potion,",
add_HP: 4
}
class Person:
#global equipped_weapon
equipped_weapon = weapon_rusty_sword
ui_equipped_weapon = {"Equipped Weapon: {}".format(weapon_rusty_sword): ""}
equipped_armor = {
"Head Protection:": {"Name": armor_head_rusty_cap["Name:"], "Defense": armor_head_rusty_cap[add_defense]},
"Chest Protection:": {"Name": armor_chest_rusty_mail["Name:"], "Defense": armor_chest_rusty_mail[add_defense]},
"Legs Protection:": {"Name": armor_legs_rash_leggings["Name:"], "Defense": armor_legs_rash_leggings[add_defense]},
}
ATTACK = 1 + equipped_weapon[add_attack]
DEFENSE = 1
HP = 20
gold = 10
potions = {"Potions: ": [potion_hp["Name:"]]}
ui_gold = {"Gold: ": gold}
def __init__(self):
self.name = "Cavalex"
inv = [
equipped_armor,
ui_equipped_weapon,
potions,
ui_gold
]
def see_inventory(self):
for element in self.inv:
for k, v in element.items():
if type(v) == list:
print(k, ' '.join(v))
else:
print(k, v)
# def equip_weapon(self, new_weapon_code):
# global equipped_weapon
# eq_val = input(
# "Do you want to equip this weapon? ->( {} )<-\nNote that your current weapon ( {} )will be discarded.".format(new_weapon_code["Name:"], self.equipped_weapon["Name:"]))
# if eq_val.lower() in yes_list:
# #del self.equipped_weapon
# self.equipped_weapon = new_weapon_code
# print("The weapon you had was discarded.")
# else:
# print("The new weapon was discarded.")
# See total amount of defense.
def defense_points():
return sum(value["Defense"] for key, value in player.equipped_armor.items())
def add_gold(amount):
player.gold += amount
# Adding to inventory
def new_potion_to_inv(potion):
player.potions["Potions: "].append(potion["Name:"])
def equipp_weapon(new_weapon_code):
# global player.equipped_weapon
eq_val = input(
"Do you want to equip this weapon? ->( {} )<-\nNote that your current weapon ( {} )will be discarded.".format(
new_weapon_code["Name:"], player.equipped_weapon["Name:"]))
if eq_val.lower() in yes_list:
del player.equipped_weapon
player.equipped_weapon = new_weapon_code
print("The weapon you had was discarded.")
else:
print("The new weapon was discarded.")
player = Person()
# game loop
while True:
print("Your name: ", player.name)
player.see_inventory() # Can't put print this function, else will print "None" in the end.
print("\nThis is your total armor defense: {}".format(defense_points()))
print()
new_potion_to_inv(potion_hp)
player.see_inventory()
print(player.ATTACK)
print()
print("Now we are changing your weapon.")
equipp_weapon(weapon_sword_iron)
print()
print(player.ATTACK)
player.see_inventory()
break
#现有项目
#需要一个函数来创建一个随机项目,在一定范围内具有随机统计数据和随机名称。
yes_list=[“yes”,“yeah”,“sure”,“why not”]
添加\u attack=“攻击:”
添加_defence=“defence:”
add_HP=“HP已添加:”
稀有性=“稀有性”
武器生锈的剑={
“名字::“生锈的剑”,
添加攻击:1,
添加_防御:0,
稀有性:1
}
武器、剑、木={
“名字::“木剑”,
新增攻击:1.5,
添加_防御:0,
稀有性:1
}
武器、剑、铁={
“名字::”铁剑“,
添加攻击:2,
添加_防御:0,
稀有性:2
}
盔甲\u箱子\u生锈\u邮件={
“姓名::“生锈的邮件”,
添加攻击:0,
加上:1,,
稀有性:1
}
护甲·腿·冒险家={
“姓名::“冒险家绑腿”,
添加攻击:0,
加上:1,,
稀有性:1
}
护甲、护腿、皮疹、护腿={
“姓名::“皮疹绑腿”,
添加攻击:0,
添加_防御:0.5,
稀有性:1
}
盔甲\u头\u生锈\u帽={
“姓名::“生锈的帽子”,
添加攻击:0,
添加_防御:0.5,
稀有性:1
}
药水\u hp={
“名称::“HP药剂,”,
加上HP:4
}
班长:
#全球装备反坦克武器
装备的武器=武器生锈的剑
ui_装备的武器={“装备的武器:{}”。格式(武器生锈的剑):“”
装备装甲={
“头部防护:”:{“名称”:盔甲头锈帽[“名称:”],“防御”:盔甲头锈帽[添加防御],
“护胸:”:{“名称”:护甲护胸生锈邮件[“名称:”],“防御”:护甲护胸生锈邮件[添加防御],
“腿部防护:”:{“名称”:护甲、护腿、护腿[“名称:”],“防御”:护甲、护腿、护腿[添加防御],
}
攻击=1+装备武器[增加攻击]
防御=1
HP=20
黄金=10
药剂={“药剂::[potion_hp[“名称:”]}
ui_gold={“gold::gold}
定义初始化(自):
self.name=“Cavalex”
库存=[
装备装甲,
装备了反坦克武器,
药剂,
乌尤黄金
]
def见库存(自我):
对于self.inv中的元素:
对于元素.items()中的k,v:
如果类型(v)==列表:
打印(k),“连接(v))
其他:
印刷品(k,v)
#def装备武器(自身、新武器代码):
#全球装备反坦克武器
#eq_val=输入(
#“你想装备这个武器吗?”->({})({})问题是你把装备的武器设置成了类属性,而不是实例属性。del instance.attribute
只删除实例属性,它甚至不查找类属性
如果目标只是更改实例,您可以完全删除del
;下一行将添加(如果不存在实例属性,隐藏类属性)或替换(如果已经存在实例属性)实例的特定武器
如果目标是更改类,则需要更改作业以对类进行操作:
type(player).equipped_weapon = new_weapon_code
Player.equipped_weapon = new_weapon_code
或显式命名类:
type(player).equipped_weapon = new_weapon_code
Player.equipped_weapon = new_weapon_code
无论哪种方式,del
都不是必需的;分配新值将替换旧值,以与del
显式相同的方式隐式删除对旧值的引用。执行del类型(玩家)是完全合法的.装备武器
或del Player.装备武器
删除特定的类属性,但这是毫无意义的;无论需要什么行为,简单地分配给类或实例属性都将丢弃旧的引用
更新:如您所述,删除del
可以防止异常,但您的输出(从查看\u inventory
)永远不会改变。这是因为查看库存正在查看玩家.inv
,它反过来包含了对玩家.ui装备的武器原始值的引用。问题是,ui装备的武器和装备的武器是基于同一默认武器初始化的,但它们没有同步相互之间;更改一个对另一个没有影响(因此,在类或实例上更改装备的武器不会影响库存,因此请参见库存
)
实际上,这里的解决方案是创建一个健全的类。你的类属性没有一个是有意义的;它们都是逻辑上的实例属性,应该这样定义。在一些情况下,它们只是另一个属性的面向方便的转换;在这些情况下,它们根本不应该是属性,而应该是property
s,whichh基于另一个属性动态地重新计算它们的值,以防止它们不同步
下面是一个非常快速的重写(未测试,可能有小的拼写错误),它将所有对齐的属性移动到实例,并将其余属性转换为只读属性,这些属性的值从另一个实例属性派生:
import copy
# Factored out to avoid repetition
def clean_armor(armor):
return {k.rstrip(':'): v
for k, v in armor.items() if k in {'Name:', 'Defense:'}}
class Person:
DEFAULT_WEAPON = weapon_rusty_sword
DEFAULT_ARMOR = {
"Head Protection:": clean_armor(armor_head_rusty_cap),
"Chest Protection:": clean_armor(armor_chest_rusty_mail),
"Legs Protection:": clean_armor(armor_legs_rash_leggings),
}
def __init__(self, name="Cavalex",
equipped_weapon=DEFAULT_WEAPON, equipped_armor=DEFAULT_ARMOR,
base_attack=1, base_defense=1,
hp=20, gold=10,
potions=(potion_hp["Name:"],)):
self.name = name
# deepcopy is defensive (so changing defaults doesn't retroactively
# alter existing instance); can be removed if you guarantee defaults
# won't be changed, or you want changes to defaults to affect
# Players still wielding default items
self.equipped_weapon = copy.deepcopy(equipped_weapon)
self.equipped_armor = copy.deepcopy(equipped_armor)
self.base_attack = int(base_attack)
self.base_defense = int(base_defense)
self.HP = int(hp)
self.gold = int(gold)
# potions only used as dictionary, but it's silly to store it as one
# Just store list of potion names in protected attribute,
# property can construct the expected dict on demand
self._potions = list(potions)
@property
def ATTACK(self):
return self.base_attack + self.equipped_weapon[add_attack]
@property
def DEFENSE(self):
return self.base_defense + sum(armor['Defense'] for armor in self.equipped_armor.values())
@property
def potions(self):
return {"Potions: ": self._potions}
@property
def ui_gold(self):
return {"Gold: ": self.gold}
@property
def ui_equipped_weapon(self):
return {"Equipped Weapon: {}".format(self.equipped_weapon): ""}
@property:
def inv(self):
return [
self.equipped_armor,
self.ui_equipped_weapon,
self.potions,
self.ui_gold,
]
def see_inventory(self):
for element in self.inv:
for k, v in element.items():
if isinstance(v, list):
print(k, ' '.join(v))
else:
print(k, v)
这仍然有很多值得怀疑的选择(不一致的属性/属性命名;dict
s中奇怪的键名,这些键名似乎是为了使显示更容易,但使所有非显示使用更烦人;对仅作为实例方法才有意义的事情使用顶级函数,等等),但我保留了这些怪癖,使其成为现有类的替代品(但是在实例上设置了所有每个玩家的属性,而不是类,并且所有派生属性都是通过属性s计算的,而不是静态设置的,因为独立的静态属性会增加基本属性和派生属性不同步的几率)
我保存