Loading... <blockquote>在本博客中,ansible是一个系列文章,我们会尽量以通俗易懂的方式总结ansible的相关知识点。 ansible系列博文直达链接:<a href="https://www.zsythink.net/archives/tag/ansible/" target="_blank" rel="noopener">ansible轻松入门系列</a> “ansible系列”中的每篇文章都建立在前文的基础之上,所以,请按照顺序阅读这些文章,否则有可能在阅读中遇到障碍。 </blockquote> <h2>转义的一些操作</h2> 前文中我们已经总结了jinja2模板的一些基础用法,比如,变量和表达式被包含在”{{ }}”中,控制语句被包含在”{% %}”, 注释被包含在”{# #}”中,也就是说,在模板文件中,一旦遇到”{{ }}”、”{% %}”或者”{# #}”,jinja2模板引擎就会进行相应的处理,最终生成的文件内容中并不会包含”{{ }}”或者”{% %}”这些字符,但是如果,最终生成的文件中就是需要有”{{ }}”这一类的字符,该怎么办呢?有如下几种方法。 最简单的方法就是直接在”{{ }}”中使用引号将这类符号引起,当做纯粹的字符串进行处理,示例模板内容如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-c0"># cat test.j2</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-s0">'{{'</span> <span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-s0">'}}'</span> <span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-s0">'{{ test string }}'</span> <span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-s0">'{% test string %}'</span> <span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-s0">'{# test string #}'</span> <span class="enlighter-g1">}}</span></div> </div> </div> </div> 上述模板最终生成的内容如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-c0"># cat test</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span></div> </div> <div class=""> <div><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text"> test string </span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% test string %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-c0">{# test string #}</span></div> </div> </div> </div> 但是如果有较多这样的符号都需要保持原样(不被jinja2解析),那么使用上述方法可能比较麻烦,因为行多量大,大段的符号需要注意就比较烦人,所以,如果有较大的段落时,可以借助”{% raw %}”块,来实现刚才的需求,示例如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-c0"># cat test.j2</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% raw %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text"> test </span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% test %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-c0">{# test #}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% </span><span class="enlighter-k1">if</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% </span><span class="enlighter-k1">for</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endraw %</span><span class="enlighter-g1">}</span></div> </div> </div> </div> 如上例所示,”{% raw %}”与”{% endraw %}”之间的所有”{{ }}”、”{% %}”或者”{# #}”都不会被jinja2解析,上例模板被渲染后,raw块中的符号都会保持原样,最终生成内容如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-c0"># cat test</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text"> test </span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% test %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-c0">{# test #}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% </span><span class="enlighter-k1">if</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% </span><span class="enlighter-k1">for</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> </div> </div> 默认情况下,变量和表达式被包含在”{{ }}”中,控制语句被包含在”{% %}”,其实,我们也可以在调用模板引擎时,手动的指定一些符号,这些符号可以替换默认的”{{ }}”和”{% %}”,当我们在ansible中调用templdate模块时,可以使用variable_start_string参数指定一个符号,这个符号用于替换”{{ }}”中的”{{“,同时,可以使用variable_end_string参数指定一个符号,这个符号用于替换”{{ }}”中的”}}”,示例如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-c0"># cat test.j2</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% set test=</span><span class="enlighter-s0">'abc'</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">((</span><span class="enlighter-text"> test </span><span class="enlighter-g1">))</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text"> test </span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text"> test1 </span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-s0">'test'</span> <span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-s0">'test1'</span> <span class="enlighter-g1">}}</span></div> </div> </div> </div> 上述内容为示例模板的内容,当我们调用templdate模块时,执行如下命令,注意,如下命令表示使用”((“代替”{{“,使用”))”代替”}}”。 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-c0"># ansible test70 -m template -a "src=test.j2 dest=/opt/test variable_start_string='((' variable_end_string='))'"</span></div> </div> </div> </div> 执行上述命令后,最终生成的文件内容如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-c0"># cat test</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-text">abc</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text"> test </span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text"> test1 </span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-s0">'test'</span> <span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-s0">'test1'</span> <span class="enlighter-g1">}}</span></div> </div> </div> </div> 如你所见,当我们使用了指定的符号替换了默认的”{{ }}”之后,”{{ }}”字符将会保持原样,”{{ }}”中的内容也不会再被jinja2模板引擎解析,我们指定的符号为”(( ))”,所以,jinja2引擎在遇到”(( ))”符号时,才会进行对应的解析渲染。 同理,我们可以使用block_start_string参数指定一个符号,这个符号用于替换”{% %}”中的”{% ” 可以使用block_end_string参数指定一个符号,这个符号用于替换”{% %}”中的”%}” 刚才提到的这几个参数在2.4以及之后版本的ansible中可用。 如果你想要生成的文件通篇都是”{{ }}”和”{% %}”这种符号,只有个别地方需要用到模板引擎的表达式和控制语句,那么不如直接使用刚才提到的参数,使用指定的符号将默认的符号替代,替代后,”{{ }}”或”{% %}”都会保持原样,不会被解析。 <h2>宏相关总结</h2> jinja2中也有类似函数的东西,它叫做”宏”,利用宏,我们可以方便快捷的重复的利用一段内容,并且把这段内容当做一个独立的逻辑单元,与其他语言中的函数一样,jinja2的宏也可以传入参数,先来看一个最简单的宏,示例模板如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-c0"># cat test.j2</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">()</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-m0">testfunc</span><span class="enlighter-g1">()</span> <span class="enlighter-g1">}}</span></div> </div> </div> </div> 如上例所示,定义宏时需要使用”{% macro %}”开头,使用”{% endmacro %}”结束,上例中,我定义了一个名为testfunc的宏,与大多数语言中的函数一样,宏的括号中可以传入参数,但是上例的宏中并没有定义任何参数,testfunc中的内容没有什么意义,只是用于示例宏的用法,”{% macro %}”和”{% endmacro %}”之间的内容只是用来定义宏,如果想要真正的使用宏,还需要引用它,上例的最后一行就是在调用testfunc宏。 看完最简单的宏,再来看一个传参的宏,示例如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-c0"># cat test.j2</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% set testvar1=</span><span class="enlighter-s0">'teststr1'</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% set testvar2=</span><span class="enlighter-n1">2</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span><span class="enlighter-text">tv1,tv2</span><span class="enlighter-g1">)</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv1</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv2</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span><span class="enlighter-text">testvar1,testvar2</span><span class="enlighter-g1">)</span> <span class="enlighter-g1">}}</span></div> </div> </div> </div> 如上例所示,我们在定义宏时,定义了两个参数,然后 在调用宏时,传入了提前定义好的testvar1变量和testvar2变量,但是上述示例有一个很明显的问题,就是如果宏在定义的时候有对应的参数,在调用宏时就必须传入对应的参数,否则就会报错,其实,我们还可以在定义宏时,为对应的参数指定一个默认值,当在调用宏时没有显式的指定对应的参数时,宏就使用参数的默认值,示例模板如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span><span class="enlighter-text">tv1=</span><span class="enlighter-n1">111</span><span class="enlighter-g1">)</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv1</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span> <span class="enlighter-g1">)</span> <span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span><span class="enlighter-n1">666</span><span class="enlighter-g1">)</span> <span class="enlighter-g1">}}</span></div> </div> </div> </div> 渲染结果如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-n1">111</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-n1">666</span></div> </div> </div> </div> 如上例所示,我们在定义宏时,为tv1参数定义了默认值111,然后调用了两次testfunc宏,第一次没有传入对应参数,使用了默认值,第二次调用宏时传入了对应参数,于是使用了传入的值 注意,当有多个参数时,如果并不是所有参数都有默认值,那么没有默认值的参数必须在有默认值的参数之前,否则会出现错误,这一点与python中的函数传参时的注意点是一样的,下例中对错误的用法进行了示例。 下例是一个错误示例,下例的宏中定义了三个参数,tv1和tv3有默认值,但是tv2没有,这样就是错误的,因为tv2参数没有设置默认值,但是它的前面却有一个定义了默认值的参数,如下模板虽然能够渲染成功,但是得到的结果却是错误的 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span><span class="enlighter-text">tv1=</span><span class="enlighter-n1">1</span><span class="enlighter-text">,tv2,tv3=</span><span class="enlighter-n1">3</span><span class="enlighter-g1">)</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv1</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv2</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv3</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span> <span class="enlighter-s0">'a'</span> <span class="enlighter-g1">)</span> <span class="enlighter-g1">}}</span></div> </div> </div> </div> 上述错误示例渲染后的结果如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-text"> a</span></div> </div> <div class=""> <div><span class="enlighter-n1">1</span></div> </div> <div class=""> <div><span class="enlighter-n1">3</span></div> </div> </div> </div> 上述结果与我们预期的正确结果并不相同,所以我们应该避免这种情况发生。 如下写法是正确的,因为所有没有默认值的参数在有默认值的参数之前 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span><span class="enlighter-text">tv1,tv2,tv3=</span><span class="enlighter-n1">3</span><span class="enlighter-text">,tv4=</span><span class="enlighter-n1">4</span><span class="enlighter-g1">)</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv1</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv2</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv3</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv4</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span> <span class="enlighter-s0">'aa'</span><span class="enlighter-text">,</span><span class="enlighter-s0">'a'</span> <span class="enlighter-g1">)</span> <span class="enlighter-g1">}}</span></div> </div> </div> </div> 渲染上述模板结果如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-text"> aa</span></div> </div> <div class=""> <div><span class="enlighter-text"> a</span></div> </div> <div class=""> <div><span class="enlighter-n1">3</span></div> </div> <div class=""> <div><span class="enlighter-n1">4</span></div> </div> </div> </div> 如你所见,调用宏时传入的值会按照顺序与没有默认值的参数进行对应。 在传入参数时,也可以显式的指明参数的名称,示例如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span><span class="enlighter-text">tv1,tv2=</span><span class="enlighter-n1">2</span><span class="enlighter-text">,tv3=</span><span class="enlighter-n1">3</span><span class="enlighter-g1">)</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv1</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv2</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv3</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span> <span class="enlighter-n1">111</span><span class="enlighter-text">,tv3=</span><span class="enlighter-s0">'ccc'</span> <span class="enlighter-g1">)</span> <span class="enlighter-g1">}}</span></div> </div> </div> </div> 如上例所示,在调用宏时,传入了两个参数 ,第一个参数与没有默认值的tv1对应,第二个参数指明了参数名为tv3,表示设置tv3参数的值为’ccc’,由于没有传入针对tv2的值,所以tv2将会使用对应的默认值,上例渲染后内容如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-n1">111</span></div> </div> <div class=""> <div><span class="enlighter-n1">2</span></div> </div> <div class=""> <div><span class="enlighter-text"> ccc</span></div> </div> </div> </div> 显式的指定参数名可以帮助我们灵活的传入参数。 其实,在宏的内部,有三个默认的内置特殊变量可供我们使用,它们分别是varargs、kwargs、caller,它们的作用我们慢慢道来。 我们可以在调用宏时,多传入几个额外的参数,这些额外的参数会作为一个元组保存在varargs变量上,我们可以通过获取varargs变量的值获取到额外传入的参数,示例如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text">cat test.</span><span class="enlighter-m3">j2</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span><span class="enlighter-text">testarg1=</span><span class="enlighter-n1">1</span><span class="enlighter-text">,testarg2=</span><span class="enlighter-n1">2</span><span class="enlighter-g1">)</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">testarg1</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">testarg2</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">varargs</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span><span class="enlighter-s0">'a'</span><span class="enlighter-text">,</span><span class="enlighter-s0">'b'</span><span class="enlighter-text">,</span><span class="enlighter-s0">'c'</span><span class="enlighter-text">,</span><span class="enlighter-s0">'d'</span><span class="enlighter-text">,</span><span class="enlighter-s0">'e'</span><span class="enlighter-g1">)</span> <span class="enlighter-g1">}}</span></div> </div> </div> </div> 上例中我们只定义了两个参数,但是在调用宏时,我们传入了5个参数,而在宏里面,我们输出了内置变量varargs,最终渲染后的效果如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-text"> a</span></div> </div> <div class=""> <div><span class="enlighter-m0">b</span></div> </div> <div class=""> <div><span class="enlighter-g1">(</span><span class="enlighter-s0">'c'</span><span class="enlighter-text">, </span><span class="enlighter-s0">'d'</span><span class="enlighter-text">, </span><span class="enlighter-s0">'e'</span><span class="enlighter-g1">)</span></div> </div> </div> </div> 既然varargs变量里面存储了多余的参数,那么如果宏压根就没有定义任何参数,我们却传入了一些参数,那么这些所有传入的参数都是“多余”出的参数,也可以使用varargs变量处理这些参数,示例如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">()</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">%</span><span class="enlighter-k1">for</span><span class="enlighter-text"> i </span><span class="enlighter-k1">in</span><span class="enlighter-text"> varargs%</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">i</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">%endfor%</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-s0">'--------'</span> <span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-m0">testfunc</span><span class="enlighter-g1">()</span> <span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span><span class="enlighter-n1">1</span><span class="enlighter-text">,</span><span class="enlighter-n1">2</span><span class="enlighter-text">,</span><span class="enlighter-n1">3</span><span class="enlighter-g1">)</span> <span class="enlighter-g1">}}</span></div> </div> </div> </div> 如上例所示,定义宏时,并没有定义任何参数,但是在使用宏时,可以传入任意个数的参数,或者不传任何参数,这种使用方式类似于python中的可变参数,上例的最终渲染效果如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-text"> --------</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-n1">1</span></div> </div> <div class=""> <div><span class="enlighter-n1">2</span></div> </div> <div class=""> <div><span class="enlighter-n1">3</span></div> </div> <div class=""> <div><span class="enlighter-text"> --------</span></div> </div> </div> </div> 聊完内置变量varargs,再来聊聊变量kwargs,kwargs变量与varargs变量的作用很像,但是kwargs变量只是针对’关键字参数’而言的,而varargs变量是针对’非关键字参数’而言的,看了如下示例你就会明白了 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span><span class="enlighter-text">tv1=</span><span class="enlighter-s0">'tv1'</span><span class="enlighter-g1">)</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">varargs</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">kwargs</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span> <span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span><span class="enlighter-s0">'a'</span><span class="enlighter-text">,</span><span class="enlighter-n1">2</span><span class="enlighter-text">,</span><span class="enlighter-s0">'test'</span><span class="enlighter-text">,testkeyvar=</span><span class="enlighter-s0">'abc'</span><span class="enlighter-g1">)</span> <span class="enlighter-g1">}}</span></div> </div> </div> </div> 如上例所示,我们在定义宏时,定义了一个参数tv1,并且设置了默认值,在宏中,我们输出了varargs变量和kwargs变量,在调用宏时,我们多传入了3个参数,最后一个参数是一个带有参数名的关键字参数,那么渲染上述模板,内容如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-text"> test </span><span class="enlighter-m0">string</span></div> </div> <div class=""> <div><span class="enlighter-g1">(</span><span class="enlighter-n1">2</span><span class="enlighter-text">, </span><span class="enlighter-s0">'test'</span><span class="enlighter-g1">)</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-s0">'testkeyvar'</span><span class="enlighter-text">: </span><span class="enlighter-s0">'abc'</span><span class="enlighter-g1">}</span></div> </div> </div> </div> 如上所示,多余的非关键字参数都会保存在varargs变量中,varargs变量的结构是一个元组,而多余的关键字参数都会保存在kwargs变量中,kwargs变量的结构是一个字典,kwargs变量实现的效果与Python的关键字参数效果类似。 了解了varargs变量和kwargs变量,现在来说说caller变量。 与其说是caller变量,不如称其为caller函数或者caller方法,caller可以帮助我们将宏中的内容进行替换,这样描述可能不太容易理解,不如先来看一个小例子: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">()</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-m0">caller</span><span class="enlighter-g1">()}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> </div> </div> 如上例所示,我们定义了一个testfunc宏,在testfunc宏中,”{{caller()}}”部分可以被”其他内容”替换,但是此刻,我们还没有调用testfunc宏,如果想要替换testfunc宏中的”{{caller()}}”部分,则需要在调用testfunc宏时,使用”call语句块”进行调用,示例如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">()</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-m0">caller</span><span class="enlighter-g1">()}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">%call </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">()</span><span class="enlighter-text">%</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text">something~~~~~</span></div> </div> <div class=""> <div><span class="enlighter-text">something </span><span class="enlighter-k1">else</span><span class="enlighter-text">~~~~~</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">%endcall%</span><span class="enlighter-g1">}</span></div> </div> </div> </div> 如上例所示,我们使用了”{%call%}”语句块调用了testfunc宏,”{%call%}”和”{%endcall%}”之间的内容将会替换testfunc宏中的”{{caller()}}”部分,上例模板最终渲染效果如下 <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-text"> something~~~~~</span></div> </div> <div class=""> <div><span class="enlighter-text">something </span><span class="enlighter-k1">else</span><span class="enlighter-text">~~~~~</span></div> </div> </div> </div> 是不是觉得跟传参数的效果一模一样,就像传了一个参数给testfunc宏一样,当我们要传入大段内容或者复杂的内容时,可以借助caller进行传递,当然,上例只是 为了让你能够更加直观的了解caller的用法,caller其实还能够帮助我们在一个宏中调用另一个宏,示例如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">()</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-m0">caller</span><span class="enlighter-g1">()}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc1</span><span class="enlighter-g1">()</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% </span><span class="enlighter-k1">for</span><span class="enlighter-text"> i </span><span class="enlighter-k1">in</span> <span class="enlighter-m0">range</span><span class="enlighter-g1">(</span><span class="enlighter-n1">3</span><span class="enlighter-g1">)</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">i</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endfor %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">%call </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">()</span><span class="enlighter-text">%</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-m0">testfunc1</span><span class="enlighter-g1">()}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">%endcall%</span><span class="enlighter-g1">}</span></div> </div> </div> </div> 如上例所示,我们定义了两个宏,testfunc和testfunc1,我们将testfunc1传递到了testfunc中。 其实,”caller()”也可以接收参数,只要在call块中提前定义好,在caller中传入参数即可,示例如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">()</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-m0">caller</span><span class="enlighter-g1">(</span><span class="enlighter-s0">'somethingElse~~'</span><span class="enlighter-g1">)}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">%</span><span class="enlighter-m0">call</span><span class="enlighter-g1">(</span><span class="enlighter-text">testvar</span><span class="enlighter-g1">)</span> <span class="enlighter-m0">testfunc</span><span class="enlighter-g1">()</span><span class="enlighter-text">%</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text">something~~~~</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">testvar</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">%endcall%</span><span class="enlighter-g1">}</span></div> </div> </div> </div> 如上例所示,call块中定义了testvar参数,call块中的内容使用了testvar参数,在testfunc宏中的调用caller时,传入了一个字符串作为参数,上例最终的渲染的效果如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-text"> something~~~~</span></div> </div> <div class=""> <div><span class="enlighter-text">somethingElse~~</span></div> </div> </div> </div> 当testfunc中的某些内容需要循环的进行替换时,这种方法非常有效。 除了varargs、kwargs、caller这些内部变量,宏还有一些属性可以使用。 可用的宏属性如下,此处先对这些属性进行描述,之后会进行示例: <strong>name属性</strong>:宏的名称。 <strong>arguments属性</strong>:宏中定义的所有参数的参数名,这些参数名组成了一个元组存放在arguments中。 <strong>defaults属性</strong>:宏中定义的参数如果有默认值,这些默认值组成了一个元组存放在defaults中。 <strong>catch_varargs属性</strong>:如果宏中使用了varargs变量,此属性的值为true。 <strong>catch_kwargs属性</strong>: 如果宏中使用了kwargs变量,此属性的值为true。 <strong>caller属性</strong>:如果宏中使用了caller变量,此属性值为true。 上述宏属性的使用示例如下,可以对比着渲染后的结果查看: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-c0"># cat test.j2</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc</span><span class="enlighter-g1">(</span><span class="enlighter-text">tv1,tv2,tv3=</span><span class="enlighter-n1">3</span><span class="enlighter-text">,tv4=</span><span class="enlighter-n1">4</span><span class="enlighter-g1">)</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv1</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv2</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv3</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv4</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">testfunc.</span><span class="enlighter-m3">name</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">testfunc.</span><span class="enlighter-m3">arguments</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">testfunc.</span><span class="enlighter-m3">defaults</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">testfunc.</span><span class="enlighter-m3">catch_varargs</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">testfunc.</span><span class="enlighter-m3">catch_kwargs</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">testfunc.</span><span class="enlighter-m3">caller</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-s0">'################################'</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc1</span><span class="enlighter-g1">(</span><span class="enlighter-text">tv1=</span><span class="enlighter-s0">'a'</span><span class="enlighter-text">,tv2=</span><span class="enlighter-s0">'b'</span><span class="enlighter-g1">)</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv1</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">tv2</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">varargs</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">kwargs</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">testfunc1.</span><span class="enlighter-m3">catch_varargs</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">testfunc1.</span><span class="enlighter-m3">catch_kwargs</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">testfunc1.</span><span class="enlighter-m3">caller</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-s0">'################################'</span><span class="enlighter-g1">}}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% macro </span><span class="enlighter-m0">testfunc2</span><span class="enlighter-g1">()</span><span class="enlighter-text"> %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div><span class="enlighter-text"> test string</span></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-m0">caller</span><span class="enlighter-g1">()}}</span></div> </div> <div class=""> <div><span class="enlighter-g1">{</span><span class="enlighter-text">% endmacro %</span><span class="enlighter-g1">}</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-g1">{{</span><span class="enlighter-text">testfunc2.</span><span class="enlighter-m3">caller</span><span class="enlighter-g1">}}</span></div> </div> </div> </div> 如你所见,我并没有调用宏,但是可以直接使用宏的属性,上例模板内容渲染后的结果如下: <div class="enlighter-default enlighter-v-standard enlighter-t-enlighter enlighter-hover enlighter-overflow-scroll"> <div class="enlighter-toolbar"> <div class="enlighter-btn enlighter-btn-raw"></div> <div class="enlighter-btn enlighter-btn-copy"></div> <div class="enlighter-btn enlighter-btn-window"></div> </div> <div class="enlighter"> <div class=""> <div><span class="enlighter-m0">testfunc</span></div> </div> <div class=""> <div><span class="enlighter-g1">(</span><span class="enlighter-s0">'tv1'</span><span class="enlighter-text">, </span><span class="enlighter-s0">'tv2'</span><span class="enlighter-text">, </span><span class="enlighter-s0">'tv3'</span><span class="enlighter-text">, </span><span class="enlighter-s0">'tv4'</span><span class="enlighter-g1">)</span></div> </div> <div class=""> <div><span class="enlighter-g1">(</span><span class="enlighter-n1">3</span><span class="enlighter-text">, </span><span class="enlighter-n1">4</span><span class="enlighter-g1">)</span></div> </div> <div class=""> <div><span class="enlighter-k1">False</span></div> </div> <div class=""> <div><span class="enlighter-k1">False</span></div> </div> <div class=""> <div><span class="enlighter-k1">False</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-c0">################################</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-k1">True</span></div> </div> <div class=""> <div><span class="enlighter-k1">True</span></div> </div> <div class=""> <div><span class="enlighter-k1">False</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-c0">################################</span></div> </div> <div class=""> <div></div> </div> <div class=""> <div></div> </div> <div class=""> <div><span class="enlighter-text"> True</span></div> </div> </div> </div> 这篇文章就先 总结到这里,希望可以对你有所帮助~~ 转载自朱双印日志https://www.zsythink.net/archives/3037 Last modification:May 29, 2024 © Allow specification reprint Like 如果觉得我的文章对你有用,请随意赞赏