用一局太空侵略者看懂 SQLAlchemy ORM:多态继承与 joinedload 预加载实战

发布时间:2026/11/4 1:47:49
用一局太空侵略者看懂 SQLAlchemy ORM:多态继承与 joinedload 预加载实战 用一局太空侵略者看懂 SQLAlchemy ORM多态继承与 joinedload 预加载实战【免费下载链接】sqlalchemyThe Database Toolkit for Python项目地址: https://gitcode.com/gh_mirrors/sq/sqlalchemySQLAlchemy ORM 常被当成 CRUD 脚手架但仓库里藏着一个比较深的例子一个用终端 curses 画出来的太空侵略者游戏运行状态、碰撞判断、动画刷新全部压在 ORM 之上。我们以它为例倒推三件事——如何用一张表装下多种敌人、如何把碰撞检测写成一条 SQL以及为什么一个joinedload能救回一批查询。先跑起来500 行终端射击游戏背后例子在 space_invaders.py 里单文件、无第三方依赖跑起来就是一局可玩的射击游戏。建库和建表只用了四行e create_engine(sqlite://) Base.metadata.create_all(e) session Session(e) init_glyph(session) session.commit()sqlite://是纯内存库create_all一次建完所有表之后对象都挂在同一个Session上。游戏每 10ms 刷新一次而每帧场上有什么都是从数据库查出来的——这正是它作为 ORM 案例的意义所在。单表多态一张 glyph 表装下所有敌人游戏里有军队、UFO、玩家船、导弹、爆炸、提示文字类型很多ORM 却用单表继承把它们塞进同一张glyph表。polymorphic_on 就是类型判别列class Glyph(Base): __tablename__ glyph id Column(Integer, primary_keyTrue) type Column(String) __mapper_args__ {polymorphic_on: type} class ArmyGlyph(EnemyGlyph): __mapper_args__ {polymorphic_identity: army} class GlyphCoordinate(Base): __tablename__ glyph_coordinate glyph_id Column(Integer, ForeignKey(glyph.id)) x Column(Integer) y Column(Integer) glyph relationship(Glyph, innerjoinTrue)polymorphic_on指定type列作判别列polymorphic_identity给每个子类一个字符串标签。查出来时 ORM 按type的值把行还原成正确的子类ArmyGlyph、SaucerGlyph各自带上自己的方法。更多规则见 inheritance.rst。把碰撞检测写进 SQLof_type 与 hybrid_method常规做法是把坐标加载进内存用 Python 逐个判断矩形是否相交。这里反了过来让数据库来做几何判断。intersects 把判断下推到数据库hybrid_method def intersects(self, other): return ~( (self.x self.width other.x) | (self.x other.x other.width) ) ~( (self.y self.height other.y) | (self.y other.y other.height) )hybrid_method让它在 Python 端和 SQL 端都能用于是判负逻辑可以整段下推def check_lose(session, state): player state[player] return ( session.query(GlyphCoordinate) .join(GlyphCoordinate.glyph.of_type(ArmyGlyph)) .filter( GlyphCoordinate.intersects(player) | GlyphCoordinate.bottom_bound ) .count() )of_type(ArmyGlyph)把继承查询收窄到军队这一支再配合intersects生成一条带几何条件的COUNT命中即判负。一次往返没有把全部坐标拉回内存。调优joinedload 如何救你的 N1渲染阶段如果不用预加载每访问一次gcoord.glyph就多发一条查询十几个敌人就是十几条额外往返。joinedload 一次 JOIN 取回关联def draw(session, window, state): for gcoord in session.query(GlyphCoordinate).options( joinedload(GlyphCoordinate.glyph) ): gcoord.render(window, state)joinedload让glyph_coordinate与glyph一次 JOIN 取回把 N1 压回单条 SQL。策略取舍可参考 loading_relationships.rst。对这种小结果集、高频刷新的场景joinedload基本是默认最优解行数极大时再换subqueryload/selectinload。下一步想继续拆可以顺着 space_invaders.py 看move_army如何用func.min/func.max算出军队边界并整体平移或把单表继承换成 joined-table对比多出来的 JOIN。这个例子的价值在于它把多态、hybrid、预加载几件事压缩进了一个能跑、能玩、能看 SQL 的闭环里。【免费下载链接】sqlalchemyThe Database Toolkit for Python项目地址: https://gitcode.com/gh_mirrors/sq/sqlalchemy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询