【发布时间】:2016-07-19 20:47:16
【问题描述】:
我有这样的结构(伪代码):
class Player {
steamid: str
hero: Hero
}
class Hero {
class_id: str
level: int
xp: int
skills: list[Skill]
}
class Skill {
class_id: str
level: int
}
现在我正在尝试将其存储到数据库中,并为我的播放器提供了一个 get_serialized_data() 方法,该方法返回一个如下所示的元组:
return (
# players
(steamid, hero.class_id),
# heroes
(steamid, hero.class_id, hero.level, hero.xp),
# skills
(
(steamid, hero.class_id, skill.class_id, skill.level)
for skill in hero.skills
),
)
最后,我同时将每个玩家的数据存储到数据库中,并使用三个调用executemany() 来保存:
-
每个玩家的数据在一个
executemany() -
每个英雄的数据在一个
executemany() -
每个技能的数据在一个
executemany()
这是我的代码:
def save_all_data(*, commit=True):
"""Save every active player's data into the database."""
players_data = []
heroes_data = []
skills_data = []
for player in _players.values():
player_data, hero_data, skills_data_ = player.get_serialized_data()
players_data.append(player_data)
heroes_data.append(heroes_data)
skills_data.extend(skills_data_)
_database.save_players(players_data)
_database.save_heroes(heroes_data)
_database.save_skills(skills_data)
if commit:
_database.commit()
如您所见,“问题”是我构建了三个大列表。是否可以以某种方式用生成器替换这些列表?我的_database.save_X() 方法都接受生成器,因此会节省大量内存。
编辑:另外,我不想循环播放器三遍。所以我很想在一个循环中以某种方式获得三个生成器。
【问题讨论】:
-
“三个大列表” – 我们实际谈论的是多大?
player_data和hero_data似乎分别是 2 元组和 4 元组。如果您使用的是 Python 3,那么skills_data_应该已经是 4 元组的生成器(因为您使用的是生成器表达式(something for skill in hero.skills)) -
玩家人数可以是 1 到 5000 人之间的任意值,英雄人数总是等于玩家人数,每个英雄可以拥有 4 到 15 种技能。我说的是
players_data、heroes_data和skills_data列表,希望将它们变成(tuple, tuple, generator[tuple])的生成器,而不是(tuple, tuple, generator[tuple])的列表。 -
这很重要,因为一个包含 15 个项目的列表是 nothing (你从那里的生成器中一无所获)。甚至 5000 也不是那么多。您还必须考虑数据的来源。数据是否已经在内存中?还是你懒洋洋地从别的地方看?
-
就您的问题而言,尚不清楚数据来自何处以及您究竟想将什么变成生成器。
player.get_serialized_data()返回一个没有太多数据的三元组,所以这没有多大意义,所以我觉得你想把_players.values()变成一个生成器,但你根本没有显示_players是什么。所以我不知道我们应该如何帮助你。 -
5000 名玩家并不多,但请记住,英雄的数量是相同的,每个英雄都有 4-15 种技能。那是约 100,000 件物品。数据 确实 已经存在,因此它已经在 RAM 中,但如果可能的话,我仍然希望避免使用这些列表。正如我所说,我想将当前的
players_data、heroes_data和skills_data变成生成器。它们目前是列表。
标签: python python-3.x generator