Python 选择特定属性值较大的对象
我刚开始学习python,所以我不熟悉各种技巧或工具,也不熟悉正确的提问方式。正因为如此,我无法找到以前的问题,做什么,我正在寻找 我在这里概述了一个工作代码:Python 选择特定属性值较大的对象,python,Python,我刚开始学习python,所以我不熟悉各种技巧或工具,也不熟悉正确的提问方式。正因为如此,我无法找到以前的问题,做什么,我正在寻找 我在这里概述了一个工作代码: import random class UserGroup: def __init__(self, users): self.user_list = users def random_users(self): self.random_1 = random.choice(self.use
import random
class UserGroup:
def __init__(self, users):
self.user_list = users
def random_users(self):
self.random_1 = random.choice(self.user_list)
self.random_2 = self.random_1
while self.random_2 == self.random_1:
self.random_2 = random.choice(self.user_list)
return self.random_1, self.random_2
class User:
def __init__(self, nickname, stats):
self.nickname = nickname
self.strength = stats['strength']
self.constitution = stats['constitution']
self.dexterity = stats['dexterity']
self.intelligence = stats['intelligence']
self.wisdom = stats['wisdom']
self.charisma = stats['charisma']
def __repr__(self):
return self.nickname
class Jared(User):
def fight_stat(self):
self.attack = self.strength + self.intelligence
self.defense = self.constitution * 2
self.speed = self.dexterity / 2
class Poptart(User):
def fight_stat(self):
self.attack = self.strength + self.dexterity
self.defense = self.dexterity
self.speed = self.dexterity + self.charisma
class Kaos(User):
def fight_stat(self):
self.attack = self.dexterity + self.wisdom
self.defense = self.wisdom * 2
self.speed = self.dexterity
class Magda(User):
def fight_stat(self):
self.attack = self.intelligence + self.charisma
self.defense = self.dexterity + self.charisma
self.speed = self.dexterity + self.constitution / 2
class Battle:
def __init__(self, user1, user2):
self.user1 = user1
self.user2 = user2
print(user1, "and", user2, "have entered the fight!")
def fight(self):
self.user1.fight_stat()
self.user2.fight_stat()
if self.user1.speed > self.user2.speed:
self.attacker = self.user1
self.defender = self.user2
elif self.user2.speed > self.user1.speed:
self.attacker = self.user2
self.defender = self.user1
elif self.user1.dexterity > self.user2.dexterity:
self.attacker = self.user1
self.defender = self.user2
else:
self.attacker = self.user2
self.defender = self.user1
if self.attacker.attack > self.defender.defense:
return self.attacker
elif self.defender.attack > self.attacker.defense:
return self.defender
else:
return "Draw"
# HERE STARTS BATTLE CODE
jared = Jared('Jarebear', {'strength': 7, 'constitution': 6, 'dexterity': 6, 'intelligence': 8, 'wisdom': 5, 'charisma': 5})
poptart = Poptart('Yung SLizzy', {'strength': 4, 'constitution': 5, 'dexterity': 10, 'intelligence': 7, 'wisdom': 5, 'charisma': 7})
kaos = Kaos('Kung Cows', {'strength': 8, 'constitution': 7, 'dexterity': 6, 'intelligence': 4, 'wisdom': 7, 'charisma': 4})
magda = Magda('Meghan M', {'strength': 7, 'constitution': 5, 'dexterity': 7, 'intelligence': 8, 'wisdom': 5, 'charisma': 5})
users = UserGroup([jared, poptart, kaos, magda])
for i in range(1,4):
print("Battle number", i)
battle = Battle(*users.random_users())
print("The winner is: ", battle.fight())
示例输出如下所示:
Battle number 1
Jarebear and Kung Cows have entered the fight!
The winner is: Kung Cows
Battle number 2
Jarebear and Kung Cows have entered the fight!
The winner is: Kung Cows
Battle number 3
正如我所写的,代码按预期执行。然而,我关心的是我在Battle
类中实现fight()
方法的方式。我不认为大序列的if
语句是说“用户先进行高速攻击”的正确方式。从逻辑上讲,我只需要一个类似于self.attacker=max(self.user1.speed,self.user2.speed)
的语句,但是攻击者被设置为用户,而不是用户的速度。但是,我不知道如何用python中的一两行代码来实现这一点。您确实可以使用max()以最快的速度获得用户
方法是使用键
参数,您可以使用该参数传递一个自定义评分函数,该函数接受每个对象并返回一个可排序的值,如float或int
def score(user):
return user.speed
fastest_user = max(list_of_users, key=score)
最常见的是传递一个匿名lambda函数,该函数由以下语法定义:
lambda var1, var2: expression
所以代码看起来像:
fastest_user = max(list_of_users, key=lambda user: user.speed)
您确实可以使用max()以最快的速度获取用户
方法是使用键
参数,您可以使用该参数传递一个自定义评分函数,该函数接受每个对象并返回一个可排序的值,如float或int
def score(user):
return user.speed
fastest_user = max(list_of_users, key=score)
最常见的是传递一个匿名lambda函数,该函数由以下语法定义:
lambda var1, var2: expression
所以代码看起来像:
fastest_user = max(list_of_users, key=lambda user: user.speed)
我只需要一个像自我攻击一样的陈述=
max(self.user1.speed,self.user2.speed),但攻击者设置为
用户,而不是用户的速度
你可以用
from operator import attrgetter
...
self.attacker = max(self.user1, self.user2, key=attrgetter('speed'))
这将返回用户
(不是速度
)具有最大速度
如果您有2个以上的用户,还可以通过列表
我只需要一个像自我攻击一样的陈述=
max(self.user1.speed,self.user2.speed),但攻击者设置为
用户,而不是用户的速度
你可以用
from operator import attrgetter
...
self.attacker = max(self.user1, self.user2, key=attrgetter('speed'))
这将返回用户
(不是速度
)具有最大速度
如果您有2个以上的用户,还可以通过列表
创建集中逻辑的小方法没有“开销”。它们很容易理解,并且不需要出于很多原因进行更改-因此它们在大多数情况下都是完成、测试和不变的
class Battle:
# snipped some code
@staticmethod
def get_attacker_defender(u1, u2):
"""Returs tuple (attacker,defender) based on given user."""
if u1.speed > u2.speed:
return u1,u2
elif u2.speed > u1.speed:
return u2,u1
# probably cleaner to stay with elif: ... else ... but this is shorter
return (u1,u2) if u1.dexterity > u2.dexterity else (u2,u1)
def fight(self):
self.user1.fight_stat()
self.user2.fight_stat()
self.attacker, self.defender = Battle.get_attacker_defender(self.user1,self.user2)
if self.attacker.attack > self.defender.defense:
return self.attacker
elif self.defender.attack > self.attacker.defense:
return self.defender
else:
return "Draw"
如果你喜欢脑筋急转弯,不妨:
@staticmethod
def get_attacker_defender(u1,u2):
return sorted( [u1,u2], key = lambda u:(u.speed,u.dexterity), reverse=True)
它利用基于第一个元素排序的元组排序,并且当元组的第二个元素上的第一个元素相等时。如果两者相等,则顺序保持不变(稳定排序)
Doku:
- (对于
返回..如果..否则..
)
创建集中逻辑的小方法没有“开销”。它们很容易理解,并且不需要出于很多原因进行更改-因此它们在大多数情况下都是完成、测试和不变的
class Battle:
# snipped some code
@staticmethod
def get_attacker_defender(u1, u2):
"""Returs tuple (attacker,defender) based on given user."""
if u1.speed > u2.speed:
return u1,u2
elif u2.speed > u1.speed:
return u2,u1
# probably cleaner to stay with elif: ... else ... but this is shorter
return (u1,u2) if u1.dexterity > u2.dexterity else (u2,u1)
def fight(self):
self.user1.fight_stat()
self.user2.fight_stat()
self.attacker, self.defender = Battle.get_attacker_defender(self.user1,self.user2)
if self.attacker.attack > self.defender.defense:
return self.attacker
elif self.defender.attack > self.attacker.defense:
return self.defender
else:
return "Draw"
如果你喜欢脑筋急转弯,不妨:
@staticmethod
def get_attacker_defender(u1,u2):
return sorted( [u1,u2], key = lambda u:(u.speed,u.dexterity), reverse=True)
它利用基于第一个元素排序的元组排序,并且当元组的第二个元素上的第一个元素相等时。如果两者相等,则顺序保持不变(稳定排序)
Doku:
- (对于
返回..如果..否则..
)
最小值
和最大值函数接受一个键函数,告诉它们如何比较输入。键接受每个输入并返回要比较的实际值:
max(self.user1, self.user2, key=lambda item: item.speed)
对于大量比较,可以将其改写为
from operator import attrgetter
speed_key = attrgetter('speed')
max(self.user1, self.user2, key=speed_key)
如果速度相等,则可以决定使用不同的属性进行比较。这是通过理解Python序列是按字典顺序进行比较来实现的。这是字符串最容易理解的,因为它基本上只是字典顺序:例如,'abc'>'abb'
,因为每个元素都是按顺序比较的。列表和元组也是如此:[1,2,3]>[1,2,2]
因此,要使用灵巧性
属性作为同等速度的后备方法,请执行以下操作
max(self.user1, self.user2, key=lambda item: (item.speed, item.dexterity))
或
min
和max
函数接受一个键
函数,告诉它们如何比较输入。键接受每个输入并返回要比较的实际值:
max(self.user1, self.user2, key=lambda item: item.speed)
对于大量比较,可以将其改写为
from operator import attrgetter
speed_key = attrgetter('speed')
max(self.user1, self.user2, key=speed_key)
如果速度相等,则可以决定使用不同的属性进行比较。这是通过理解Python序列是按字典顺序进行比较来实现的。这是字符串最容易理解的,因为它基本上只是字典顺序:例如,'abc'>'abb'
,因为每个元素都是按顺序比较的。列表和元组也是如此:[1,2,3]>[1,2,2]
因此,要使用灵巧性
属性作为同等速度的后备方法,请执行以下操作
max(self.user1, self.user2, key=lambda item: (item.speed, item.dexterity))
或
这里有一个答案,它将上述逻辑分开,并使用您最初的最大欲望。此解决方案的好处是,可以轻松重构确定第一次攻击的逻辑。只需更改顺序(或添加属性)
attribute\u priority\u顺序
class Battle:
def __init__(self, user1, user2):
self.user1 = user1
self.user2 = user2
print(user1, "and", user2, "have entered the fight!")
@staticmethod
def _compare_attributes(user1: User, user2: User, attribute: str):
if getattr(user1, attribute) != getattr(user2, attribute):
return max(
[user1, user2],
key=lambda user: getattr(user, attribute)
)
def get_attacker(self):
"""
Returns attacker based on attribute comparison
:return: User
"""
default_attacker = self.user2
attribute_priority_order = [
'speed',
'dexterity'
]
for attribute in attribute_priority_order:
attacker = self._compare_attributes(
user1=self.user1,
user2=self.user2,
attribute=attribute
)
if attacker:
return attacker
return default_attacker
def get_defender(self):
"""
User in the battle that isn't the attacker.
:return: User
"""
for user in [self.user1, self.user2]:
if str(user) != str(self.attacker):
return user
def fight(self):
self.user1.fight_stat()
self.user2.fight_stat()
self.attacker = self.get_attacker()
self.defender = self.get_defender()
if self.attacker.attack > self.defender.defense:
return self.attacker
elif self.defender.attack > self.attacker.defense:
return self.defender
else:
return "Draw"
通过一些额外的抽象,
\u compare\u attributes
方法可以循环使用,以确定胜利者,也可以使用可选的第二个属性。如果没有联系,此方法的返回也可以由用户选择。这里有一个答案,它将如上所述的逻辑分开,并使用您最初的最大期望值。此解决方案的好处是,可以轻松重构确定第一次攻击的逻辑。只需更改顺序(或添加属性)attribute\u priority\u顺序
class Battle:
def __init__(self, user1, user2):
self.user1 = user1
self.user2 = user2
print(user1, "and", user2, "have entered the fight!")
@staticmethod
def _compare_attributes(user1: User, user2: User, attribute: str):
if getattr(user1, attribute) != getattr(user2, attribute):
return max(
[user1, user2],
key=lambda user: getattr(user, attribute)
)
def get_attacker(self):
"""
Returns attacker based on attribute comparison
:return: User
"""
default_attacker = self.user2
attribute_priority_order = [
'speed',
'dexterity'
]
for attribute in attribute_priority_order:
attacker = self._compare_attributes(
user1=self.user1,
user2=self.user2,
attribute=attribute
)
if attacker:
return attacker
return default_attacker
def get_defender(self):
"""
User in the battle that isn't the attacker.
:return: User
"""
for user in [self.user1, self.user2]:
if str(user) != str(self.attacker):
return user
def fight(self):
self.user1.fight_stat()
self.user2.fight_stat()
self.attacker = self.get_attacker()
self.defender = self.get_defender()
if self.attacker.attack > self.defender.defense:
return self.attacker
elif self.defender.attack > self.attacker.defense:
return self.defender
else:
return "Draw"
再加一点