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