【Python实践】Python部分实际案例解答1
🌈據說,看我文章時 關注、點贊、收藏 的 帥哥美女們 心情都會不自覺的好起來。
前言:
🧡作者簡介:大家好我是 user_from_future ,意思是 “ 來自未來的用戶 ” ,寓意著未來的自己一定很棒~
?個人主頁:點我直達,在這里肯定能找到你想要的~
👍專欄介紹:Python實踐 ,一個專注于分享實際案例的專欄~
專欄文章直鏈:
【Python實踐】關于python多任務設計基礎
【Python實踐】你可能沒有見過的碼代碼小技巧1
史上最最最沒用程序——自寫平衡化學方程式
Python進階——對Python“腳本”的理解與使用
十大排序算法整理(含JavaScript版本與Python版本源碼)
從常用實例學習正則2
從常用實例學習正則1
自制小功能——cmd中的規則加密輸入
文件目錄操作實例2
文件目錄操作實例1
Python部分實際案例解答1
- 不同進制之間的轉換
- 其他進制轉十進制
- 十進制轉其他進制
- 獲取變量內存地址、獲取內存地址所指向的變量
- 了解C語言指針
- python“使用”指針
- python垃圾回收
- 二維數組生成的區別
- 淺拷貝與深拷貝
- 從列表中分離奇數和偶數
- 從列表中提取公共信息轉換成字典
- 模擬有密碼輸入次數的登錄系統
- 計算1-100內的奇數和、代碼執行時間計時
- 二層列表轉單層列表、代碼執行時間計時
- 發撲克小程序
不同進制之間的轉換
首先,我們最長看見的是十進制數,所以我們用此作為“橋梁”,連接其他進制。
這里就分兩種情況,一個是其他進制轉十進制,一個是十進制轉其他進制,這樣其他進制轉其他的其他進制就可以通過十進制中轉。
其他進制轉十進制
這個比較簡單,python的內置函數 int 就能實現:
int("1010011010", base=2) # 666 int("1232", base=8) # 666 int("666", base=10) # 666 int("29a", base=16) # 666對于“特殊”進制,二進制、八進制、十進制、十六進制,設置 base 為 0 就會自動識別字符串中的進制,默認為 10:
int("0b1010011010", base=0) # 666 int("0o1232", base=0) # 666 int("666", base=0) # 666 int("666") # 666 int("0x29a", base=0) # 666就如這小栗子所示,0b 是二進制的前綴, 0o 是八進制的前綴,0x 是十六進制的前綴,十進制沒有前綴。
十進制轉其他進制
常用輾轉相除法來計算,取余的逆向數字為結果。輾轉相除法本來是為了優化更相減損術,用來計算最大公約數的,為什么能用輾轉相除法計算呢?慢慢來理解:
先來一段2的指數結果表
- 20 = 1
- 21 = 2
- 22 = 4
- 23 = 8
- 24 = 16
- 25 = 32
- 26 = 64
- 27 = 128
- 28 = 256
- 29 = 512
再來看看十進制 666 是如何由 2 的指數加起來的:
666 = 1 * 29 + 0 * 28 + 1 * 27 + 0 * 26 + 0 * 25 + 1 * 24 +1 * 23 + 0 * 22 + 1 * 21 + 0 * 20
( == 29 + 27 + 24 + 23 + 21 )
最后看看輾轉相除法能得到什么:
666 = 2 * 333 + 0 = 29 + 27 + 24 + 23 + 21
333 = 2 * 166 + 1 = 28 + 26 + 23 + 22 + 20
166 = 2 * 83 + 0 ?= 27 + 25 + 22 + 21
83 ?= 2 * 41 + 1 ?= 26 + 24 + 21 + 20
41 ?= 2 * 20 + 1 ?= 25 + 23 + 20
20 ?= 2 * 10 + 0 ?= 24 + 22
10 ?= 2 * 5 + 0 ??= 23 + 21
5 ??= 2 * 2 + 1 ??= 22 + 20
2 ??= 2 * 1 + 0 ??= 21
1 ??= 2 * 0 + 1 ??= 20
對右邊豎線觀察,會發現經過每次除以2,高位指數慢慢變成了低位,直到最高位指數變成0為止。
然后從最底下逆推上去的原因就是:
上一式子總是在下一式子的基礎上,乘以指數,加上余數(也就是余數 * 底數的** 0** 次方);
也就是不斷把整個下一式子最右邊的指數和代入上一式子中的 2 * ? 中的 ? 部分,從而一步一步的得到指數和的相加結果。
還有一種拼湊法的意思就是:
666 < 210
666 > 29
666 < 29 + 28
666 > 29 + 27
666 < 29 + 27 + 26
666 < 29 + 27 + 25
666 > 29 + 27 + 24
666 > 29 + 27 + 24 + 23
666 < 29 + 27 + 24 + 23 + 22
666 = 29 + 27 + 24 + 23 + 21
從最大位開始湊;
湊到后面大了,就讓最后一個2的指數調小一級;
湊到后面小了,就讓最后再增加一個更小2的指數;
不斷反復直到相等。
先來一段8的指數結果表
- 80 = 1
- 81 = 8
- 82 = 64
- 83 = 512
再來看看十進制 666 是如何由 8 的指數加起來的:
666 = 1 * 83 + 2 * 82 + 3 * 81 + 2 * 80
和二進制一樣,看看輾轉相除法能得到什么:
666 = 8 * 83 + 2 = 1 * 83 + 2 * 82 + 3 * 81 + 2 * 80
83 ?= 8 * 10 + 3 = 1 * 82 + 2 * 81 + 3 * 80
10 ?= 8 * 1 + 2 ?= 1 * 81 + 2 * 80
1 ??= 8 * 0 + 1 ?= 1 * 80
代入后同樣能得到指數和的加法式子。
同樣拼湊法的意思就是:
666 < 2 * 83
666 > 1 * 83
666 < 1 * 83 + 3 * 82
666 > 1 * 83 + 2 * 82
666 < 1 * 83 + 2 * 82 + 4 * 81
666 > 1 * 83 + 2 * 82 + 3 * 81
666 = 1 * 83 + 2 * 82 + 3 * 81 + 2 * 81
原理理解了,就能上代碼了:
def dfs(x, d=2):if x:dfs(x // d, d)print({n: n for n in range(10)}.get(x % d, chr(x % d + 55 + 32)), end='')print('十進制轉任意進制小程序') jz = int(input('請輸入進制:') or 2) assert 1 < jz < 37, '只能從十進制轉換成二進制到三十六進制' num = input('請輸入十進制數:') dfs(int(num), d=jz)這可以用于十進制轉任意進制,dfs 函數中的三行分別代表的如下三個步驟:
也可以改寫為設置固定進制的,看著就很方便~
當然特殊的二進制、八進制和十六進制都有相應的函數,且會自帶字符前綴特征:
獲取變量內存地址、獲取內存地址所指向的變量
了解C語言指針
學過C語言的都知道,有個叫做 指針 的讓人頭疼的玩意,老是學起來問題,這邊先簡單講解一下C語言的變量指針作為了解鋪墊:
指針的作用:用來保存內存地址;
& 的作用:用來獲取內存地址(可以在輸出中用 %u 打印成無符號整數);
定義整型變量 int value = 0 ;
定義指針變量 int *address; address = &value 或 int *address = &value ;
這里可以看出,指針變量并不是 int 類型,而是 int * 類型,雖然他存的是一個地址整數,并且這當中加了一個空格,但其是一個整體,定義完了就可以丟一邊去了~
指針與變量的等價關系:*address = value 和 address = &value 。( address 是指針變量,是指針的地址;value 是變量值)
用一幅圖來明白:
sizeof() 用于獲取變量字節長度,這里是4是因為字符串有個終止字符**\0**,sizeof() 會將終止字符 \0 一并計算在內。
好了,對C語言指針有個初始的印象了吧?接下來就來說說,python中對指針的使用。
python“使用”指針
其實上面說一堆,下面實現起來很簡單,幾行代碼,使用了萬能的 ctypes 庫【C:我有指針你沒有! Python:拿來吧你!】:
import ctypes value = 666 value_id = id(value) print(value_id) value_get = ctypes.cast(value_id, ctypes.py_object).value print(value_get)輸出結果:
2022050320228 666第一行是獲取到的變量內存地址;
第二行是從該內存地址讀取變量;
python和其他語言對變量和內存地址的處理不同,先舉個小栗子:
你們覺得兩個id值輸出是不是一樣的?
我想大部分正常的人應該和很久之前的我一樣,認為他是不一樣的吧?
那就想錯了,答案是它倆的 id 值是一樣的,不管 del 多少次,每次指向同一變量所在的內存地址是相同的!
del 只會銷毀變量名所指向的內存地址,但不會關閉該內存地址,
簡單來說,python中定義的變量實際上是一個指針地址,表面上在修改變量值,實際上是在新的內存地址上創建了變量值,然后用變量名指向該內存地址。
所以與其說python中的 = 是賦值語句,倒不如說這是引用語句,就換了個內存地址的引用。
python垃圾回收
既然怎么 del ,內存空間都沒有被釋放,那變量太多內存滿了怎么辦?
這個不用擔心,雖然內存空間沒有被釋放,但它是根據其他特征決定是否釋放內存空間的,就是——引用計數器,它會動態跟蹤你代碼中的引用次數并判斷是否可以回收內存空間。
當你有多個變量等于一個值的時候,引用計數器就會累加;
當你其中一個變量重新賦值為其他值的時候,原來的值的引用計數器就會減一,同時新的值的引用計數器會加一。
當你操作 del 解除變量的引用、或者刪除可變對象(列表、字典、集合等)中的變量時,變量值的引用計數器也會相應減一,當你 del 等操作后下文沒有變量名引用這個變量值了,python就會自動銷毀它以釋放內存空間。
所以python的垃圾回收完全是自動檢測的,不會受到人為 del 的干預,完全是取決于你代碼下文是否用到這個變量。
二維數組生成的區別
我之前做過的跟棋盤有關的的游戲中需要生成一個12*12且全是0的二維數組,所以我很自然是使用了符合我氣質的超短生產法:[[0] * 12] * 12 ,結果不出意外的時候,出了意外,有個bug怎么看代碼怎么正確,但bug依舊存在。這讓我很抓狂,后來費勁千辛萬苦,才找到了罪惡的源頭——創建二維數組創建方法用錯了。
先來簡單輸出對比一下,更改某一二維度值后列表的變化:
結果:
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] [[0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0]]可以發現,l1 的改變是我們想要的結果,只更改了一個值;
但 l2 的結果令人意外,每個二維表的相同位置都變了…隨后我進行了大膽的嘗試:打印列表中每個值的 id ,看看每個 0 的 id 地址是否一致:
結果是意外的:
2426444079752 2426451175624 2426451175560 2426451193160 2426451090760 2426448839880 2426448839240 2426451176008 2426451385736 2426451170824 2426451385800 2426451385864 ---------------- 2426451385992 2426451385992 2426451385992 2426451385992 2426451385992 2426451385992 2426451385992 2426451385992 2426451385992 2426451385992 2426451385992 2426451385992可以發現第一種生成的列表的每一項,id值都不一樣,但第二種生成的列表的每一項 id 值都一樣,代表只要改變其中一個第二維數組,所有第二維數組都會跟著一起變!想想就可怕,以后在這種不能偷懶的地方還是不偷懶了…
淺拷貝與深拷貝
上一個例子為什么會這樣,原因很簡單,因為python中有兩種拷貝方式:
淺拷貝(copy):拷貝父對象,不會拷貝對象的內部的子對象。
深拷貝(deepcopy): copy 模塊的 deepcopy 方法,完全拷貝了父對象及其子對象。
然后上文又說到直接賦值,就其實是對對象的引用(別名)。
了解了這個,再來看上面例子的兩種二維表創建方式:
[0] * n 是淺拷貝,也就是把一個列表重復了n次,每一行的改變都會改變其他行;
[[0] * n] * m 這種方式是直接將[0] * n 復制了m遍;
[0 for _ in range(n)] 才是創建,是深拷貝。
所以其實上面還能這樣創建二維數組,這樣也能正確創建二維數組:
l = [[0] * 12 for _ in range(12)]因為創建全0數組,所以最深元素0肯定是一個 id ,要想多維數組正確創建,最多只能最里層數組是采用乘法復制的操作,來看個小栗子:
l1 = [[[0 for _ in range(6)] for _ in range(6)] for _ in range(6)] l2 = [[[0] * 6 for _ in range(6)] for _ in range(6)] l3 = [[[0] * 6] * 6 for _ in range(6)] l4 = [[[0] * 6] * 6] * 6 print(l1, l2, l3, l4, sep='\n') print('*******************************************') l1[1][2][3] = 4 l2[1][2][3] = 4 l3[1][2][3] = 4 l4[1][2][3] = 4 print(l1, l2, l3, l4, sep='\n')舉了四個小栗子,然后看看結果:
[[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]] [[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]] [[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]] [[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]] ******************************************* [[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]] [[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]] [[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]] [[[0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0]], [[0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0]], [[0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0]], [[0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0]], [[0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0]], [[0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0], [0, 0, 0, 4, 0, 0]]]看著可能有點密密麻麻,但可以 Ctrl + F 查找一下數字 4 ,會發現只有第一、第二種創建方式是我們想要的,其他都出現了問題,所以偷懶最多偷一點,偷懶多了就得不償失了~
從列表中分離奇數和偶數
首先,隨便整一堆數字:
numbers = [12, 23, 34, 45, 56, 67, 78, 89]一般人的做法:
jishu, oushu = [], [] for num in numbers:if num % 2:jishu.append(num)else:oushu.append(num) print(jishu) print(oushu)結果:
[23, 45, 67, 89] [12, 34, 56, 78]這是別人問過的問題,所以這里放上別人看的PPT上的解答:
奇數偶數都分離出來了不錯,但用了8行,這不是我想要的 (手動滑稽) ~
我作為一個有知識的博主,肯定要挑戰一行代碼實現他!
上代碼:
別看他長,代碼是真的只有一行,奇數偶數的分類以及輸出全都一行搞定,當中lambda主體的兩個列表是假的,主要用來列表推導循環獲取一下(他執行完后應該會自動當垃圾清理掉的吧),然后靠 and 后輸出兩個列表,然后在 pint 中解包,并設置 sep 參數換行輸出,結果和上面一模一樣。
什么?你嫌棄這太長了?沒關系!我還有一個簡短版本的,使用了內置函數 filter ,非常好用!
print(list(filter(lambda _: _ % 2, [12, 23, 34, 45, 56, 67, 78, 89])), list(filter(lambda _: not _ % 2, [12, 23, 34, 45, 56, 67, 78, 89])), sep='\n')比上面的至少少了十幾個字符呢 (此處應有掌聲!) ~
filter 這個函數可以理解為一個功能 “條件格式” ,用于過濾序列。當滿足條件(第一個參數為 True )時,他會返回遍歷到的元素,否則不返回。(關于高階函數,以后有機會更新【比如下一篇?】)
因為這個遍歷返回的是可迭代對象,要強迫它立刻完成,那就用 list(filter()) ,讓它直接出結果。
從列表中提取公共信息轉換成字典
這仍然是解答別人問題時候的一個小栗子:
var = [['王*龍', '北京市海淀區蘇州街大恒科技大廈南座4層'],['龐*飛', '北京市昌平區匯德商廈四樓403'],['顧*銳', '江蘇省揚州市三垛鎮工業集中區揚州市立華畜禽有限公司'],['王*飛', '上海市徐匯區上海市徐匯區H88越虹廣場B座5E'],['華*升', '北京市海淀區杰睿大廈'],['朱*鍇', '上海市浦東新區川沙新鎮華川家園33號樓503'],['陳*盼', '浙江省杭州市閑林街道,西溪華東園,十幢一單元401。'],['司*鵬', '河南省鶴壁市淇濱大道310號 鶴壁京立醫院'],['聶*睿', '河北省石家莊市中山路勒泰中心寫字樓b座11層'],['張*', '遼寧省本溪市明興麗城九號樓四單元'],['冉*晗', '河北省石家莊市體育南大街385號'],['高*杰', '北京市朝陽區廣渠路42號院3號樓,408'],['李*國', '安徽省合肥市新站區淮合花園'],['常*源', '江蘇省南京市白下路242號,南京市紅十字醫院,放射科'],['張*玉', '河北省滄州市新居然家居廣場'],['王*川', '上海市奉賢區南橋鎮 貝港七區'],['冀*慶', '河北省保定市河北大學坤興園生活區'],['胡*晨', '浙江省寧波市浙江省寧波市江東區中山首府A座2004室'],['尹*婷', '湖北省武漢市武漢大學信息學部'],['李*東', '遼寧省大連市大關一街3號3-3-1'],['張*', '天津市河西區隆昌路94號(天津科技館)'],['劉*', '湖北省黃岡市城關鎮'],['阿*亞', '內蒙古呼和浩特市包頭東接民望家園1區3號樓2單元1501'],['孫*云', '山東省濟南市山東省濟南市歷下區祥泰匯東國際,一號樓3005室'],['曹*亮', '黑龍江省大慶市服務外包產業園D1'],['侯*琦', '上海市長寧區金鐘路凌空soho16號樓3樓'],['郭*峰', '河南省商丘市高新技術開發區恒宇食品廠'],['趙*生', '河北省唐山市朝陽道與學院路路口融通大廈2408室'],['張*', '陜西省咸陽市文匯東路6號西藏民族大學'],['劉*民', '北京市大興區南海家園四里7號樓1單元902'],['郭*蘭', '湖北省武漢市湖北省'],['張*強', '河北省張家口市經開區鉆石南路11號'],['鞠*龍', '山東省濰坊市玉清街江山帝景B區12號樓一單元14樓'],['李*', '北京市海淀區西二旗智學苑5號樓超市'],['許*康', '北京市西城區西單北大街甲133號'],['葉*生', '江蘇省揚州市揚子江中路756號'],['趙*興', '北京市海淀區西二旗上地信息路1號金遠見大樓華緯訊301'],['徐*革', '北京市海淀區閔莊路3號102棟二層206'],['徐*', '安徽省淮南市金荷小區(金格商場旁)'],['雷*', '北京市朝陽區望京街道望京sohoT1C座1201'],['莊*', '浙江省杭州市恒生電子大廈'],['蔡*恩', '湖北省武漢市仁和路沙湖港灣B區1103'],['陳*', '江蘇省蘇州市巴城鎮湖濱北路193號牛吃蟹莊'],['黃*', '北京市朝陽區霄云路26號鵬潤大廈A座33層'],['魏*飛', '河北省石家莊市新石北路與紅旗大街交口開元大廈502室'],['張*', '山東省濟南市興港路三慶城市主人'],['段*琪', '山西省臨汾市福利路堯鄉小區'],['劉*', '北京市昌平區龍禧三街驪龍園601'],['王*生', '上海市楊浦區邯鄲路復旦大學遺傳學樓319室'],['王*君', '江蘇省揚州市葉挺路318號建行營業部'],['王*義', '北京市東城區環球貿易中心D座'],['李*', '陜西省漢中市同溝寺鎮晨光村二組'],['裴*宇', '吉林省四平市嶺西新耀豪庭7棟'],['丁*', '山東省煙臺市大季家鎮蘆洋村'],['劉*鐸', '黑龍江省佳木斯市火電小區橋頭浴池附近惠惠干洗店'],['樊*', '浙江省寧波市文苑風荷201-301'],['陳*瑞', '安徽省宣城市安徽省宣城市宣州區薰化路301合肥工業大學宣城校區'],['崔*峰', '浙江省臺州市福溪街道始豐西路43號501室'],['徐*', '湖北省武漢市三金雄楚天地1號樓1210'],['王*', '浙江省寧波市浙江工商職業技術學院信息中心'],['閆*', '上海市浦東新區藍天路368弄1號301室'],['于*泉', '吉林省四平市金星書苑小區8號樓5單元102室'],['劉*萌', '河北省秦皇島市撫寧鎮交通局家屬院3-2-201'],['石*', '安徽省宣城市薰化路301'],['王*雯', '甘肅省蘭州市天水南路222號蘭州大學'],['王*朝', '河南省鄭州市嵩山南路政通路升龍城六號院'],['金*晶', '吉林省延邊州延吉市新興街民安委11'],['蔣*彬', '遼寧省本溪市新城北岸,恒大綠洲'],['牛*鑫', '黑龍江省雞西市南山路康光二號樓中雅發廊'],['陳*宏', '山西省太原市太原理工大學'],['劉*', '山西省運城市卿頭鎮'],['陳*杰', '浙江省寧波市高新區研發園A5幢7樓多維時空科技有限公司'],['郝**', '山東省德州市焦廟鎮'],['焦*', '山西省長治市太行西街金威超市太西店金威快購辦公室'],['李*旗', '北京市昌平區沙河鎮匯德商廈4樓403老男孩教育'],['通*大都', '北京市豐臺區萬泉寺東路9號院1棟1單1704'],['孫*川', '浙江省金華市佛堂鎮雅西村雙溪口便民超市'],['宋*', '安徽省合肥市上派鎮濱河家園9棟2102'],['李*', '陜西省安康市漢濱區新城街道南環東路口桃園小區大門口'],['李*連', '北京市昌平區立湯路北七家威尼斯花園2區2-3'],['籍*旭', '北京市房山區良鄉鴻順園西區20號樓3單元601'],['韓*嵩', '北京市昌平區立湯路威尼斯花園2區2-3'],['曹*', '北京市朝陽區東三環北路28號博瑞大廈B座'],['賀*', '上海市徐匯區古美路1515號19號樓1101室'],['關*軒', '山西省長治市石哲鎮'],['羅*', '河北省廊坊市書香苑小區四號樓'],['段**', '北京市朝陽區酒仙橋東路M5世紀互聯'],['杜*偉', '北京市昌平區匯德商廈老男孩教育'],['王*', '北京市昌平區匯德商廈四樓'],['趙*波', '上海市閔行區上海市閔行區莘莊鎮廟涇路水清三村52號32弄402室'],['許*', '北京市海淀區西北旺鎮中海楓漣山莊北門對面中心'],['李*成', '北京市昌平區沙河鎮于辛莊村天利合家園'],['劉*', '江蘇省南京市興智路6號興智科技園A棟7層'],['張*濤', '安徽省合肥市安徽省合肥市廬陽區壽春路156號古井百花大廈大廈A座2603'],['高*', '上海市虹口區歐陽路351弄10號樓104室'],['谷*成', '浙江省杭州市城廂街道 下湘湖路1號'],['王*玉', '上海市嘉定區南翔鎮'],['劉*海', '北京市海淀區玉淵潭南路3號水科院萬方城科技樓'],['楊*娟', '安徽省合肥市清源路中鐵國際城和暢園'],['謝*橋', '北京市海淀區豐秀中路3號院9號樓北京數碼大方科技股份有限公司'],['張*', '陜西省咸陽市北上召秦楚汽車城別克雪佛蘭4s店'],['邵*龍', '北京市海淀區西北旺鎮大牛坊社區四期4號樓1單元301'],['耿*濤', '北京市朝陽區三間房東柳巷甲一號意菲克大廈A座'],['孫*周', '北京市東城區東花市街道便宜坊寫字樓10層,恒信通大廈。就在崇文門地鐵站口旁邊'],['于*涵', '山東省濟南市舜耕路舜耕山莊宿舍'],['陳*', '上海市普陀區近鐵城市廣場北座15樓'],['馬*', '北京市昌平區沙河鎮松蘭堡村西口興業家園6號樓'],['齊*', '江蘇省南京市天元東路228號萊茵量子國際'],['高*', '山西省太原市經濟技術開發區龍盛街2號國藥控股'],['劉*', '北京市海淀區中關村丹棱街中國電子大廈B座1608'],['陳*山', '安徽省六安市南港鎮'],['趙*', '黑龍江省哈爾濱市錦山路5號,黑龍江省地質科學研究所'],['伍*', '安徽省蕪湖市泉塘鎮'],['白*潮', '上海市浦東新區康橋鎮環橋路2585弄文怡苑一期27號樓301'],['黃*曦', '北京市朝陽區西壩河南路3號2層201室 同創雙子信息技術股份有限公司'],['牟*強', '山東省日照市山東東路619號 廣電網絡公司'],['李*運', '上海市松江區滬亭南路208弄109號801室'],['楊*', '北京市朝陽區安苑路20號世紀興源大廈304'],['宋*偉', '河北省石家莊市高頭鄉西高村'],['任*鵬', '陜西省西安市錦業一路29號 龍旗科技園 6層 西安和利時系統工程有限公司'],['孫*洲', '北京市東城區東花市街道便宜坊寫字樓10層,恒信通公司。就在崇文門地鐵站旁邊'],['張*義', '上海市浦東新區三舒路181弄2號904'],['門*意', '黑龍江省哈爾濱市文昌街238號聯通系統集成有限公司'],['楊*康', '北京市豐臺區豐臺科技園漢威廣場12棟'] ]這么一大段數據,最后要根據省份變成字典,如圖:
忽略掉對方是編程小白這個因素,這個是很簡單的對吧🤣~
import jsonvar_dict = {} for v in var:var_dict[v[1][:3]] = var_dict.get(v[1][:3], [])var_dict[v[1][:3]].append(v) print(json.dumps({k: [str(i) for i in v] for k, v in var_dict.items()}, indent=4, ensure_ascii=False).replace('"[', '[').replace(']"', ']'))這里的 var_dict[v[1][:3]] = var_dict.get(v[1][:3], []) 我感覺用的很巧,如果鍵值不存在就自動創建,存在就賦值為原來的值,省去了 if 的兩行(但好像犧牲了些許性能),然后下面就可以放心肯定是列表而不會是 None 了。
你看 print 那里好像有點長,其實就是在轉字符串,為什么要將列表轉成字符串呢?因為不轉換成字符串的話,列表元素會自動換行,就像這樣:
為了貼合它給的示例,所以就要讓列表變成一個個的字符串,這樣就能在一行內顯示了,最后記得把列表外面的引號去掉。
這叫什么,這就叫細節!
如果接下來不再使用這個字典,只是為了打印,那可以從上面入手轉換:
這就少了不少代碼了,完成!
模擬有密碼輸入次數的登錄系統
這還是別人請教我的一個問題,讓我看看他的代碼有沒有問題,我忘了他原來發的代碼是什么了,不過我記得他是 賬號或密碼為空 的時候仍然扣除次數,這樣肯定是不對, 于是我改后的代碼如下:
ctrl = 3 while 1 <= ctrl <= 3:x, y = input("請輸入賬號:"), input("請輸入密碼:")if x == '' or x == ' ' or y == '' or y == ' ':print("警告,賬號或密碼不能為空")elif x != 'admin' or y != '123':ctrl -= 1print(f'輸入錯誤請重新輸入,你還有{ctrl}次機會')else:print(x, '歡迎登錄')break僅在輸入不為空且賬號或密碼不對的時候次數減少,這樣的邏輯就是對的。
現在滿足他了,缺不滿足我了。為啥?這代碼這么長,11行的代碼!這看著太多了,對于縮減王的我來說,這要能壓縮到5行以內才有挑戰性:
可惜了我最大只能縮減到5行,如果是python3.10以上的話,我還能憑借海象運算符( := ,先賦值后判斷)又減少至少一行代碼~
計算1-100內的奇數和、代碼執行時間計時
這又又又是別人請教我的一個問題,應該已經麻木了,不然我也不會想到要出此一期合集。
正常人寫代碼:
像我一樣的非正常博主寫代碼:
from functools import reduce print(sum([_ for _ in range(1, 100, 2)])) print(sum([_ for _ in range(1, 100) if _ % 2])) print(sum([_ * (_ % 2) for _ in range(1, 100)])) print(sum([_ if _ % 2 else 0 for _ in range(1, 100)])) print(reduce(lambda _, __: _ + __, [_ for _ in range(1, 100, 2)])) print(reduce(lambda _, __: _ + __, [_ for _ in range(1, 100) if _ % 2])) print(reduce(lambda _, __: _ + __ * (__ % 2), [_ for _ in range(1, 100)])) print(reduce(lambda _, __: _ + __, [_ if _ % 2 else 0 for _ in range(1, 100)]))分分鐘給他寫一堆一行就能完成的不同方案的代碼(如果細小改變也能稱之為新方法的話),一會 sum ,一會 range 里分奇偶,一會列表推導式分奇偶,一會遍歷元素處分奇偶,一會 reduce 配合上面幾種分奇偶。(實際感覺也就四種小方法和兩種大方法混合使用,但我就覺得他們不一樣!)
但別人跟我說,你代碼短沒用,說不定執行速度沒我快,我心一沉,還真沒考慮,現在就來測一下他們的執行速度:
import timeittests = """ sum([_ for _ in range(1, 100, 2)]) sum([_ for _ in range(1, 100) if _ % 2]) sum([_ * (_ % 2) for _ in range(1, 100)]) sum([_ if _ % 2 else 0 for _ in range(1, 100)]) __import__('functools').reduce(lambda _, __: _ + __, [_ for _ in range(1, 100, 2)]) __import__('functools').reduce(lambda _, __: _ + __, [_ for _ in range(1, 100) if _ % 2]) __import__('functools').reduce(lambda _, __: _ + __ * (__ % 2), [_ for _ in range(1, 100)]) __import__('functools').reduce(lambda _, __: _ + __, [_ if _ % 2 else 0 for _ in range(1, 100)]) """.strip('\n')for test in tests.split('\n'):print(timeit.timeit(stmt=test, number=100000))接下來運行多次測試,結果如下:
這里就貼了隨機三次的測試,發現不僅代碼長度越來越長了,執行速度還越來越慢了。
幾次測試下來,第一種方法不僅穩,而且速度快,難怪能成為內置函數。那么問題來了,sum 函數和正常寫多行代碼來比呢?
同樣取三次結果:
發現還是 sum 穩如老狗,而且速度很快。
以后就不要說代碼寫一行速度會變慢了,內置函數還是很好用的!
二層列表轉單層列表、代碼執行時間計時
這實際上是我很久以前的需求了,我肯定會要求一行代碼實現,不然就不會有這個話題了。
import timeitpoke = [[f'{_ + 1}_{__ + 1}' for __ in range(4)] if _ < 13 else [str(_ + 1)] for _ in range(15)] tests = f""" poke_list = [];list(map(poke_list.extend, {poke})) poke_list = sum({poke}, []) poke_list = __import__('functools').reduce(list.__add__, {poke}) poke_list = list(__import__('itertools').chain(*{poke})) poke_list = (lambda _, __ = eval("[]"): __.clear() or [[__.append(____) for ____ in ___ if ____] for ___ in _] and __)({poke}) """.strip('\n')for test in tests.split('\n'):print(timeit.timeit(stmt=test, number=100000))還是老樣子,測試三次數據:
所有方法實際使用代碼如下:
poke = [[f'{_ + 1}_{__ + 1}' for __ in range(4)] if _ < 13 else [str(_ + 1)] for _ in range(15)] print(poke) poke_list = [];list(map(poke_list.extend, poke)) print(poke_list) poke_list = sum(poke, []) print(poke_list) poke_list = __import__('functools').reduce(list.__add__, poke) print(poke_list) poke_list = [_ for __ in poke for _ in __] print(poke_list) poke_list = list(__import__('itertools').chain(*poke)) print(poke_list) poke_list = (lambda _, __=eval("[]"): __.clear() or [[__.append(____) for ____ in ___ if ____] for ___ in _] and __)(poke) print(poke_list)發現第一種測試起來不僅穩,還比其他快一截,雖然他寫的不優雅…
然而最后的 lambda 函數是我之前用的,現在一看用時這么長…果然長的代碼可能用的時間長…
我現在就感覺我的生命白白浪費了那么多秒!
發撲克小程序
我看到代碼的下面,才發現原來上面都是鋪墊,下面這個功能才是正題,依然是別人問我的,上面只是為了生成一副撲克牌而已…
不多說,上代碼,這里采用已經轉換成一位數組的列表直接賦值:
這個程序呢,我就沒什么好解釋的了,這我感覺沒錯的話,只是個半成品,要么就是我沒搞懂別人搞這程序想干啥,不過這都不重要
總結
以上是生活随笔為你收集整理的【Python实践】Python部分实际案例解答1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 利用Adams对单摆进行建模、仿真的动力
- 下一篇: python航空订票系统_航空订票系统