Python進階:如何將字串常量轉化為變數?
Python進階:如何將字串常量轉化為變數?
前幾天,我們Python貓交流學習群 裡的 M 同學提了個問題。這個問題挺有意思,經初次討論,我們認為它無解。
然而,我認為它很有價值,應該繼續思考怎麼解決,所以就在私密的知識星球上記錄了下來。
萬萬沒想到的是,在第二天,有兩位同學接連給出瞭解決方法!
由此,群內出現了一輪熱烈的技術交流。
本文將相關的內容要點作了梳理,並由此引申到更進一步的學習話題,希望對你有所幫助。
1、如何動態生成變數名?
M 同學的問題如下:
打擾一下大家,請教一個問題,已知 list = ['A', 'B', 'C', 'D'] , 如何才能得到以 list 中元素命名的新列表 A = [], B = [], C = [], D = [] 呢?
簡單理解,這個問題的意思是,將字串內容作為其它物件的變數名。
list 中的元素是字串,此處的 ‘A’-‘D’ 是常量 ,而在要求的結果中,A-D 是變數 。
如果強行直接將常量當做變數使用,它會報錯:
>>> 'A' = []
...SyntaxError: can't assign to literal
報錯中的literal 指的是字面量 ,這是電腦科學中常見的一個概念,用於表達原始碼中的固定值。 例如,整數、浮點數、字串等基本型別,就是字面量。
字面量指的就是一個量本身,可以理解為一種原子性的實體,當然不能再被賦值了。
所以,取出的字串內容,並不能直接用作變數名,需要另想辦法。
有初學者可能會想,list[0] = [] 行不行?當然不行,因為沒有出現 A 。那 A = list[0] ,接著 A = [] 呢?那也不行,因為這裡的 A 是你憑空定義出來的,而不是從已有條件中生成的。
當時,群裡只有兩三個同學參與了討論,我們沒想到解決辦法。但是,我覺得這個題目很有意思,值得玩味。
因為,如果能解決這個問題,那就意味著可以不作預先定義,而是動態地生成變數名,這不僅能減少給變數取名的麻煩,還實現了自動編碼!
可以設想一下未來,人工智慧在編寫程式碼的時候,如果能根據已知條件,動態生成變數名,那編寫程式碼的過程不就順利多了麼?(據說,現在已經有人工智慧可以編寫程式碼了,不知它在取變數名時,是用的什麼方法?)
2、辦法總是有的
最近,學習群裡矇混進來了幾個打廣告的,為此,我決定提高稽核門檻,例如,用群裡的問題來作個考核。
萬萬沒想到的是,第一個被考核到的 Q 同學,幾乎不假思索地就說出了一個解決上述問題的思路。而偏偏就是那麼巧 ,幾乎在同時,群內的 J 同學給出了另外一個解決方法(他沒看到群內的討論,而是看到了知識星球的記錄,才知道這個問題的)。
也就是說,前一晚還以為無解的問題,在第二天竟得到了兩種不同的解決方法!
那麼,他們的答案是什麼呢?
# J 同學的解答
>>> list1 = ['A', 'B', 'C', 'D']
>>> for i in list1:
>>> globals()[i] = []
>>> A
[]
這個方法透過修改全域性名稱空間,巧妙地“定義”出了新的變數。globals() 方法取出來的是一個字典,字串 ‘A’ 是其中一個鍵值(key),而這個鍵值恰恰是全域性名稱空間中的一個變數,這就實現了從常量到變數的轉化。
在資料結構層面上,空列表 [] 作為一個值(value)跟它的字串鍵值繫結在一起,而在運用層面上,它作為變數內容而跟變數名繫結在一起。
看到這個回答的時候,我就突然想起來了,上個月轉載過一篇《Python 動態賦值的陷阱》,講的正是 動態地進行變數賦值 的問題啊!我似乎只關注了 globals() 與 locals() 用法的區別,卻沒有真正地掌握它們的原初用途。
J 同學說,他正是看了那篇文章,才學得了這個方法。這就有意思了,我分享了一個自己囫圇吞棗的知識,然後它被 J 同學吸收掌握,最後反饋回來解決了我的難題。
我真切地感受到了知識分享的魅力: 知識在流動中獲得生命,在碰撞中鋥亮色澤。
同時,我也真切地明白了一個互助的學習團體的好處: 利人者也利己,互助者共同進步。
3、動態執行程式碼的方法
新進群的 Q 同學,提供了一個不同的答案:
# Q 同學的解答
>>> list1 = ['A', 'B', 'C', 'D']
>>> for i in list1:
>>> exec(f"{i} = []")
>>> A
[]
他的寫法用到了 Python 3.6 才引入的 f-strings 特性,事實上,在較低版本中,也是可以實現的,只需要保證 exec() 方法接收的引數是包含了變數 i 的字串即可,例如這樣寫:
# 以下程式碼可替換上例的第 4 行
exec(i + " = []")
# 或者:
exec("{} = []".format(i))
# 或者:
exec(' '.join([i, '= []']))
這幾種寫法的區別只是字串拼接法的區別,關於如何拼接字串,以及不同方法之間的區別,可參看《詳解Python拼接字串的七種方式》。
Q 同學這個答案的核心在於 exec() 方法,它是內建的,用途是 執行儲存在字串或檔案中的程式碼段。
它的基礎用法如下:
>>> exec('x = 1 + 2')
>>> x
3
# 執行程式碼段
>>> s = """
>>> x = 10
>>> y = 20
>>> sum = x + y
>>> print(sum)
>>> """
>>> exec(s)
30
看完了 exec() 的用法,我們再回來看 Q 同學的答案。for-迴圈中取出來的 i 是字串,而拼接後的字串經過 exec() 的處理,就獲得了動態編寫程式碼的效果。
也就是說,因為字串常量的內容被當做有效程式碼而執行了,其中的 'A'-'D' 元素,就取得了新的身份,變成了最終的 A-D 變數名。
這個方法看起來很簡單啊,可是由於 exec() 方法太生僻了,直到 Q 同學提出,我們才醒悟過來。
注意:在 Python3 中,exec() 是個內建方法;而在 Python2 中,exec 是個語句(statement),另外有個 execfile() 方法,兩者相合並,就成了 Python3 中的 exec() 方法。本文使用的是 Python3。
4、總結
抽象一下最初的問題,它實際問的是“如何將字串內容作為其它物件的變數名”,更進一步地講是——“ 如何將常量轉化為變數 ”。
使用直接進行賦值的靜態方法,行不通。
兩位同學提出的方法都是間接的動態方法: 一個是動態地進行變數賦值,透過修改名稱空間而植入變數;一個是動態地執行程式碼,可以說是透過“走後門”的方式,安插了變數。
兩種方法殊途同歸,不管是白貓還是黑貓,它們都抓到了老鼠。
這兩種方法已經給我們帶來了很有價值的啟發,同時,因為它們,群內小夥伴們更是發散地討論一些相關聯的話題,例如:S 同學提出了另一種修改名稱空間中變數的寫法、L 同學提到了 eval() 的意義、eval() 與 exec() 的區別、我查到了為什麼要慎用 eval() 、C 與 H 同學提到了 eval() 的安全用法......
雖然,某些話題無法在群聊中充分展開,但是,這些話題知識的延展聯絡,大大地豐富了本文開頭的問題,這一個微小的問題,牽連出來了兩個大的知識體系。
最後,真得感謝群內的這些愛學習的優秀的同志們!除了文中提及的,還有一些同學也做了積極貢獻,大家都很給力!
相關連結:
《Python 動態賦值的陷阱》
《詳解Python拼接字串的七種方式》
eval()、exec()及其相關函式:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29829936/viewspace-2641365/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Python中如何將字串變成數字?Python字串
- Octave 數字轉字元,連線兩個字串,以及如何將字串轉換為變數名稱字元字串變數
- javascript如何將字串轉換為數字JavaScript字串
- C語言進階[2]:字串常量C語言字串
- 將字串轉為數字字串
- Python 如何將一變數做為函式名?Python變數函式
- 字串:怎樣將數字型別轉換為字串 (轉)字串型別
- Thymeleaf將字串轉換為數字字串
- C 如何將輸出的地址轉化為十進位制數
- 將html字串轉化為jquery物件HTML字串jQuery物件
- 在 Laravel 中將 PHP 變數轉化為 JavaScript 變數並輸出LaravelPHP變數JavaScript
- postgresql如何將字串轉為時間SQL字串
- 將檔案轉化為字串的方法字串
- Python進階如何修改閉包內使用的外部變數?Python變數
- VBA靜態變數與常量(轉)變數
- 華為機試題(9)--將兩個數從字串轉為數,將這兩個數做乘積後再轉化為字串儲存起來字串
- 如何在MySQL中使用CONVERT將字串轉換為數字MySql字串
- Python將字串轉為字典最佳實踐Python字串
- python3 將bytes轉為字串Python字串
- 將一個字串進行反轉:將字串中指定部分進行反轉。比如“abcdefg”反轉為”abfedcg”字串
- javascript中將數字轉為字串的方法JavaScript字串
- C++將數字轉為字串,並拼接C++字串
- 在Python中將字典轉為成員變數的方法Python變數
- 常量與變數變數
- 演算法數字轉化為字串演算法字串
- 如何在Java中將字串轉換為日期Java字串
- Java如何將字串轉換為字元陣列?Java字串字元陣列
- js如何將陣列元素轉換為字串JS陣列字串
- php變數的型別是如何轉換的?常量如何定義?系統常量是如何定義的?PHP變數型別
- 如何使用 Python 進行字串格式化Python字串格式化
- 2、全域性變數和列舉常量 (轉)變數
- java變數及常量Java變數
- java常量和變數Java變數
- 六、常量與變數變數
- PHP 常量與變數PHP變數
- Python將阿拉伯數字轉化為中文大寫Python
- 如何在 Go 中將 int 型別轉為字串Go型別字串
- 如何將時間字串轉換為時間物件字串物件