摘要:例如,整數(shù)浮點數(shù)字符串等基本類型,就是字面量。所以,取出的字符串內(nèi)容,并不能直接用作變量名,需要另想辦法。總結(jié)抽象一下最初的問題,它實際問的是如何將字符串內(nèi)容作為其它對象的變量名,更進(jìn)一步地講是如何將常量轉(zhuǎn)化為變量。
前幾天,我們Python貓交流學(xué)習(xí)群 里的 M 同學(xué)提了個問題。這個問題挺有意思,經(jīng)初次討論,我們認(rèn)為它無解。
然而,我認(rèn)為它很有價值,應(yīng)該繼續(xù)思考怎么解決,所以就在私密的知識星球上記錄了下來。
萬萬沒想到的是,在第二天,有兩位同學(xué)接連給出了解決方法!
由此,群內(nèi)出現(xiàn)了一輪熱烈的技術(shù)交流。
本文將相關(guān)的內(nèi)容要點作了梳理,并由此引申到更進(jìn)一步的學(xué)習(xí)話題,希望對你有所幫助。
1、如何動態(tài)生成變量名?M 同學(xué)的問題如下:
打擾一下大家,請教一個問題,已知 list = ["A", "B", "C", "D"] , 如何才能得到以 list 中元素命名的新列表 A = [], B = [], C = [], D = [] 呢?
簡單理解,這個問題的意思是,將字符串內(nèi)容作為其它對象的變量名。
list 中的元素是字符串,此處的 ‘A’-‘D’ 是常量 ,而在要求的結(jié)果中,A-D 是變量 。
如果強(qiáng)行直接將常量當(dāng)做變量使用,它會報錯:
>>> "A" = [] ...SyntaxError: can"t assign to literal
報錯中的literal 指的是字面量 ,這是計算機(jī)科學(xué)中常見的一個概念,用于表達(dá)源代碼中的固定值。 例如,整數(shù)、浮點數(shù)、字符串等基本類型,就是字面量。
字面量指的就是一個量本身,可以理解為一種原子性的實體,當(dāng)然不能再被賦值了。
所以,取出的字符串內(nèi)容,并不能直接用作變量名,需要另想辦法。
有初學(xué)者可能會想,list[0] = [] 行不行?當(dāng)然不行,因為沒有出現(xiàn) A 。那 A = list[0] ,接著 A = [] 呢?那也不行,因為這里的 A 是你憑空定義出來的,而不是從已有條件中生成的。
當(dāng)時,群里只有兩三個同學(xué)參與了討論,我們沒想到解決辦法。但是,我覺得這個題目很有意思,值得玩味。
因為,如果能解決這個問題,那就意味著可以不作預(yù)先定義,而是動態(tài)地生成變量名,這不僅能減少給變量取名的麻煩,還實現(xiàn)了自動編碼!
可以設(shè)想一下未來,人工智能在編寫代碼的時候,如果能根據(jù)已知條件,動態(tài)生成變量名,那編寫代碼的過程不就順利多了么?(據(jù)說,現(xiàn)在已經(jīng)有人工智能可以編寫代碼了,不知它在取變量名時,是用的什么方法?)
2、辦法總是有的最近,學(xué)習(xí)群里蒙混進(jìn)來了幾個打廣告的,為此,我決定提高審核門檻,例如,用群里的問題來作個考核。
萬萬沒想到的是,第一個被考核到的 Q 同學(xué),幾乎不假思索地就說出了一個解決上述問題的思路。而偏偏就是那么巧 ,幾乎在同時,群內(nèi)的 J 同學(xué)給出了另外一個解決方法(他沒看到群內(nèi)的討論,而是看到了知識星球的記錄,才知道這個問題的)。
也就是說,前一晚還以為無解的問題,在第二天竟得到了兩種不同的解決方法!
那么,他們的答案是什么呢?
# J 同學(xué)的解答 >>> list1 = ["A", "B", "C", "D"] >>> for i in list1: >>> globals()[i] = [] >>> A []
這個方法通過修改全局命名空間,巧妙地“定義”出了新的變量。globals() 方法取出來的是一個字典,字符串 ‘A’ 是其中一個鍵值(key),而這個鍵值恰恰是全局命名空間中的一個變量,這就實現(xiàn)了從常量到變量的轉(zhuǎn)化。
在數(shù)據(jù)結(jié)構(gòu)層面上,空列表 [] 作為一個值(value)跟它的字符串鍵值綁定在一起,而在運用層面上,它作為變量內(nèi)容而跟變量名綁定在一起。
看到這個回答的時候,我就突然想起來了,上個月轉(zhuǎn)載過一篇《Python 動態(tài)賦值的陷阱》,講的正是動態(tài)地進(jìn)行變量賦值 的問題啊!我似乎只關(guān)注了 globals() 與 locals() 用法的區(qū)別,卻沒有真正地掌握它們的原初用途。
J 同學(xué)說,他正是看了那篇文章,才學(xué)得了這個方法。這就有意思了,我分享了一個自己囫圇吞棗的知識,然后它被 J 同學(xué)吸收掌握,最后反饋回來解決了我的難題。
我真切地感受到了知識分享的魅力:知識在流動中獲得生命,在碰撞中锃亮色澤。
同時,我也真切地明白了一個互助的學(xué)習(xí)團(tuán)體的好處:利人者也利己,互助者共同進(jìn)步。
3、動態(tài)執(zhí)行代碼的方法新進(jìn)群的 Q 同學(xué),提供了一個不同的答案:
# Q 同學(xué)的解答 >>> list1 = ["A", "B", "C", "D"] >>> for i in list1: >>> exec(f"{i} = []") >>> A []
他的寫法用到了 Python 3.6 才引入的 f-strings 特性,事實上,在較低版本中,也是可以實現(xiàn)的,只需要保證 exec() 方法接收的參數(shù)是包含了變量 i 的字符串即可,例如這樣寫:
# 以下代碼可替換上例的第 4 行 exec(i + " = []") # 或者: exec("{} = []".format(i)) # 或者: exec(" ".join([i, "= []"]))
這幾種寫法的區(qū)別只是字符串拼接法的區(qū)別,關(guān)于如何拼接字符串,以及不同方法之間的區(qū)別,可參看《詳解Python拼接字符串的七種方式》。
Q 同學(xué)這個答案的核心在于 exec() 方法,它是內(nèi)置的,用途是執(zhí)行儲存在字符串或文件中的代碼段。
它的基礎(chǔ)用法如下:
>>> exec("x = 1 + 2") >>> x 3 # 執(zhí)行代碼段 >>> s = """ >>> x = 10 >>> y = 20 >>> sum = x + y >>> print(sum) >>> """ >>> exec(s) 30
看完了 exec() 的用法,我們再回來看 Q 同學(xué)的答案。for-循環(huán)中取出來的 i 是字符串,而拼接后的字符串經(jīng)過 exec() 的處理,就獲得了動態(tài)編寫代碼的效果。
也就是說,因為字符串常量的內(nèi)容被當(dāng)做有效代碼而執(zhí)行了,其中的 "A"-"D" 元素,就取得了新的身份,變成了最終的 A-D 變量名。
這個方法看起來很簡單啊,可是由于 exec() 方法太生僻了,直到 Q 同學(xué)提出,我們才醒悟過來。
注意:在 Python3 中,exec() 是個內(nèi)置方法;而在 Python2 中,exec 是個語句(statement),另外有個 execfile() 方法,兩者相合并,就成了 Python3 中的 exec() 方法。本文使用的是 Python3。4、總結(jié)
抽象一下最初的問題,它實際問的是“如何將字符串內(nèi)容作為其它對象的變量名”,更進(jìn)一步地講是——“如何將常量轉(zhuǎn)化為變量 ”。
使用直接進(jìn)行賦值的靜態(tài)方法,行不通。
兩位同學(xué)提出的方法都是間接的動態(tài)方法:一個是動態(tài)地進(jìn)行變量賦值,通過修改命名空間而植入變量;一個是動態(tài)地執(zhí)行代碼,可以說是通過“走后門”的方式,安插了變量。
兩種方法殊途同歸,不管是白貓還是黑貓,它們都抓到了老鼠。
這兩種方法已經(jīng)給我們帶來了很有價值的啟發(fā),同時,因為它們,群內(nèi)小伙伴們更是發(fā)散地討論一些相關(guān)聯(lián)的話題,例如:S 同學(xué)提出了另一種修改命名空間中變量的寫法、L 同學(xué)提到了 eval() 的意義、eval() 與 exec() 的區(qū)別、我查到了為什么要慎用 eval() 、C 與 H 同學(xué)提到了 eval() 的安全用法......
雖然,某些話題無法在群聊中充分展開,但是,這些話題知識的延展聯(lián)系,大大地豐富了本文開頭的問題,這一個微小的問題,牽連出來了兩個大的知識體系。
最后,真得感謝群內(nèi)的這些愛學(xué)習(xí)的優(yōu)秀的同志們!除了文中提及的,還有一些同學(xué)也做了積極貢獻(xiàn),大家都很給力!
相關(guān)鏈接:
《Python 動態(tài)賦值的陷阱》
《詳解Python拼接字符串的七種方式》
eval()、exec()及其相關(guān)函數(shù):https://www.tuicool.com/wx/vE...
公眾號【Python貓】, 專注Python技術(shù)、數(shù)據(jù)科學(xué)和深度學(xué)習(xí),力圖創(chuàng)造一個有趣又有用的學(xué)習(xí)分享平臺。本號連載優(yōu)質(zhì)的系列文章,有喵星哲學(xué)貓系列、Python進(jìn)階系列、好書推薦系列、優(yōu)質(zhì)英文推薦與翻譯等等,歡迎關(guān)注哦。PS:后臺回復(fù)“愛學(xué)習(xí)”,免費獲得一份學(xué)習(xí)大禮包。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/43375.html
摘要:獲取怎樣的數(shù)據(jù)在這里首先需要考慮,我們的四則運算計算器的計算復(fù)雜度是如何的是僅能計算兩個數(shù)值的簡單運算,如還是能進(jìn)行混合四則運算,如那么你想處理運算的復(fù)雜程度就決定了你想獲取怎樣的數(shù)據(jù),這是很實際的問題。 引言 在上一篇文章的介紹中,我們提及了Python的三種基本數(shù)據(jù)類型,如文章末尾所說,Python中的內(nèi)建數(shù)據(jù)類型并不僅僅是這幾種,但其實我從接觸Python到現(xiàn)在,往往就是這幾種簡...
摘要:如的語句被稱為預(yù)處理指令,還有注釋文本的刪除,都在此階段完成替換。故宏在程序規(guī)模和執(zhí)行速度方面更勝一籌。宏替換發(fā)生在預(yù)編譯期間,故無法調(diào)試。宏可能由于運算符優(yōu)先級的問題,會導(dǎo)致程序出錯。 ...
摘要:內(nèi)置函數(shù)們能夠被提拔出來,這就意味著它們皆有獨到之處,有用武之地。因此,掌握內(nèi)置函數(shù)的用法,就成了我們應(yīng)該點亮的技能。報錯包含了內(nèi)置命名空間中的名稱,在控制臺中輸入,就能發(fā)現(xiàn)很多內(nèi)置函數(shù)異常和其它屬性的名稱。 Python 提供了很多內(nèi)置的工具函數(shù)(Built-in Functions),在最新的 Python 3 官方文檔中,它列出了 69 個。 大部分函數(shù)是我們經(jīng)常使用的,例如 p...
閱讀 1339·2021-11-11 16:54
閱讀 2385·2021-09-22 10:51
閱讀 2655·2019-08-30 15:44
閱讀 3206·2019-08-29 17:05
閱讀 1445·2019-08-29 17:01
閱讀 2898·2019-08-29 12:28
閱讀 2471·2019-08-26 13:50
閱讀 1731·2019-08-23 16:47