You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jinja2模板中set修改变量为何无法在循环后续持久生效?

Jinja2循环内变量重置问题分析与解决

问题根源

你遇到的问题是Jinja2的作用域规则导致的:

  • 循环外定义的has_swimming = 0属于全局作用域变量
  • 在循环内执行{% set has_swimming = 1 %}时,Jinja2会创建一个当前循环迭代的局部变量,这个变量只在本次迭代生效,下一次循环时局部变量被销毁,程序会重新引用全局的has_swimming=0,所以每次循环都相当于把变量重置回初始值,这才导致第二个SWIMMING条目又触发了find swim。

解决方法

因为你已经启用了jinja2.ext.do扩展,这里提供两种简单可行的方案:

方案1:用Namespace对象存储状态(推荐)

Jinja2的namespace是可变对象,其属性可以在循环内修改并保留状态,写法更直观:
修改模板部分代码如下:

{% set ns = namespace(has_swimming=0) %}

{% for row in Class['Students'] %}
{% set name = row['name'] -%}
{% set hobby = row['hobby'] %}
    {% if hobby == 'SWIMMING' and ns.has_swimming == 0 %}
        {% set ns.has_swimming = 1 %}
find swim=============
    {% endif %}
name is {{name}}, hobby is {{hobby}}
    {% if hobby != 'SWIMMING' and ns.has_swimming == 1 %}
        {% set ns.has_swimming = 0 %}
end===============
    {% endif %}
{% endfor %}

{% if ns.has_swimming == 1%}
end===============
{% endif %}

方案2:用可变列表存储状态

利用列表是可变类型的特性,修改列表元素来保留状态:

{% set has_swimming = [0] %}

{% for row in Class['Students'] %}
{% set name = row['name'] -%}
{% set hobby = row['hobby'] %}
    {% if hobby == 'SWIMMING' and has_swimming[0] == 0 %}
        {% do has_swimming.__setitem__(0, 1) %}
find swim=============
    {% endif %}
name is {{name}}, hobby is {{hobby}}
    {% if hobby != 'SWIMMING' and has_swimming[0] == 1 %}
        {% do has_swimming.__setitem__(0, 0) %}
end===============
    {% endif %}
{% endfor %}

{% if has_swimming[0] == 1%}
end===============
{% endif %}

验证结果

修改后运行代码,将得到你预期的输出:

name is CHOI, hobby is RUNNINg
name is KIM, hobby is RUNNINg
find swim=============
name is JEON, hobby is SWIMMING
name is YOON, hobby is SWIMMING
end===============

内容的提问来源于stack exchange,提问作者seonguk.jeon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 17:33:08