Python進階:如何將字符串常量轉化為變量?

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

?

前幾天,我們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()及其相關函數:https://www.tuicool.com/wx/vEbeumE

公眾號【Python貓】, 專注Python技術、數據科學和深度學習,力圖創造一個有趣又有用的學習分享平臺。本號連載優質的系列文章,有喵星哲學貓系列、Python進階系列、好書推薦系列、優質英文推薦與翻譯等等,歡迎關注哦。PS:后臺回復“愛學習”,免費獲得一份學習大禮包。

轉載于:https://my.oschina.net/u/4051725/blog/3023591

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/275589.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/275589.shtml
英文地址,請注明出處:http://en.pswp.cn/news/275589.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

怎么在matlab中圖像中外接矩形,Matlab 最小外接矩形

Matlab 中并沒有發現最小外接矩形的代碼,為了方便下面提供最小外接矩形的代碼:注:這個函數是源于網上找到的代碼的改進版,原版不能檢測水平線或者垂直線function [rectx,recty,area,perimeter] minboundrect(x,y,metric)% minbou…

尤雨溪開發的 vue-devtools 如何安裝,為何打開文件的功能鮮有人知?

1. 前言大家好,我是若川。最近組織了一次源碼共讀活動。每周讀 200 行左右的源碼。很多第一次讀源碼的小伙伴都感覺很有收獲,感興趣可以加我微信 ruochuan12,拉你進群學習。第一周讀的是:據說 99% 的人不知道 vue-devtools 還能直…

sketch浮動布局_使用智能布局和調整大小在Sketch中創建更好的可重用符號

sketch浮動布局Sketch is a widely used tool for UI designs. It implemented the Sketch是用于UI設計的廣泛使用的工具。 它實施了 atomic design methodology and made the workflow of UI design much more efficient. You can create a Symbol in Sketch and use it ever…

用Sql添加刪除字段,判斷字段是否存在的方法

