代碼翻譯模板-程序代碼翻譯模板
日期:2023-03-11 12:39:36 / 人氣: 542 / 發(fā)布者:成都翻譯公司
我們之前的程序主要是python代碼,有一些HTML代碼嵌入python邏輯中。既然我們用python來(lái)實(shí)現(xiàn)我們的模板引擎,一些python的概念會(huì)出現(xiàn)在我們的語(yǔ)法中。我們實(shí)現(xiàn)的引擎使用編譯方法:我們將模板編譯為python代碼。我們的引擎將編譯這個(gè)模板為python代碼。每個(gè)模板都被轉(zhuǎn)換為一個(gè)render_function函數(shù),其接受一個(gè)叫做context的數(shù)據(jù)字典。500行以內(nèi)是一系列非常經(jīng)典且相對(duì)較短的python文章。每章代碼不超過(guò)500行,但實(shí)現(xiàn)了一些強(qiáng)大的功能。是業(yè)內(nèi)大佬寫(xiě)的,有很大的學(xué)習(xí)價(jià)值。適合新手了解基本概念,也適合進(jìn)階python。
來(lái)源文章
源代碼
其他一些開(kāi)源翻譯文章
介紹
在一些編程任務(wù)中代碼模板翻譯,邏輯很少,但文本很多。對(duì)于這些任務(wù),我們希望有更好的工具來(lái)解決這些基于文本的問(wèn)題。模板引擎就是這樣一個(gè)工具。在本文中,我們構(gòu)建了一個(gè)簡(jiǎn)單的模板引擎。
Web 應(yīng)用程序是基于文本的任務(wù)的*常見(jiàn)示例。任何 Web 應(yīng)用程序中的一個(gè)重要階段是生成 HTML 并將其交付給瀏覽器。只有少數(shù) HTML 頁(yè)面是純靜態(tài)的,它們基本上至少包含少量動(dòng)態(tài)數(shù)據(jù),例如用戶名。通常它們包含更多動(dòng)態(tài)數(shù)據(jù):產(chǎn)品列表、來(lái)自朋友的新消息等。
同時(shí),每個(gè) HTML 頁(yè)面都包含大量靜態(tài)文本。而且這些頁(yè)面非常大,包含數(shù)萬(wàn)字節(jié)的文本。那么,Web 應(yīng)用程序開(kāi)發(fā)人員面臨一個(gè)問(wèn)題:如何生成大量的靜態(tài)和動(dòng)態(tài)數(shù)據(jù)是*好的?另外,靜態(tài)文本內(nèi)容其實(shí)是HTML標(biāo)記語(yǔ)言,由團(tuán)隊(duì)其他成員-前端設(shè)計(jì)師創(chuàng)建,這種生成方式*好讓他們熟悉。
為了說(shuō)明這一點(diǎn),我們假設(shè)我們想要生成這個(gè)極簡(jiǎn)的 HTML:
Welcome, Charlie!Products:Apple: $1.00Fig: $1.50Pomegranate: $3.25
在這里,用戶名將是動(dòng)態(tài)的代碼模板翻譯,產(chǎn)品的名稱和價(jià)格也將是動(dòng)態(tài)的。甚至產(chǎn)品數(shù)量也不固定,因?yàn)閹?kù)存在波動(dòng)。
生成 HTML 的一種方法是在我們的代碼中添加字符串常量,然后將它們與動(dòng)態(tài)數(shù)據(jù)組合以生成頁(yè)面。動(dòng)態(tài)數(shù)據(jù)將以某種形式的字符串替換插入。我們的一些動(dòng)態(tài)數(shù)據(jù)是重復(fù)的,比如我們的產(chǎn)品列表,這意味著我們有一批重復(fù)的 HTML 塊。所以我們單獨(dú)對(duì)待它,并與其他部分結(jié)合起來(lái)。
以上述方式生成的頁(yè)面將如下所示:
# The main HTML for the whole page. PAGE_HTML = """Welcome, {name}!Products:{products}""" # The HTML for each product displayed. PRODUCT_HTML = "{prodname}: {price}" def make_page(username, products): product_html = "" for prodname, price in products: product_html += PRODUCT_HTML.format( prodname=prodname, price=format_price(price)) html = PAGE_HTML.format(name=username, products=product_html) return html
它有效,但它給我們?cè)黾恿撕芏嗦闊?。HTML 代碼嵌入在應(yīng)用程序代碼中的多個(gè)字符串常量中。頁(yè)面的邏輯很不清楚,因?yàn)殪o態(tài)內(nèi)容被分成了幾塊。Python 代碼中丟失了有關(guān)如何格式化數(shù)據(jù)的詳細(xì)信息。為了修改HTML頁(yè)面,我們的前端工程師必須學(xué)會(huì)修改python代碼。如果頁(yè)面復(fù)雜十倍或一百倍,這種做法會(huì)讓人感到無(wú)所適從。
模板
使用模板生成 HTML 頁(yè)面是一種更好的方法。HTML 頁(yè)面是作為模板創(chuàng)建的,這意味著該文件主要是靜態(tài) HTML,其中嵌入了由特殊符號(hào)表示的動(dòng)態(tài)數(shù)據(jù)片段。上面的*小頁(yè)面變成了這樣的模板:
Welcome, {{user_name}}!Products:{% for product in product_list %}{{ product.name }}: {{ product.price|format_price }}{% endfor %}
此時(shí),重點(diǎn)是 HTML 文本,僅嵌入了一些邏輯結(jié)構(gòu)。將這種以文本為中心的方法與之前以邏輯為中心的代碼進(jìn)行比較。我們之前的程序主要是python代碼,python邏輯中嵌入了一些HTML代碼。在這里,它們中的大多數(shù)是靜態(tài) HTML 標(biāo)記語(yǔ)言。
模板的多靜態(tài)風(fēng)格與大多數(shù)編程語(yǔ)言的工作方式相反。例如,python 的大多數(shù)源文件都是可執(zhí)行代碼。如果您需要文字靜態(tài)文本,請(qǐng)將其嵌入到字符串中:
def hello(): print("Hello, world!") hello()
當(dāng)python讀取這個(gè)源文件時(shí),它的翻譯類似于def hello():這樣的語(yǔ)句就是一條要執(zhí)行的指令。print("Hello, world!") 中的雙引號(hào)表示文本只是文字。這是大多數(shù)編程語(yǔ)言的工作方式:動(dòng)態(tài)是中流砥柱,而指令中嵌入了少量靜態(tài)片段。靜態(tài)部分用引號(hào)標(biāo)記。
模板語(yǔ)言正好相反:它主要是靜態(tài)文字文本,同時(shí)使用特殊符號(hào)來(lái)表示可執(zhí)行文件的動(dòng)態(tài)部分。
Welcome, {{user_name}}!
此處的文本字面出現(xiàn)在生成的 HTML 頁(yè)面中。直到 {{}} 表示里面的內(nèi)容是動(dòng)態(tài)模式,里面的變量才會(huì)在輸出中被替換。
Python的"foo = {foo}!".format(foo=17)等字符串格式化函數(shù)是小語(yǔ)言的典型例子。這種語(yǔ)言用來(lái)按字面意思和要插入的數(shù)據(jù)創(chuàng)建文本。模板將這個(gè)想法擴(kuò)展到包括條件和循環(huán)結(jié)構(gòu),唯一的區(qū)別是擴(kuò)展的程度。
這些文件被稱為模板,因?yàn)樗鼈冇糜谏稍S多具有相似結(jié)構(gòu)和不同細(xì)節(jié)的頁(yè)面。
為了在我們的程序中使用 HTML 模板,我們需要一個(gè)模板引擎:一個(gè)接收參數(shù)作為靜態(tài)模板(包含頁(yè)面的結(jié)構(gòu)和靜態(tài)內(nèi)容)和動(dòng)態(tài)上下文(提供嵌入在模板中的動(dòng)態(tài)數(shù)據(jù))的函數(shù)。這個(gè)模板引擎結(jié)合了模板和上下文來(lái)生成一個(gè)純 HTML 字符串。模板引擎的任務(wù)是翻譯模板并用動(dòng)態(tài)數(shù)據(jù)替換動(dòng)態(tài)片段。
順便說(shuō)一下,模板引擎不是針對(duì) HTML 的,它可以用來(lái)生成任何文本結(jié)果。例如,它們還用于生成純文本電子郵件。但是它們通常在HTML中使用,偶爾會(huì)有一些HTML特有的功能,比如轉(zhuǎn)義(escaping),這使得在HTML中插入值成為可能,而不必?fù)?dān)心HTML中是否存在特殊字符。
支持的語(yǔ)法
模板引擎支持的語(yǔ)法不同。我們的模板語(yǔ)法基于流行的 Web 框架 Django。由于我們使用python來(lái)實(shí)現(xiàn)我們的模板引擎,所以我們的語(yǔ)法中會(huì)出現(xiàn)一些python的概念。我們已經(jīng)在本章頂部的簡(jiǎn)約模板中看到了部分語(yǔ)法。下面是我們將實(shí)現(xiàn)的語(yǔ)法的快速總結(jié)。
上下文中的數(shù)據(jù)使用雙花括號(hào)插入:
Welcome, {{user_name}}!
呈現(xiàn)模板時(shí),模板中可用的數(shù)據(jù)由上下文提供。以后再說(shuō)。
模板引擎通常使用簡(jiǎn)化和寬松的語(yǔ)法來(lái)提供對(duì)數(shù)據(jù)元素的訪問(wèn)。在python中,這些表達(dá)式有不同的效果:
dict["key"] obj.attr obj.method()
在我們的模板語(yǔ)法中,所有這些操作都用點(diǎn)表示:
dict.key obj.attr obj.method
點(diǎn)將訪問(wèn)對(duì)象的屬性或字典的值,如果結(jié)果值是可調(diào)用的,它將被自動(dòng)調(diào)用。這與 python 代碼不同,其中這些操作具有不同的語(yǔ)法。這導(dǎo)致了一個(gè)簡(jiǎn)單的模板語(yǔ)法:
The price is: {{product.price}}, with a {{product.discount}}% discount.
您還可以使用稱為過(guò)濾器的函數(shù)來(lái)修改值。過(guò)濾器由豎線(管道字符)調(diào)用:
Short name: {{story.subject|slugify|lower}}
如果條件語(yǔ)句可用,構(gòu)建一個(gè)有趣的網(wǎng)站通常至少需要一些決定:
{% if user.is_logged_in %}Welcome, {{ user.name }}!{% endif %}
循環(huán)讓我們?cè)陧?yè)面中包含一組數(shù)據(jù):
Products:{% for product in product_list %}{{ product.name }}: {{ product.price|format_price }}{% endfor %}
就像其他編程語(yǔ)言一樣,條件和循環(huán)語(yǔ)句可以嵌套以構(gòu)建復(fù)雜的邏輯結(jié)構(gòu)。
*后,讓我們將文檔添加到模板中,注釋出現(xiàn)在花括號(hào)和井號(hào)之間:
{# This is the best template ever! #}
執(zhí)行
模板引擎有兩個(gè)主要階段:解析模板,然后渲染模板。
渲染模板具體包括:
從解析階段傳遞到渲染階段的內(nèi)容是問(wèn)題的關(guān)鍵。解析為渲染產(chǎn)生什么?有兩個(gè)主要選項(xiàng),我們稱之為解釋和編譯,使用與其他語(yǔ)言實(shí)現(xiàn)相關(guān)的術(shù)語(yǔ)。
在解釋模型中,分析產(chǎn)生表示模板結(jié)構(gòu)的數(shù)據(jù)結(jié)構(gòu)。渲染階段遍歷該數(shù)據(jù)結(jié)構(gòu)并根據(jù)找到的指令組合結(jié)果文本。一個(gè)真實(shí)的例子是使用這種方法的 Django 模板引擎。
在編譯模型中,解析產(chǎn)生某種形式的直接可執(zhí)行代碼。代碼在渲染階段執(zhí)行,并產(chǎn)生結(jié)果。Jinja2 和 Mako 都是使用編譯方式的模板引擎。
我們實(shí)現(xiàn)的引擎采用的是編譯方式:我們將模板編譯成python代碼。執(zhí)行時(shí),代碼會(huì)組合結(jié)果。這里描述的模板引擎*初是作為coverage.py 的一部分編寫(xiě)的,用于生成HTML 報(bào)告。在coverage.py中,只有幾個(gè)模板,并且被反復(fù)使用,生成了很多文件。一般來(lái)說(shuō),如果將模板編譯成python代碼,程序運(yùn)行速度會(huì)更快,因?yàn)榧词咕幾g過(guò)程更復(fù)雜,也只需要運(yùn)行一次,編譯后的代碼執(zhí)行多次,這比解釋的要多得多一種數(shù)據(jù)結(jié)構(gòu)。快多了。
將模板編譯成 python 代碼有點(diǎn)復(fù)雜,但沒(méi)有你想象的那么糟糕。另外,寫(xiě)一個(gè)能寫(xiě)代碼的程序,比寫(xiě)程序本身有趣多了!我們的模板編譯器是代碼生成常用技術(shù)的一個(gè)小例子。代碼生成技術(shù)構(gòu)成了許多強(qiáng)大而靈活的工具的基礎(chǔ),包括編程語(yǔ)言編譯器。代碼生成可能會(huì)變得非常復(fù)雜,但它是一種值得擁有的有用技術(shù)。
如果模板一次只使用幾次,這樣的模板應(yīng)用程序可能傾向于解釋該方法。從長(zhǎng)遠(yuǎn)來(lái)看,將模板編譯成 python 代碼的成本要貴一些??偟膩?lái)說(shuō),更簡(jiǎn)單的解釋過(guò)程可能會(huì)更好。
編譯為 Python
在拿到模板引擎的代碼之前,我們先來(lái)看看它生成的代碼。解析階段將模板轉(zhuǎn)換為 Python 函數(shù)。再次使用我們的小模板:
Welcome, {{user_name}}!Products:{% for product in product_list %}{{ product.name }}: {{ product.price|format_price }}{% endfor %}
我們的引擎會(huì)將此模板編譯為 python 代碼。python 代碼的結(jié)果看起來(lái)不尋常,因?yàn)槲覀冞x擇了一些快捷方式來(lái)生成輕量級(jí)和更快的代碼。為了便于閱讀,以下 Python 代碼已稍微重新格式化:
def render_function(context, do_dots): c_user_name = context['user_name'] c_product_list = context['product_list'] c_format_price = context['format_price'] result = [] append_result = result.append extend_result = result.extend to_str = str extend_result([ 'Welcome, ', to_str(c_user_name), '!Products:' ]) for c_product in c_product_list: extend_result([ '', to_str(do_dots(c_product, 'name')), ': ', to_str(c_format_price(do_dots(c_product, 'price'))), '' ]) append_result('') return ''.join(result)
每個(gè)模板都被轉(zhuǎn)換成一個(gè) render_function 函數(shù),它接受一個(gè)名為 context 的數(shù)據(jù)字典。函數(shù)體首先將上下文字典中的數(shù)據(jù)解包為局部變量,因?yàn)橹貜?fù)使用數(shù)據(jù)會(huì)更快。所有的上下文數(shù)據(jù)都以加c_前綴的形式變成局部變量,這樣我們就可以自由地使用局部變量名而不必?fù)?dān)心命名沖突。
模板的結(jié)果將是一個(gè)字符串。從部分構(gòu)建字符串的*快方法是創(chuàng)建一個(gè)字符串列表,然后將它們組合在一起。結(jié)果是一個(gè)字符串列表。因?yàn)槲覀儗⑾蜻@個(gè)列表添加一個(gè)字符串,所以我們捕獲了它的 append 和 extend 方法并將其分配給局部變量 result_append 和 result_extend。創(chuàng)建的*后一個(gè)局部變量是內(nèi)置方法 str - to_str 的簡(jiǎn)寫(xiě)。
這些形式的快捷鍵很不尋常。讓我們更仔細(xì)地看:在python中,諸如result.append("hello")之類的對(duì)象調(diào)用的方法分兩步執(zhí)行。首先從result對(duì)象中獲取append屬性,然后將獲取到的值作為函數(shù)調(diào)用,傳遞參數(shù)“hello”給它。雖然我們習(xí)慣于看到這些步驟一起執(zhí)行,但它們實(shí)際上是分開(kāi)的。如果您存儲(chǔ)第一步的結(jié)果,那么您將對(duì)存儲(chǔ)的結(jié)果執(zhí)行第二步。所以下面的兩個(gè)代碼片段做同樣的事情:
# The way we're used to seeing it: result.append("hello") # But this works the same: append_result = result.append append_result("hello")
在模板引擎代碼中,我們采用了這種分離方式,這樣無(wú)論第二步做多少次,第一步都只需要做一次。這為我們節(jié)省了少量時(shí)間,因?yàn)樗苊饬嘶〞r(shí)間查找對(duì)象的 append 屬性。
這是微優(yōu)化的一個(gè)例子:一種不尋常的編碼技術(shù)使我們能夠獲得速度的小幅提升。微優(yōu)化可能會(huì)使代碼可讀性較差或更容易混淆,因此只有使用被證明是性能瓶頸的代碼才是合理的。開(kāi)發(fā)者對(duì)于什么微優(yōu)化是合理的存在分歧,一些新手會(huì)過(guò)度使用它。這里的優(yōu)化僅在時(shí)間測(cè)試表明它們提高了性能時(shí)才添加,即使是很小的改進(jìn)。微優(yōu)化很有啟發(fā)性,因?yàn)樗鼈兪褂昧?Python 的一些奇怪的方面,但不要在您自己的代碼中過(guò)度使用它。
str 的快捷方式也是一個(gè)微優(yōu)化。python 中的變量可以是函數(shù)局部或模塊全局或 python 內(nèi)置。查找局部變量名稱比查找全局或內(nèi)置名稱更快。我們習(xí)慣于 str 是一個(gè)始終可用的內(nèi)置函數(shù),但是每次使用時(shí),python 仍然必須查找變量名。將它放在局部變量中可以為我們節(jié)省少量時(shí)間,因?yàn)榫植孔兞勘葍?nèi)置變量快。
一旦定義了這些快捷鍵,以下是被認(rèn)為是從我們的特定模板生成的python代碼。字符串將使用 append_result 或 extend_result 快捷鍵添加到結(jié)果列表中。選擇上一個(gè)還是下一個(gè)取決于我們是只添加一個(gè)字符串還是多個(gè)字符串。模板中的文本變成了一個(gè)簡(jiǎn)單的字符串。
同時(shí)使用 append 和 extend 方法會(huì)增加復(fù)雜性,但請(qǐng)記住,我們的目標(biāo)是*快地執(zhí)行模板。對(duì)項(xiàng)目使用擴(kuò)展意味著創(chuàng)建該項(xiàng)目的新列表,以便我們可以將其傳遞給擴(kuò)展。
{{...}} 中的表達(dá)式將被計(jì)算,轉(zhuǎn)換為字符串,并添加到結(jié)果中。表達(dá)式中的點(diǎn)會(huì)被傳遞給渲染函數(shù)的do_dots函數(shù)處理,認(rèn)為打點(diǎn)表達(dá)式的含義取決于上下文中的數(shù)據(jù)形式:可能是屬性訪問(wèn)、子項(xiàng)獲取,也可能是調(diào)用。
{% if ... %} 和 {% for ... %} 的邏輯結(jié)構(gòu)被轉(zhuǎn)化為 python 條件語(yǔ)句和循環(huán)。{% if/for ... %} 標(biāo)簽中的表達(dá)式將成為 if/for 語(yǔ)句中的表達(dá)式,然后 {% end ... %} 標(biāo)簽之前的內(nèi)容將成為語(yǔ)句的主體。
相關(guān)閱讀Relate
熱門(mén)文章 Recent
- 畢業(yè)證翻譯2023-03-11
- 老版結(jié)婚證翻譯件模板 老版結(jié)婚證翻譯模板.doc2023-03-11
- 已婚公證書(shū)翻譯模板 公證咨詢2023-03-11
- 英語(yǔ)邀請(qǐng)信模板帶翻譯 實(shí)用貼:高考英語(yǔ)作文必考邀請(qǐng)信萬(wàn)能模板2023-03-11
- 外貿(mào)翻譯模板 外貿(mào)翻譯英文簡(jiǎn)歷模板下載2023-03-11
- 國(guó)內(nèi)合同翻譯模板 翻譯服務(wù)合同英文正式樣本2023-03-11
- 天津南山區(qū)的戶口本翻譯模板 深圳情侶選好日子登記結(jié)婚,因集體戶口材料不全被拒2023-03-11
- 身份證翻譯模板2023-03-11
- 加拿大戶口本翻譯件標(biāo)準(zhǔn)模板 商務(wù)合同英語(yǔ)翻譯_專業(yè)合同英語(yǔ)翻譯服務(wù)2023-03-11
- 永州正規(guī)的合同協(xié)議翻譯模板 翻譯服務(wù)合同模板錦集9篇2023-03-11