python3 cookbook中常遇問(wèn)題解答
數(shù)據(jù)結(jié)構(gòu)與算法
將序列分解為單獨(dú)的變量
問(wèn)題:現(xiàn)在有一個(gè)包含 N 個(gè)元素的元組或者是序列,怎樣將它里面的值解壓后同時(shí)賦值給 N 個(gè)變量?
解答:任何的序列(或者是可迭代對(duì)象)可以通過(guò)一個(gè)簡(jiǎn)單的賦值操作來(lái)分解為單獨(dú)的變量。 唯一的要求就是變量的總數(shù)和結(jié)構(gòu)必須與序列相吻合。
代碼示例:(當(dāng)前環(huán)境為python3.8版本)
p = (1, 2) x, y = p x ? # 1 y ? # 2 data = [ 'ABC', 20, 51.1, (2023, 2, 5) ] name, age, price, date = data name ?# 'ABC' date ?# ?(2023, 2, 5)
解壓可迭代對(duì)象賦值給多個(gè)變量
問(wèn):如果一個(gè)可迭代對(duì)象的元素個(gè)數(shù)超過(guò)變量個(gè)數(shù)時(shí),會(huì)拋出一個(gè) ValueError。 那么怎樣才能從這個(gè)可迭代對(duì)象中解壓出 N 個(gè)元素出來(lái)?
解答:Python 的星號(hào)表達(dá)式可以用來(lái)解決這個(gè)問(wèn)題。比如,你在學(xué)習(xí)一門(mén)課程,在學(xué)期末的時(shí)候, 你想統(tǒng)計(jì)下家庭作業(yè)的平均成績(jī),但是排除掉第一個(gè)和最后一個(gè)分?jǐn)?shù)。如果只有四個(gè)分?jǐn)?shù),你可能就直接去簡(jiǎn)單的手動(dòng)賦值, 但如果有 24 個(gè)呢?這時(shí)候星號(hào)表達(dá)式就派上用場(chǎng)了。
def drop_first_last(grades): first, *middle, last = grades return avg(middle)
另外一種情況,假設(shè)你現(xiàn)在有一些用戶的記錄列表,每條記錄包含一個(gè)名字、郵件,接著就是不確定數(shù)量的電話號(hào)碼。 你可以像下面這樣分解這些記錄:
record = ('Dave', 'dave@example.com', '773-555-1212', '847-555-1212') name, email, *phone_numbers = record name # 'Dave' email # 'dave@example.com' phone_numbers # ['773-555-1212', '847-555-1212']
值得注意的是上面解壓出的 phone_numbers 變量永遠(yuǎn)都是列表類型,不管解壓的電話號(hào)碼數(shù)量是多少(包括 0 個(gè))。
查找最大或最小的 N 個(gè)元素
問(wèn)題:怎樣從一個(gè)集合中獲得最大或者最小的 N 個(gè)元素列表?
解答:heapq 模塊有兩個(gè)函數(shù):nlargest() 和 nsmallest() 可以完美解決這個(gè)問(wèn)題。
import heapq nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2] print(heapq.nlargest(3, nums)) # Prints [42, 37, 23] print(heapq.nsmallest(3, nums)) # Prints [-4, 1, 2]
兩個(gè)函數(shù)都能接受一個(gè)關(guān)鍵字參數(shù),用于更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)中:
portfolio = [ {'name': 'IBM', 'shares': 100, 'price': 91.1}, {'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'FB', 'shares': 200, 'price': 21.09}, {'name': 'HPQ', 'shares': 35, 'price': 31.75}, {'name': 'YHOO', 'shares': 45, 'price': 16.35}, {'name': 'ACME', 'shares': 75, 'price': 115.65} ] cheap = heapq.nsmallest(3, portfolio, key=lambda s: s['price']) cheap # [{'name': 'YHOO', 'shares': 45, 'price': 16.35}, {'name': 'FB', 'shares': 200, 'price': 21.09},{'name': 'HPQ', 'shares': 35, 'price': 31.75}] expensive = heapq.nlargest(3, portfolio, key=lambda s: s['price']) expensive # [{'name': 'AAPL', 'shares': 50, 'price': 543.22},{'name': 'ACME', 'shares': 75, 'price': 115.65}, {'name': 'IBM', 'shares': 100, 'price': 91.1}]
字典的運(yùn)算
問(wèn)題:怎樣在數(shù)據(jù)字典中執(zhí)行一些計(jì)算操作(比如求最小值、最大值、排序等等)?
解答:考慮下面的股票名和價(jià)格映射字典
prices = { 'ACME': 45.23, 'AAPL': 612.78, 'IBM': 205.55, 'HPQ': 37.20, 'FB': 10.75 }
為了對(duì)字典值執(zhí)行計(jì)算操作,通常需要使用 zip() 函數(shù)先將鍵和值反轉(zhuǎn)過(guò)來(lái)。 比如,下面是查找最小和最大股票價(jià)格和股票值的代碼:
min_price = min(zip(prices.values(), prices.keys())) # min_price is (10.75, 'FB') max_price = max(zip(prices.values(), prices.keys())) # max_price is (612.78, 'AAPL')
類似的,可以使用 zip() 和 sorted() 函數(shù)來(lái)排列字典數(shù)據(jù):
prices_sorted = sorted(zip(prices.values(), prices.keys())) # prices_sorted is [(10.75, 'FB'), (37.2, 'HPQ'), # (45.23, 'ACME'), (205.55, 'IBM'), # (612.78, 'AAPL')]
執(zhí)行這些計(jì)算的時(shí)候,需要注意的是 zip() 函數(shù)創(chuàng)建的是一個(gè)只能訪問(wèn)一次的迭代器。 比如,下面的代碼就會(huì)產(chǎn)生錯(cuò)誤:
prices_and_names = zip(prices.values(), prices.keys()) print(min(prices_and_names)) # (10.75, 'FB') print(max(prices_and_names)) # ValueError: max() arg is an empty sequence
查找兩字典的相同點(diǎn)
問(wèn)題:怎樣在兩個(gè)字典中尋找相同點(diǎn)(比如相同的鍵、相同的值等等)?
解答:考慮下面兩個(gè)字典
a = { ? ? 'x' : 1, ? ? 'y' : 2, ? ? 'z' : 3 } b = { ? ? 'w' : 10, ? ? 'x' : 11, ? ? 'y' : 2 }
為了尋找兩個(gè)字典的相同點(diǎn),可以簡(jiǎn)單的在兩字典的 keys() 或者 items() 方法返回結(jié)果上執(zhí)行集合操作。比如:
# Find keys in common a.keys() & b.keys() # { 'x', 'y' } # Find keys in a that are not in b a.keys() - b.keys() # { 'z' } # Find (key,value) pairs in common a.items() & b.items() # { ('y', 2) }
這些操作也可以用于修改或者過(guò)濾字典元素。 比如,假如你想以現(xiàn)有字典構(gòu)造一個(gè)排除幾個(gè)指定鍵的新字典。 下面利用字典推導(dǎo)來(lái)實(shí)現(xiàn)這樣的需求:
# Make a new dictionary with certain keys removed c = {key:a[key] for key in a.keys() - {'z', 'w'}} # c is {'x': 1, 'y': 2}
序列中出現(xiàn)次數(shù)最多的元素
問(wèn)題:怎樣找出一個(gè)序列中出現(xiàn)次數(shù)最多的元素呢?
解答:collections.Counter 類就是專門(mén)為這類問(wèn)題而設(shè)計(jì)的, 它甚至有一個(gè)有用的 most_common() 方法直接給了你答案。
先假設(shè)你有一個(gè)單詞列表并且想找出哪個(gè)單詞出現(xiàn)頻率最高。你可以這樣做:
words = [ 'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes', 'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the', 'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into', 'my', 'eyes', "you're", 'under' ] from collections import Counter word_counts = Counter(words) # 出現(xiàn)頻率最高的3個(gè)單詞 top_three = word_counts.most_common(3) print(top_three) # Outputs [('eyes', 8), ('the', 5), ('look', 4)]
通過(guò)某個(gè)字段將記錄分組
問(wèn)題:你有一個(gè)字典或者實(shí)例的序列,然后你想根據(jù)某個(gè)特定的字段比如 date 來(lái)分組迭代訪問(wèn)。
解答:itertools.groupby() 函數(shù)對(duì)于這樣的數(shù)據(jù)分組操作非常實(shí)用。 假設(shè)你已經(jīng)有了下列的字典列表:
rows = [ {'address': '5412 N CLARK', 'date': '07/01/2012'}, {'address': '5148 N CLARK', 'date': '07/04/2012'}, {'address': '5800 E 58TH', 'date': '07/02/2012'}, {'address': '2122 N CLARK', 'date': '07/03/2012'}, {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'}, {'address': '1060 W ADDISON', 'date': '07/02/2012'}, {'address': '4801 N BROADWAY', 'date': '07/01/2012'}, {'address': '1039 W GRANVILLE', 'date': '07/04/2012'}, ]
現(xiàn)在假設(shè)你想在按 date 分組后的數(shù)據(jù)塊上進(jìn)行迭代。為了這樣做,你首先需要按照指定的字段(這里就是date)排序, 然后調(diào)用 itertools.groupby() 函數(shù):
from operator import itemgetter from itertools import groupby # Sort by the desired field first rows.sort(key=itemgetter('date')) # Iterate in groups for date, items in groupby(rows, key=itemgetter('date')): ? ? print(date) ? ? for i in items: ? ? ? ? print(' ', i)
運(yùn)行結(jié)果:
07/01/2012
{'date': '07/01/2012', 'address': '5412 N CLARK'}
{'date': '07/01/2012', 'address': '4801 N BROADWAY'}
07/02/2012
{'date': '07/02/2012', 'address': '5800 E 58TH'}
{'date': '07/02/2012', 'address': '5645 N RAVENSWOOD'}
{'date': '07/02/2012', 'address': '1060 W ADDISON'}
07/03/2012
{'date': '07/03/2012', 'address': '2122 N CLARK'}
07/04/2012
{'date': '07/04/2012', 'address': '5148 N CLARK'}
{'date': '07/04/2012', 'address': '1039 W GRANVILLE'}
過(guò)濾序列元素
問(wèn)題:你有一個(gè)數(shù)據(jù)序列,想利用一些規(guī)則從中提取出需要的值或者是縮短序列。
解答:最簡(jiǎn)單的過(guò)濾序列元素的方法就是使用列表推導(dǎo)。比如:
mylist = [1, 4, -5, 10, -7, 2, 3, -1] [n for n in mylist if n > 0] # [1, 4, 10, 2, 3] [n for n in mylist if n < 0] # [-5, -7, -1]
有時(shí)候,過(guò)濾規(guī)則比較復(fù)雜,不能簡(jiǎn)單的在列表推導(dǎo)或者生成器表達(dá)式中表達(dá)出來(lái)。 比如,假設(shè)過(guò)濾的時(shí)候需要處理一些異?;蛘咂渌麖?fù)雜情況。這時(shí)候你可以將過(guò)濾代碼放到一個(gè)函數(shù)中, 然后使用內(nèi)建的 filter() 函數(shù)。示例如下:
values = ['1', '2', '-3', '-', '4', 'N/A', '5'] def is_int(val): try: x = int(val) return True except ValueError: return False ivals = list(filter(is_int, values)) print(ivals) # Outputs ['1', '2', '-3', '4', '5']
filter() 函數(shù)創(chuàng)建了一個(gè)迭代器,因此如果你想得到一個(gè)列表的話,就得像示例那樣使用 list() 去轉(zhuǎn)換。
轉(zhuǎn)換并同時(shí)計(jì)算數(shù)據(jù)
問(wèn)題:你需要在數(shù)據(jù)序列上執(zhí)行聚集函數(shù)(比如 sum() , min() , max()), 但是首先你需要先轉(zhuǎn)換或者過(guò)濾數(shù)據(jù)
解答:一個(gè)非常優(yōu)雅的方式去結(jié)合數(shù)據(jù)計(jì)算與轉(zhuǎn)換就是使用一個(gè)生成器表達(dá)式參數(shù)。 比如,如果你想計(jì)算平方和,可以像下面這樣做:
nums = [1, 2, 3, 4, 5] s = sum(x * x for x in nums)
下面是更多的例子:
# Determine if any .py files exist in a directory import os files = os.listdir('dirname') if any(name.endswith('.py') for name in files): print('There be python!') else: print('Sorry, no python.') # Output a tuple as CSV s = ('ACME', 50, 123.45) print(','.join(str(x) for x in s)) # Data reduction across fields of a data structure portfolio = [ {'name':'GOOG', 'shares': 50}, {'name':'YHOO', 'shares': 75}, {'name':'AOL', 'shares': 20}, {'name':'SCOX', 'shares': 65} ] min_shares = min(s['shares'] for s in portfolio)
合并多個(gè)字典或映射
問(wèn)題:現(xiàn)在有多個(gè)字典或者映射,你想將它們從邏輯上合并為一個(gè)單一的映射后執(zhí)行某些操作, 比如查找值或者檢查某些鍵是否存在。
解答:假如你有如下兩個(gè)字典
a = {'x': 1, 'z': 3 } b = {'y': 2, 'z': 4 }
現(xiàn)在假設(shè)你必須在兩個(gè)字典中執(zhí)行查找操作(比如先從 a 中找,如果找不到再在 b 中找)。 一個(gè)非常簡(jiǎn)單的解決方案就是使用 collections 模塊中的 ChainMap 類。比如:
from collections import ChainMap c = ChainMap(a,b) print(c['x']) # Outputs 1 (from a) print(c['y']) # Outputs 2 (from b) print(c['z']) # Outputs 3 (from a)
到此這篇關(guān)于python3 cookbook中常遇問(wèn)題解答的文章就介紹到這了,更多相關(guān)python3 cookbook問(wèn)題內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)實(shí)現(xiàn)查找兩個(gè)字典相同點(diǎn)的方法
- Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)找出序列中出現(xiàn)次數(shù)最多的元素算法示例
- Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)篩選及提取序列中元素的方法
- Python cookbook(字符串與文本)針對(duì)任意多的分隔符拆分字符串操作示例
- Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)讓字典保持有序的方法
- Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)保存最后N個(gè)元素的方法
- Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)字典相關(guān)計(jì)算問(wèn)題示例
相關(guān)文章
教你如何編寫(xiě)、保存與運(yùn)行Python程序的方法
這篇文章主要介紹了教你如何編寫(xiě)、保存與運(yùn)行Python程序的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07使用selenium和pyquery爬取京東商品列表過(guò)程解析
這篇文章主要介紹了使用selenium和pyquery爬取京東商品列表過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08余弦相似性計(jì)算及python代碼實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了余弦相似性計(jì)算及python代碼實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09Python使用matplotlib繪制正弦和余弦曲線的方法示例
這篇文章主要介紹了Python使用matplotlib繪制正弦和余弦曲線的方法,結(jié)合實(shí)例形式分析了Python調(diào)用matplotlib庫(kù)進(jìn)行圖形繪制想具體操作技巧,需要的朋友可以參考下2018-01-01Python腳本開(kāi)發(fā)中的命令行參數(shù)及傳參示例詳解
這篇文章主要為大家介紹了Python腳本開(kāi)發(fā)中的命令行參數(shù)及傳參示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07Python存儲(chǔ)json數(shù)據(jù)發(fā)生亂碼的解決方法
當(dāng)使用json.dump()把python對(duì)象轉(zhuǎn)換為json后存儲(chǔ)到文件中時(shí),文件可能會(huì)出現(xiàn)亂碼的問(wèn)題,本篇文章可以幫助您解決亂碼問(wèn)題,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09Python中的復(fù)制操作及copy模塊中的淺拷貝與深拷貝方法
淺拷貝和深拷貝是Python基礎(chǔ)學(xué)習(xí)中必須辨析的知識(shí)點(diǎn),這里我們將為大家解析Python中的復(fù)制操作及copy模塊中的淺拷貝與深拷貝方法:2016-07-07