增加字段alter table docdsp add dspcode char(200)刪除字段ALTER TABLE table_NAME DROP COLUMN column_NAME修改字段類型ALTER TABLE table_name ALTER COLUMN column_name new_data_type改名sp_rename更改當前數據庫中用戶創建對象(如表、列或用戶定義數據類型…

小姐姐筆記:我是如何學習簡單源碼拓展視野的

大家好,我是若川。這是我上周組織的源碼共讀紀年小姐姐的筆記,寫得很好。所以分享給大家。歡迎加我微信 ruochuan12,進源碼共讀群。其他更多人的筆記可以閱讀原文查看。川哥的源碼解讀文章:據說 99% 的人不知道 vue-devtools 還能…

php表決器代碼,三人表決器:VHDL源代碼

描述--三人表決器(三種不同的描述方式) vhdl-- Three-input Majority Voter-- The entity declaration is followed by three alternative architectures which achieve the same functionality in different ways.ENTITY maj ISPORT(a,b,c : IN BIT; m : OUT BIT);END maj;--D…

保持危機感和緊迫感_什么是緊迫的:您需要知道的一切

保持危機感和緊迫感Putting the finishing touches on a graphic design project calls for a keen eye. But you already know this, because perfectionism is just a part of the job! You look at every nook and cranny of a project before you can consider it complete…

劍指offer java版(一)

二維數組中的查找 問題描述 在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷…

如何系統搭建現代 Web CI/CD

大家好,我是若川。今天分享一篇00后寫的CI/CD直播文字稿。之前發過他的故事:一位00后前端2年經驗的成長歷程。我最近組織了源碼共讀活動,感興趣的加我微信 ruochuan12。本次直播錄播鏈接:https://live.juejin.cn/4354/595741[1]開…

sqlserver oracle 數據類型對應關系,SQLSERVER和ORACLE數據類型對應關系詳解和對應表格整理...

Oracle SQLServer 比較 SQLServer 常見的 數據 庫 類型 字符 數據 類型 CHAR CHAR :都是固定長度字符資料但oracle里面最大度為2kb,SQLServer里面最大長度為8kb 變長字符 數據 類型 VARCHAR2 VARCHAR :racle里面最大長度為4kb,SQLServer里面最大長度為8k…

優化算法匯總

interior point block coordinate relaxation Boltzmann machine 求解L1范數最小化 E. Candes, M. B. Wakin, and S. P. Boyd, “Enhancing sparsity by reweighted l1 minimization,” Journalof Fourier Analysis and Applications, vol. 14, pp. 877-905, Dec. 2008.I. Daub…

對接百度地圖API

一、準備工作 百度地圖開發文檔 注冊百度賬號&#xff0c;成為開發人員&#xff0c;同時獲取AK實例代碼&#xff1a;<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content&quo…

ui邊框設計圖_UI設計形狀和對象基礎知識:填充和邊框

ui邊框設計圖第2部分 (Part 2) Welcome to the second part of the UI Design shapes basics. This time we’ll cover two of the most essential properties of a shape — fills and borders. This is also a part of the free chapters from Designing User Interfaces.歡迎…

如何移除項目中無用的 console.log 代碼

大家好&#xff0c;我是若川。早些天時&#xff0c;我看到一個后端公眾號發《辭退了一個前端》&#xff0c;當時還想著現在后端公眾號都開始吊打前端了嘛。其中有個理由就是線上還一堆console.log...我猜很多人都會移除項目中無用的console.log。可以復習一下。前言說起console…

WCF - 服務實例管理模式

WCF 提供了三種實例上下文模式&#xff1a;PreCall、PreSession 以及 Single。開發人員通過 ServiceBehavior.InstanceContextMode 就可以很容易地控制服務對象的實例管理模式。而當 WCF 釋放服務對象時&#xff0c;會檢查該對象是否實現了 IDisposable 接口&#xff0c;并調用…

oracle io lost,磁盤IO故障

測試工作正在如火如荼的進行&#xff0c;突然數據庫就連接不上了。我連接上主機發現數據庫alert_sid日志中有如下信息&#xff1a;KCF: write/open error block0x9a6 online1file2 /oracle_data1/UNDOTBS3.dbferror27072 txt: Linux Error: 5: Input/output errorAdditional in…

易思匯完成近億元B輪融資,信中利投資

3月19日消息&#xff0c;近日&#xff0c;留學生在線付費平臺易思匯宣布已在3月份完成由信中利投資的近億元B輪融資。 易思匯聯合創始人高宇同表示&#xff0c;本輪融資將主要用于留學生信用卡、留學家庭金融商城等新產品布局&#xff0c;以及擴大團隊和市場投入。 易思匯成立…

遠程連接 錯誤 內部錯誤_關于錯誤的性質和原因。 了解錯誤因素

遠程連接 錯誤 內部錯誤Back in 2012, I was a young[er] product designer working in a small tech agency in Valencia, Spain. In parallel, I worked as a freelancer on several side projects for different clients. One day I was contacted by a new health services…

得到鵝廠最新前端開發手冊一份

又逢金九銀十&#xff0c;拿到大廠offer一直是程序員朋友的目標&#xff0c;但是去大廠就得拿出實力來。除了需要積累技術&#xff0c;了解并掌握面試的技巧&#xff0c;熟悉大廠面試流程&#xff0c;也必不可少。這里分享一份最新入職騰訊的前端社招面經&#xff0c;來看看鵝廠…

性能測試分析之帶寬瓶頸的疑惑

第一部分&#xff0c; 測試執行 先看一圖&#xff0c;再看下文 這個當然就是壓力過程中帶寬的使用率了&#xff0c;我們的帶寬是1Gbps的&#xff0c;合計傳輸速率為128MB/s&#xff0c;也正因為這個就讓我越來越疑惑了&#xff0c;不過通過壓力過程中的各項數據我又不得不相信。…