如何用更简洁的内容替换所有这些 "if...elif...else" 语句?
How replace all these "if...elif...else" statements with something more concise?
有没有办法减少我的陈述中 elif
的数量?在 another question I asked 中,有人说我的代码存在冗余问题,确实如此。我对 python 和一般编码还比较陌生,当我查找内容时,总是有点难以理解。
这是我正在谈论的代码块:
(如果需要我可以 post 剩下的代码)
if (random_mon_name.lower()=='normal'):
rangen_mon_name = random.choice(mon_name_type_NORMAL)
break
elif (random_mon_name.lower()=='fire'):
rangen_mon_name = random.choice(mon_name_type_FIRE)
break
elif (random_mon_name.lower()=='water'):
rangen_mon_name = random.choice(mon_name_type_WATER)
break
elif (random_mon_name.lower()=='grass'):
rangen_mon_name = random.choice(mon_name_type_GRASS)
break
elif (random_mon_name.lower()=='electric'):
rangen_mon_name = random.choice(mon_name_type_ELECTRIC)
break
elif (random_mon_name.lower()=='ice'):
rangen_mon_name = random.choice(mon_name_type_ICE)
break
elif (random_mon_name.lower()=='fighting'):
rangen_mon_name = random.choice(mon_name_type_FIGHTING)
break
elif (random_mon_name.lower()=='poison'):
rangen_mon_name = random.choice(mon_name_type_POISON)
break
elif (random_mon_name.lower()=='ground'):
rangen_mon_name = random.choice(mon_name_type_GROUND)
break
elif (random_mon_name.lower()=='flying'):
rangen_mon_name = random.choice(mon_name_type_FLYING)
break
elif (random_mon_name.lower()=='psychic'):
rangen_mon_name = random.choice(mon_name_type_PSYCHIC)
break
elif (random_mon_name.lower()=='bug'):
rangen_mon_name = random.choice(mon_name_type_BUG)
break
elif (random_mon_name.lower()=='ghost'):
rangen_mon_name = random.choice(mon_name_type_GHOST)
break
elif (random_mon_name.lower()=='rock'):
rangen_mon_name = random.choice(mon_name_type_ROCK)
break
elif (random_mon_name.lower()=='dark'):
rangen_mon_name = random.choice(mon_name_type_DARK)
break
elif (random_mon_name.lower()=='dragon'):
rangen_mon_name = random.choice(mon_name_type_DRAGON)
break
elif (random_mon_name.lower()=='steel'):
rangen_mon_name = random.choice(mon_name_type_STEEL)
break
elif (random_mon_name.lower()=='fairy'):
rangen_mon_name = random.choice(mon_name_type_FAIRY)
break
else:
print("You didn't actually enter a type.\nTry Again.")
我建议您创建一个 dict
,这样:
myDict = {}
myDict['ice'] = mon_name_type_ICE
# ...and so on
这样您就可以使用一小段代码访问它:
rangen_mon_name = random.choice(myDict[random_mon_name.lower()])
您还可以添加一个 try
/except
块来模拟您的 else
:
try:
rangen_mon_name = random.choice(myDict[random_mon_name.lower()])
except KeyError:
print("You didn't actually enter a type.\nTry Again.")
将所有这些都放入像字典这样的数据结构中似乎会让您受益。由于您只是将值设置为具有完美 1:1 映射的其他值,因此字典就是为此而制作的。
random_mon_name_dict = {'normal': random.choice(mon_name_type_NORMAL), 'bug', random.choice(mon_name_type_BUG)}
但显然对他们所有人来说。
我理解正确吗?
像下面的 choices
那样构造一个字典。将攻击值传递给 get_attack_values
,如果攻击在 choices
中,则将值,即 mon_name_type_ICE
传递给 random.choice()
函数。
import random
choices = {
'ice': {'choice': 'mon_name_type_ICE'},
'fire': { 'choice': 'mon_name_type_WATER'}
}
def get_attack_value(attack):
if attack in choices.keys():
rangen_mon_name = random.choice(choices[attack]['choice'])
else:
print("You didn't actually enter a type.\nTry Again.")
get_attack_value('fire')
此代码中存在如此多冗余的根本原因是您必须管理大量变量。
每当你有一堆单独的变量都包含相同类型的数据,比如 mon_name_type_FIRE
和 mon_name_type_WATER
(我假设这些是与该攻击类型相关的名称列表),它是一个强有力的线索表明您应该将它们放入一个集合中,例如字典或列表。这不仅减少了代码中要跟踪的变量数量,还可以动态访问这些值,而不是使用大量复制+粘贴代码。
例如,如果您将所有不同的 mon
放入由攻击类型决定的 dict
中, 而不是 创建所有 mon_name_type_WHATEVER
个变量:
mon_by_type = {
"fire": ["charmander", "charmeleon", "charizard"],
"water": ["squirtle", "wartortle", "blastoise"],
# etc
}
您现在可以用单个字典查找替换您的巨型 if
/elif
链:
try:
random_mon = random.choice(mon_by_type[random_mon_name.lower()])
except KeyError:
print("You didn't actually enter a type. Try again.")
如果您没有在代码的其他区域使用像 mon_name_type_FIRE
这样的变量,并且您能够创建“名称”查找或字典,那么您肯定会想要这样做。请参阅@FLAC-ZOSO 和@samwise 的回答以帮助您入门。
但是,如果您已经定义了所有这些“名称”列表并且想要使用“适当的”列表,您可能会考虑从 locals()
(或 globals())
.
import random
## ------------------
## You have these pre-defined and want to keep them
## as distinct variables for some reason.
## ------------------
mon_name_type_NORMAL = ["Elf", "Human"]
mon_name_type_FIRE = ["Fire Dwarf", "Cinder Elf"]
## ------------------
## ------------------
## Use a "mob" class and locals() to find the appropriate matching
## list of mob names.
## ------------------
random_mon_name = "Fire"
rmn_key = f"mon_name_type_{random_mon_name.upper()}"
name_options = locals().get(rmn_key, ["**unnamed mob**"])
## ------------------
print(random.choice(name_options))
到目前为止,我最喜欢@Samwise 的回答,因为它使代码成为“data-driven”,因为它不仅消除了所有这些变量,而且还使扩展变得微不足道——但我认为它可能是通过创建一个字典本身也以这种方式完成了一点。这就是我的意思:
from pprint import pprint
import random
MON_TYPE_NAMES = """\
normal, Normodo, Normalia, Normew
fire, Firaint, Heatoro, Flamala
water, Splashoto, Oceatto, Puddlio
grass, Weedevon, Grassimar, Leafadroon
electric, Enetick, Electol, Litero
ice, Snova, Icello, Colaggro
fighting, Allphist, Lullakick, Bubblow
poison, Poizase, Gunkamight, Aison
ground, Groutal, Moundiflox, Umbron
flying, Wingyu, Sparial, Flogun
psychic, Mindswell, Thinkarva, Psymarine
bug, Bugonite, Flyzaur, Mantile
ghost, Phantini, Spirook, Tortasm
rock, Storilot, Rocoalia, Sedite
dark, Nolite, Dariotte, Nitrash
dragon, Dracat, Wyveron, Randigon
steel, Metalaze, Gearevo, Iromonora
fairy, Faeream, Pixirola, Trixitrite
"""
# Create dictionary from mon type names.
name_to_choices = {v[0]: v[1:] for v in (line.replace(',', ' ').split()
for line in MON_TYPE_NAMES.splitlines())}
pprint(name_to_choices, sort_dicts=False)
print()
# Select random mon name based on mon type.
random_mon_type = 'Ghost'
if not (choices := name_to_choices.get(random_mon_type.lower())):
print("Unknown mon type")
else:
rangen_mon_name = random.choice(choices)
print(f'random {random_mon_type} name -> {rangen_mon_name}')
有没有办法减少我的陈述中 elif
的数量?在 another question I asked 中,有人说我的代码存在冗余问题,确实如此。我对 python 和一般编码还比较陌生,当我查找内容时,总是有点难以理解。
这是我正在谈论的代码块:
(如果需要我可以 post 剩下的代码)
if (random_mon_name.lower()=='normal'):
rangen_mon_name = random.choice(mon_name_type_NORMAL)
break
elif (random_mon_name.lower()=='fire'):
rangen_mon_name = random.choice(mon_name_type_FIRE)
break
elif (random_mon_name.lower()=='water'):
rangen_mon_name = random.choice(mon_name_type_WATER)
break
elif (random_mon_name.lower()=='grass'):
rangen_mon_name = random.choice(mon_name_type_GRASS)
break
elif (random_mon_name.lower()=='electric'):
rangen_mon_name = random.choice(mon_name_type_ELECTRIC)
break
elif (random_mon_name.lower()=='ice'):
rangen_mon_name = random.choice(mon_name_type_ICE)
break
elif (random_mon_name.lower()=='fighting'):
rangen_mon_name = random.choice(mon_name_type_FIGHTING)
break
elif (random_mon_name.lower()=='poison'):
rangen_mon_name = random.choice(mon_name_type_POISON)
break
elif (random_mon_name.lower()=='ground'):
rangen_mon_name = random.choice(mon_name_type_GROUND)
break
elif (random_mon_name.lower()=='flying'):
rangen_mon_name = random.choice(mon_name_type_FLYING)
break
elif (random_mon_name.lower()=='psychic'):
rangen_mon_name = random.choice(mon_name_type_PSYCHIC)
break
elif (random_mon_name.lower()=='bug'):
rangen_mon_name = random.choice(mon_name_type_BUG)
break
elif (random_mon_name.lower()=='ghost'):
rangen_mon_name = random.choice(mon_name_type_GHOST)
break
elif (random_mon_name.lower()=='rock'):
rangen_mon_name = random.choice(mon_name_type_ROCK)
break
elif (random_mon_name.lower()=='dark'):
rangen_mon_name = random.choice(mon_name_type_DARK)
break
elif (random_mon_name.lower()=='dragon'):
rangen_mon_name = random.choice(mon_name_type_DRAGON)
break
elif (random_mon_name.lower()=='steel'):
rangen_mon_name = random.choice(mon_name_type_STEEL)
break
elif (random_mon_name.lower()=='fairy'):
rangen_mon_name = random.choice(mon_name_type_FAIRY)
break
else:
print("You didn't actually enter a type.\nTry Again.")
我建议您创建一个 dict
,这样:
myDict = {}
myDict['ice'] = mon_name_type_ICE
# ...and so on
这样您就可以使用一小段代码访问它:
rangen_mon_name = random.choice(myDict[random_mon_name.lower()])
您还可以添加一个 try
/except
块来模拟您的 else
:
try:
rangen_mon_name = random.choice(myDict[random_mon_name.lower()])
except KeyError:
print("You didn't actually enter a type.\nTry Again.")
将所有这些都放入像字典这样的数据结构中似乎会让您受益。由于您只是将值设置为具有完美 1:1 映射的其他值,因此字典就是为此而制作的。
random_mon_name_dict = {'normal': random.choice(mon_name_type_NORMAL), 'bug', random.choice(mon_name_type_BUG)}
但显然对他们所有人来说。
我理解正确吗?
像下面的 choices
那样构造一个字典。将攻击值传递给 get_attack_values
,如果攻击在 choices
中,则将值,即 mon_name_type_ICE
传递给 random.choice()
函数。
import random
choices = {
'ice': {'choice': 'mon_name_type_ICE'},
'fire': { 'choice': 'mon_name_type_WATER'}
}
def get_attack_value(attack):
if attack in choices.keys():
rangen_mon_name = random.choice(choices[attack]['choice'])
else:
print("You didn't actually enter a type.\nTry Again.")
get_attack_value('fire')
此代码中存在如此多冗余的根本原因是您必须管理大量变量。
每当你有一堆单独的变量都包含相同类型的数据,比如 mon_name_type_FIRE
和 mon_name_type_WATER
(我假设这些是与该攻击类型相关的名称列表),它是一个强有力的线索表明您应该将它们放入一个集合中,例如字典或列表。这不仅减少了代码中要跟踪的变量数量,还可以动态访问这些值,而不是使用大量复制+粘贴代码。
例如,如果您将所有不同的 mon
放入由攻击类型决定的 dict
中, 而不是 创建所有 mon_name_type_WHATEVER
个变量:
mon_by_type = {
"fire": ["charmander", "charmeleon", "charizard"],
"water": ["squirtle", "wartortle", "blastoise"],
# etc
}
您现在可以用单个字典查找替换您的巨型 if
/elif
链:
try:
random_mon = random.choice(mon_by_type[random_mon_name.lower()])
except KeyError:
print("You didn't actually enter a type. Try again.")
如果您没有在代码的其他区域使用像 mon_name_type_FIRE
这样的变量,并且您能够创建“名称”查找或字典,那么您肯定会想要这样做。请参阅@FLAC-ZOSO 和@samwise 的回答以帮助您入门。
但是,如果您已经定义了所有这些“名称”列表并且想要使用“适当的”列表,您可能会考虑从 locals()
(或 globals())
.
import random
## ------------------
## You have these pre-defined and want to keep them
## as distinct variables for some reason.
## ------------------
mon_name_type_NORMAL = ["Elf", "Human"]
mon_name_type_FIRE = ["Fire Dwarf", "Cinder Elf"]
## ------------------
## ------------------
## Use a "mob" class and locals() to find the appropriate matching
## list of mob names.
## ------------------
random_mon_name = "Fire"
rmn_key = f"mon_name_type_{random_mon_name.upper()}"
name_options = locals().get(rmn_key, ["**unnamed mob**"])
## ------------------
print(random.choice(name_options))
到目前为止,我最喜欢@Samwise 的回答,因为它使代码成为“data-driven”,因为它不仅消除了所有这些变量,而且还使扩展变得微不足道——但我认为它可能是通过创建一个字典本身也以这种方式完成了一点。这就是我的意思:
from pprint import pprint
import random
MON_TYPE_NAMES = """\
normal, Normodo, Normalia, Normew
fire, Firaint, Heatoro, Flamala
water, Splashoto, Oceatto, Puddlio
grass, Weedevon, Grassimar, Leafadroon
electric, Enetick, Electol, Litero
ice, Snova, Icello, Colaggro
fighting, Allphist, Lullakick, Bubblow
poison, Poizase, Gunkamight, Aison
ground, Groutal, Moundiflox, Umbron
flying, Wingyu, Sparial, Flogun
psychic, Mindswell, Thinkarva, Psymarine
bug, Bugonite, Flyzaur, Mantile
ghost, Phantini, Spirook, Tortasm
rock, Storilot, Rocoalia, Sedite
dark, Nolite, Dariotte, Nitrash
dragon, Dracat, Wyveron, Randigon
steel, Metalaze, Gearevo, Iromonora
fairy, Faeream, Pixirola, Trixitrite
"""
# Create dictionary from mon type names.
name_to_choices = {v[0]: v[1:] for v in (line.replace(',', ' ').split()
for line in MON_TYPE_NAMES.splitlines())}
pprint(name_to_choices, sort_dicts=False)
print()
# Select random mon name based on mon type.
random_mon_type = 'Ghost'
if not (choices := name_to_choices.get(random_mon_type.lower())):
print("Unknown mon type")
else:
rangen_mon_name = random.choice(choices)
print(f'random {random_mon_type} name -> {rangen_mon_name}')