您的位置:首页 > 编程语言 > Python开发

Mako 模板系统文档翻译(3) 函数定义

2007-06-15 16:17 363 查看
翻译:木野狐 http://rchen.cnblogs.com/原文:http://www.makotemplates.org/docs/defs.html译文:Version: 0.1.5 Last Updated: 05/01/07 20:21:35上一节: 语法 | 下一节: 运行时环境

Table of Contents

DefsCalling defs from Other FilesDefs within DefsCalling a def with embedded content and/or other defs

Defs

def 是一个简单的标签,用于给任意文本块或代码块定界。它在模板最终生成的 Python 代码里是一个可调用的函数。
hello world
通常我们可以通过表达式来调用它们:
the def:  hello()
如果 <%def> 没有嵌套定义在另一个 <%def> 中,则称为顶层的 def, 它可以在模板的任何地方被使用,甚至可以在定义它的位置之前。所有的 defs, 不管是不是顶层的,都可以访问当前的上下文名称空间,和模板的访问权限完全一样。设想下列模板在执行时被指定了一个包含 username 和 accountdata 变量的上下文:
Hello there username, how are ya.  Lets see what your account says:

account()

Account for username:

row  accountdata:
Value: row
username 和 accountdata 两个变量将会显示在主模板的 body 中,同样也会显示在 account() def 的 body 中。既然 defs 不过就是 python 函数,你自然也能够定义和传递参数了:
account(accountname)

account name: accountname, type
当你为 def 定义参数时,他们需要遵从 Python 的规定(比如,除了提供了默认值的关键字参数之外的所有参数,都需要提供)。这和上下文层次的变量不同,后者对不存在的名称会估算为 UNDEFINED 而不是出错。

从其他文件调用 defs

顶层的 <%defs> 被编译到模板对应的模块中,并且可以被从外部调用;包括从其他模板,或是普通的 Python 代码来调用。从其他模板中调用 <%def> 有点像使用 <%include> —— 差别在于,你是在调用模板中的一个函数,而不是整个模板。远程的 <%def> 调用也有点类似于 Python 中调用另一个模块中的函数的情形。需要有一个“导入”的步骤,以便从其他模板中萃取出名称,添加到你自己的模板中;然后这些名称的函数才可以被调用。要导入另一个模板,使用 <%namespace> 标签:
上面的标签添加了一个局部变量 "mystuff" 到当前范围中。然后,只要调用 mystuff 中的函数即可:
mystuffsomedef(x,y)
<%namespace> 标签还支持类似 Python import 语句的一些其他的语义,包括将名称提取到局部变量空间中,或使用 * 来代表所有名称,使用 import 属性:
这里只是对名称空间的概念做了一个简单的介绍,名称空间是 Mako 的一个核心概念,在文档中有独立的章节介绍。更多的细节和例子,见 Namespaces

Defs 中的 Defs

def 模型遵循 Python 中关于闭包的一些规则。在一个 <%def> 中定义另一个 <%def>,会将它定义在父 def 的外围环境(enclosing scope) 中:
a sub defim the def, and the subcomopnent is subdef()
就象 Python 中一样,定义在内嵌 <%def> 之外的名称,在其内部一样存在:
xyinner, x is x, y is youter, x is x, y is y
在 def 内的赋值语句会创建一个 def 范围内的局部变量(再一次的和 Python 自身语法吻合)。比如下面的代码就会引发错误:
x# error !somedef, x is xx
...因为对 x 的赋值将 x 定义为了 somedef 范围内的局部变量,而试图输出“外部”版本的 x 是访问不到的。

调用方自带内容或内嵌函数的方式调用 def

def 的另一个方面是它可以带内容的进行调用。也就是,当你调用 def 时,同时定义一个块的内容(或多个块),这些块将提供给你要调用的 def. 这种调用方式的主要目的是为了创建自定义的,可嵌套的标签,就象其他模板语言的自定义标签生成系统 —— 外部的标签控制内嵌标签的执行,并且可以和它们沟通状态信息。只有在 Mako 中,你才不需要使用任何外部的 Python 模块,你可以直接在你的模板中定义可任意内嵌的标签。为了达到这个目标,需要通过 <%call> 标签而不是常规的 ${} 语法来调用目标 def. 这样,目标 def 就会在其上下文中获得一个 caller 变量,其中包含一个名称空间,在此名称空间中包含了调用者的内容部分(body), 以及 <%call> 标签中定义的其他 defs. 而调用者的内容(body) 可通过 body() 方法来取得:
callerbody()I am the table body.
这会产生下列输出 (空白已格式化):
I am the table body.
body() 可以被执行多次,或根本不执行。这意味着你可以使用带内容的 def 调用(def-call-with-content)来创建迭代器(iterators),条件语句等:
x  (,count):callerbody()hi
输出:
hihihi
一个自定义的“条件”标签:
expr:callerbody()im the result
输出:
im the result
但还有更精彩的。body() 函数还可以传递参数:
item  somedata:col  item:callerbody(colcol)Body data: col
输出(空白以格式化):[译注:似乎有误!应该是3行3列表格]
Body data: 1Body data: 2Body data: 3Body data: 4Body data: 5Body data: 6Body data: 7Body data: 8Body data: 9
你不用仅盯着调用 body() 函数,在调用方可以定义任意多个 callables,使得 <%call> 标签可定制所有布局:
# a layout defcallerheader()callersidebar()callerbody()# calls the layout defI am the headersidebar 1sidebar 2this is the body
上述代码会输出(空白已格式化):
I am the headersidebar 1sidebar 2this is the body
利用 <%call> 你可以做很多事情。可以创建表单控件库(form widget libraries),比如一个自包含的 <form> 标签,以及一组内嵌的 HTML input 元素,或者用 <div> 或其他元素创建可移植的包装控件,你可以创建标签来解释数据行,比如从数据库中得到的数据,然后将行的每一列传递给 body() 的一个可调用函数,这样就可以对数据行进行任何你想要的排版。基本上,你在其他系统中通过“自定义标签”或标签库想做的事情,Mako 中都可以通过 <%def> 或通过用 <%call> 调用 Python 函数的方式来实现。上一节: 语法 | 下一节: 运行时环境 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息