摘要:可選控制所返回的函數(shù)的屬性。模式被用到,因?yàn)槎x函數(shù)需要用多個(gè)語句。聚合全部內(nèi)容,并將動(dòng)態(tài)創(chuàng)建的函數(shù)指定給一個(gè)變量。寫完之后,我偶然發(fā)現(xiàn),在自己列的計(jì)劃轉(zhuǎn)載清單中,有這一篇相關(guān)的文章,它介紹了動(dòng)態(tài)定義函數(shù)的方法。
標(biāo)題:Python Tips: Dynamic function definition
作者:Philip Trauner
譯者:豌豆花下貓
鏈接:https://philip-trauner.me/blo...
基于 MIT 許可協(xié)議
在 Python 中,沒有可以在運(yùn)行時(shí)簡化函數(shù)定義的語法糖。然而,這并不意味著它就不可能,或者是難以實(shí)現(xiàn)。
from types import FunctionType foo_code = compile("def foo(): return "bar"", "", "exec") foo_func = FunctionType(foo_code.co_consts[0], globals(), "foo") print(foo_func())
輸出:
bar剖析
逐行檢視代碼,你會(huì)發(fā)現(xiàn)語言/解釋器的屏障是多么脆弱。
>>> from types import FunctionType
Python 文檔通常不會(huì)列出那些非用于手動(dòng)創(chuàng)建的類的特征(這是完全合理的)。有三種方法可以解決這個(gè)問題:help()、inspect(無法查看內(nèi)置方法)、以及最后的解決方案,即查看 CPython 源代碼。
在本例中,help() 與 inspect 都可以完成工作,但是查看實(shí)際的源代碼,則會(huì)揭示出關(guān)于數(shù)據(jù)類型的更多細(xì)節(jié)。
>>> from inspect import signature >>> signature(FunctionType)1. code
內(nèi)部是一個(gè)PyCodeobject ,作為types.CodeType 對(duì)外開放。非內(nèi)置方法擁有一個(gè)__code__ 屬性,該屬性保存了相應(yīng)的代碼對(duì)象。利用內(nèi)置的 compile() 方法,可以在運(yùn)行期創(chuàng)建types.CodeType 對(duì)象。
2. globals如果一個(gè)函數(shù)引用的變量不是在局部定義的,而是作為參數(shù)轉(zhuǎn)入、由默認(rèn)參數(shù)值提供、或者通過閉包上下文提供,則它會(huì)在 globals 字典中查找。
內(nèi)置的 globals() 方法會(huì)返回一個(gè)對(duì)當(dāng)前模塊的全局符號(hào)表(global symbol table)的引用 ,因此能被用來提供一個(gè)總是與當(dāng)前表的狀態(tài)相一致的字典。傳入任意其它的字典也是可以的(FunctionType((lambda: bar).__code__, {"bar" : "baz"}, "foo")() == "baz")。
3. name(可選)控制所返回的函數(shù)的__name__ 屬性。只真正對(duì) lambdas 有用(由于匿名性,它們通常沒有名稱),并且重命名函數(shù)。
4. argdefs(可選)通過傳入一個(gè)包含任意類型的對(duì)象的元組,提供了一個(gè)方式來供應(yīng)默認(rèn)參數(shù)值(def foo(bar="baz"))。(FunctionType((lambda bar: bar).__code__, {}, "foo", (10,))() == 10)。
5. closure(可選)(如果需要在 CPython(PyPy,Jython,...)以外的其它 Python VM 中執(zhí)行,可能不應(yīng)該觸及,因?yàn)樗鼑?yán)重地依賴于實(shí)現(xiàn)細(xì)節(jié))。
一個(gè)cell 對(duì)象的元組。創(chuàng)建 cell 對(duì)象并非完全是直截了當(dāng)?shù)?,因?yàn)樾枰{(diào)用 CPython 的內(nèi)部組件,但有一個(gè)庫可以令它更加方便:exalt (無恥的廣告)。(譯注:這個(gè)庫是作者開發(fā)的。)
>>> foo_code = compile("def foo(): return "bar"", "", "exec")
compile() 是一個(gè)內(nèi)置方法,因此同時(shí)也是文檔豐富的。
exec 模式被用到,因?yàn)槎x函數(shù)需要用多個(gè)語句。
>>> foo_func = FunctionType(foo_code.co_consts[0], globals(), "foo")
聚合全部內(nèi)容,并將動(dòng)態(tài)創(chuàng)建的函數(shù)指定給一個(gè)變量。
那個(gè)被前一句代碼編譯成的函數(shù),成為了生成的代碼對(duì)象的第一個(gè)常量,因此僅僅指向 foo_code 是不充分的。這是 exec 模式的直接后果,因?yàn)樯傻拇a對(duì)象可以包含多個(gè)常量。
>>> print(foo_func())
動(dòng)態(tài)生成的函數(shù)可以像其它函數(shù)一樣被調(diào)用。
結(jié)尾除了做實(shí)驗(yàn),需要用到動(dòng)態(tài)創(chuàng)建函數(shù)的場景很少。
玩耍(Toying around) Python 的內(nèi)部構(gòu)件是一種深入學(xué)習(xí)這門語言的好方法。
如果需要,可以毫不費(fèi)力地越過解釋器/語言的界線。
還是一如既往地:不要濫用語言 (好吧,一點(diǎn)點(diǎn)也無妨,對(duì)吧?)
--------(譯文完)--------
花下貓語: 在上一篇《Python進(jìn)階:如何將字符串常量轉(zhuǎn)為變量?》中,我介紹了兩種動(dòng)態(tài)修改變量 的方法(globals() 與 exec())。寫完之后,我偶然發(fā)現(xiàn),在自己列的“計(jì)劃轉(zhuǎn)載清單”中,有這一篇相關(guān)的文章,它介紹了動(dòng)態(tài)定義函數(shù) 的方法。因?yàn)樗南嚓P(guān)度太大,而篇幅又是那么?。ê诵拇a只有三行,文中其它內(nèi)容都是在解釋其背后的原理),我覺得如果翻譯出來的話,效果會(huì)更好,所以就抓緊時(shí)間翻譯出來了。建議與前一篇文章配合閱讀。
公眾號(hào)【Python貓】, 專注Python技術(shù)、數(shù)據(jù)科學(xué)和深度學(xué)習(xí),力圖創(chuàng)造一個(gè)有趣又有用的學(xué)習(xí)分享平臺(tái)。本號(hào)連載優(yōu)質(zhì)的系列文章,有喵星哲學(xué)貓系列、Python進(jìn)階系列、好書推薦系列、優(yōu)質(zhì)英文推薦與翻譯等等,歡迎關(guān)注哦。PS:后臺(tái)回復(fù)“愛學(xué)習(xí)”,免費(fèi)獲得一份學(xué)習(xí)大禮包。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/43393.html
摘要:內(nèi)置函數(shù)們能夠被提拔出來,這就意味著它們皆有獨(dú)到之處,有用武之地。因此,掌握內(nèi)置函數(shù)的用法,就成了我們應(yīng)該點(diǎn)亮的技能。報(bào)錯(cuò)包含了內(nèi)置命名空間中的名稱,在控制臺(tái)中輸入,就能發(fā)現(xiàn)很多內(nèi)置函數(shù)異常和其它屬性的名稱。 Python 提供了很多內(nèi)置的工具函數(shù)(Built-in Functions),在最新的 Python 3 官方文檔中,它列出了 69 個(gè)。 大部分函數(shù)是我們經(jīng)常使用的,例如 p...
摘要:今天的騷操作,分享的是一個(gè)自動(dòng)拷貝電腦盤內(nèi)容的程序。當(dāng)別人的盤插入到你的電腦上時(shí),腳本會(huì)自動(dòng)把盤所有的內(nèi)容,全部拷貝到你的電腦上。騷源碼程序主要是由三個(gè)函數(shù)組成,。每個(gè)操作都會(huì)記錄到日志中,以便日后查看相應(yīng)的拷貝信息。 showImg(https://segmentfault.com/img/remote/1460000016794520); 閱讀文本大概需要 6 分鐘。 Python...
摘要:今天帶給大家一個(gè)非常有意思的程序,基于實(shí)現(xiàn)微信控制電腦。你可以通過在微信發(fā)送命令,來拍攝當(dāng)前電腦的使用者,然后圖片會(huì)發(fā)送到你的微信上。程序主要是通過使用庫來登錄到微信網(wǎng)頁端,然后通過來發(fā)送消息和接收消息。隨后會(huì)彈出一個(gè)微信網(wǎng)頁登錄的二維碼。 showImg(https://segmentfault.com/img/remote/1460000016807619); 閱讀文本大概需要 5...
摘要:單元素元祖這是整數(shù)這才是元祖也許這兩行,你們當(dāng)時(shí)疑惑過,并且現(xiàn)在也都知道了,當(dāng)然重點(diǎn)并不在這里。。雖然我水平很垃圾,但是我知道匿名函數(shù)有一種執(zhí)行方式叫做自執(zhí)行??窗?,這就是版的匿名函數(shù)自執(zhí)行方法。 單元素元祖: a = (1) # 這是整數(shù)1 a = (1,) # 這才是元祖 也許這兩行,你們當(dāng)時(shí)疑惑過,并且現(xiàn)在也都知道了,當(dāng)然重點(diǎn)并不在這里。。 我無聊的時(shí)候想過,為什么單...
閱讀 2141·2023-04-25 17:23
閱讀 2948·2021-11-17 09:33
閱讀 2551·2021-08-21 14:09
閱讀 3669·2019-08-30 15:56
閱讀 2634·2019-08-30 15:54
閱讀 1650·2019-08-30 15:53
閱讀 2160·2019-08-29 13:53
閱讀 1174·2019-08-29 12:31