亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python序列操作之進階篇

系統 1521 0

簡介

Python 的序列(sequence)通常指一個可迭代的容器,容器中可以存放任意類型的元素。列表和元組這兩種數據類型是最常被用到的序列,python內建序列有六種,除了剛剛有說過的兩種類型之外,還有字符串、Unicode字符串、buffer對像和最后一種xrange對像,這幾種都是不常使用的。本文講解了列表推導式、切片命名、列表元素排序、列表元素分組的使用方法。學習了 Python 基本的列表操作后,學習這些進階的操作,讓我們寫出的代碼更加優雅簡潔和 pythonic 。

列表推導式

當我們想要根據某些規則來構造一個列表時,首先想到的應該是列表推導式。列表推導式簡化了循環操作,例如我們想要從一個原始文件名列表中獲取全部 .py 文件,在沒有列表推導式的情況下,我們通常會這樣做:

            
file_list = ['foo.py', 'bar.txt', 'spam.py', 'animal.png', 'test.py']
py_list = []
for file in file_list:
if file.endswith('.py'):
py_list.append(file)

print(py_list)
# output
['foo.py', 'spam.py', 'test.py']
          

而如果使用列表推導式則可簡化為:

            
py_list = [f for f in file_list if f.endswith('.py')]
print(py_list)
# output
['foo.py', 'spam.py', 'test.py']
          

列表推導式的介紹網上資源很多,不再贅述。這里只強調,當你需要根據某個規則來構造一個列表時,首先應該想一想,能否使用簡潔的列表推導式來實現該需求,否則再回到常規的方式。

為切片命名

Python 的列表切片使用起來非常方便,但有時也會影響代碼可讀性。例如有一個字符串:

            
record = '..........19.6..........100..........'
          

19.6 為產品價格,100 為產品數量,那么計算總價格為:

但是如果這樣寫,可能過一段時間我們再來讀代碼時已經忘記了 record[10:14] record[24:27] 切出來的究竟是什么?為了解決上述問題,可以給切片命個名來增強可讀性。

            
record = '..........19.6..........100..........'
price = slice(10, 14)
count = slice(24, 27)
total_price = float(record[price])*int(record[count])
          

slice 接收的參數格式為 slice(stop) slice(start, stop[, step]) 。如果只接收了一個參數,則等價于切片語法 [:stop] ,如果接收兩個參數,則等價于切片語法 [start:stop] ,如果接收三個參數,則等價于切片語法 [start:stop:step]

排序

排序相關的任務通常由內置函數 sorted 完成。需要排序的元素一般存放在一個列表容器中,列表可以存放任意類型的元素,而 sorted 函數的 key 關鍵字使得我們能夠輕松地指定元素排序的關鍵字,讓排序變得異常簡單。下面將給出幾個常見的排序例子以說明 key 關鍵字的使用方法。注意 Python3 和 Python2 的排序方法不能通用,下面的例子只適用于 Python3 ,Python2 的排序方法未包含在本文中。

情況一

列表中的元素已經是可比較元素,直接將列表傳入 sorted 函數即可返回一個已排序列表。默認為升序排列,降序排列可以指定 reverse 參數,例如:

            
>>> l = [3,5,4,1,8]
>>> sorted(l)
[1, 3, 4, 5, 8]
>>> sorted(l, reverse=True)
[8, 5, 4, 3, 1]
>>>
          

情況二

需要排序的元素是一個元組或者字典,希望根據我指定的關鍵字來排序,例如有如下兩個列表:

            
l_v1 = [('b',2),('a',1),('c',3),('d',4)]
l_v2 = [
 {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
 {'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
 {'fname': 'John', 'lname': 'Cleese', 'uid': 1001},
 {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
]
          

l_v1 是一個元組列表, l_v2 是一個字典列表。對 l_v1 我們希望根據元組中第二個元素來排序,對 l_v2 我們希望根據字典的關鍵字 uid 進行排序。

sorted 函數接收一個關鍵字參數 key ,該參數指定一個可調用函數,函數返回一個值(只要是可比較的),那么 sorted 函數將根據返回的關鍵字對列表中的元素進行排序。

例如對上面的例子:

            
>>> l_v1 = [('b',2),('a',1),('c',3),('d',4)]
>>> sorted(l_v1, key=lambda x: x[1])
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> l_v2 = [
{'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
{'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
{'fname': 'John', 'lname': 'Cleese', 'uid': 1001},
{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
]
>>> sorted(l_v2, key=lambda x: x['uid'])
[{'lname': 'Cleese', 'uid': 1001, 'fname': 'John'}, {'lname': 'Beazley', 'uid': 1002, 'fname': 'David'}, {'lname': 'Jones', 'uid': 1003, 'fname': 'Brian'}, {'lname': 'Jones', 'uid': 1004, 'fname': 'Big'}]
          

這里 lambda 函數是一個常用的技巧。lambda 關鍵字后邊的 x 是該函數接收的參數,冒號后邊的表達式是該函數的返回值。對 l_v1 來說,傳遞給參數 x 的就是每一個元組,其返回元組的第二個元素用于排序;對 l_v2 來說,傳遞給參數 x 的就是列表中的每一個字典元素,其返回字典中 uid 對應的值用于排序。

除了使用匿名函數 lambda 這種通用的方法外,Python 標準庫 operator 為我們提供了一個 itemgetter 函數替代我們寫的 lambda 函數,且其性能會比使用 lambda 函數略有提升。

            
>>> from operator import itemgetter
>>> l_v1 = [('b',2),('a',1),('c',3),('d',4)]
>>> sorted(l_v1, key=itemgetter(1))
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> l_v2 = [
{'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
{'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
{'fname': 'John', 'lname': 'Cleese', 'uid': 1001},
{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
]
>>> sorted(l_v2, key=itemgetter('uid'))
[
{'lname': 'Cleese', 'uid': 1001, 'fname': 'John'}, 
{'lname': 'Beazley', 'uid': 1002, 'fname': 'David'}, 
{'lname': 'Jones', 'uid': 1003, 'fname': 'Brian'}, 
{'lname': 'Jones', 'uid': 1004, 'fname': 'Big'}
]
          

以上例子均是返回一個單一的值用于排序關鍵字,前面說過,關鍵字 key 接收的函數可以返回任意的可比較對象。例如在 python 中,元組是可以比較的。對元組的比較規則為首先比較元組中第一個位置上的元素,如果相等,在比較第二個位置上的元素,依次類推。回到 l_v2 的例子,假設現在需求變了,我們首先對 lname 對應的值排序,如果 lname 對應的值相等,那么再根據 fname 確定其順序。

            
>>> l_v2 = [
 {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
 {'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
 {'fname': 'John', 'lname': 'Cleese', 'uid': 1001},
 {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
]
>>> sorted(l_v2, key=lambda x: (x['lname'], x['fname']))
[
 {'lname': 'Beazley', 'uid': 1002, 'fname': 'David'}, 
 {'lname': 'Cleese', 'uid': 1001, 'fname': 'John'}, 
 {'lname': 'Jones', 'uid': 1004, 'fname': 'Big'}, 
 {'lname': 'Jones', 'uid': 1003, 'fname': 'Brian'}
]
          

這個例子中,lambda 函數返回的不再是一個標量值,而是一個元組 (x['lname'], x['fname']) ,根據元組的比較規則,首先根據元組的第一個位置上的元素 x['lname'] 的大小排序,由于列表中有兩個字典其 lname 對應的值都為 Jones,因此再根據元組第二個位置的元素 x['fname'] 的值排序,由于 Big 比 Brian 要小(按字母順序依次比較),所以 Big 排在了前面。

同樣使用 itemgetter 函數也是可以的,且性能會略有提升。此外我覺得 itemgetter 比 lambda 更加簡潔和可讀一點。

            
>>> l_v2 = [
 {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
 {'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
 {'fname': 'John', 'lname': 'Cleese', 'uid': 1001},
 {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
]
>>> sorted(l_v2, key=itemgetter('lname', 'fname'))
[
 {'lname': 'Beazley', 'uid': 1002, 'fname': 'David'}, 
 {'lname': 'Cleese', 'uid': 1001, 'fname': 'John'}, 
 {'lname': 'Jones', 'uid': 1004, 'fname': 'Big'}, 
 {'lname': 'Jones', 'uid': 1003, 'fname': 'Brian'}
]
          

情況三

需要排序的元素是一個 Python 對象,我們希望根據其某個屬性值來排序。例如一個存放 User 對象的列表如下,根據其 name 屬性排序:

            
class User:
 def __init__(self, name):
  self.name = name
def __str__(self):
return 'User: %s' % self.name

__repr__ = __str__ # 為了能夠讓 User 在解釋器中顯示為 'User: name' 的格式

user_list = [User('John'), User('David'), User('Big'), User('Alen')]
          

方法與前面的一樣,定義一個函數返回 User 的 name 屬性的值,把該函數傳給 sorted 的 key 參數。

            
>>> user_list = [User('John'), User('David'), User('Big'), User('Alen')]
>>> sorted(user_list, key=lambda x: x.name)
>>> sorted(user_list, key=lambda x: x.name)
[User: Alen, User: Big, User: David, User: John]
          

但是,itemgetter 方法不再起作用,取而代之的是 attrgetter 方法。

            
>>> sorted(user_list, key=attrgetter('name'))
[User: Alen, User: Big, User: David, User: John]
          

attrgetter 與 itemgetter 用法完全一致,只是 itemgetter 用于獲取某個位置索引或者字典關鍵字的取值,而 attrgetter 用于獲取對象的屬性值。

PS:sorted 返回的是原始列表的一個已排序的副本,而原始列表的順序并沒有任何變化。如果你只想就地排序(即排序原始列表本身),則直接調用 list 的 sort 方法即可: list.sort() 。其用法與 sorted 函數一樣,只是該函數沒有返回值,調用后原始列表已變為一個已排序列表。

對序列中的元素進行分組

和排序類似,現想根據列表中元素的某個關鍵字分組,使關鍵字相同的元素分到同一組,并可以對分好的組進行進一步處理。例如有如下的一個列表:

            
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'},
]
          

列表的元素為字典,現想根據字典的 date 分組,使日期( date )相同的元素分到一個組。Python 的 itertools 模塊中的 groupby 函數可以很好地解決該問題。為了使用 groupby 函數,首先需要對列表排序:

            
>>> from operator import itemgetter
>>> sorted_rows = sorted(rows, key=itemgetter('date'))
          

groupby 也和 sorted 一樣有一個 key 關鍵字參數,其接收一個可調用函數,該函數返回的值被用做分組的關鍵字,其用法和 sorted 的 key 關鍵字參數一樣 。

            
>>> for date, items in groupby(sorted_rows, key=itemgetter('date')):
 print(date)
 for i in items:
  print(' ', i)
07/01/2012
{'address': '5412 N CLARK', 'date': '07/01/2012'}
{'address': '4801 N BROADWAY', 'date': '07/01/2012'}
07/02/2012
{'address': '5800 E 58TH', 'date': '07/02/2012'}
{'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'}
{'address': '1060 W ADDISON', 'date': '07/02/2012'}
07/03/2012
{'address': '2122 N CLARK', 'date': '07/03/2012'}
07/04/2012
{'address': '5148 N CLARK', 'date': '07/04/2012'}
{'address': '1039 W GRANVILLE', 'date': '07/04/2012'}
          

可以看到 groupby 返回的值分別是用于分組的關鍵字對應的值和該組的全部成員。groupby 實際返回一個生成器,通過迭代即可分別對各組進行處理。值得注意的一點是,分組前對列表排序這一步必不可少,否則對于非緊鄰的元素即使其值相同也會被分在不同組。

總結

以上就是關于python序列進階篇的全部內容,希望本文的內容對大家學習或者使用python能有所幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 91福利国产在线观看一区二区 | 国产欧美综合在线一区二区三区 | 在线观看国产一区二三区 | 97影院网 | 久久精品福利 | 狠狠色噜狠狠狠狠色综合久 | 性做久久久久久网站 | 日韩三集片| 国产成人一区二区三区影院免费 | 欧美一级aa天码毛片 | 香蕉久久久 | 日本高清在线观看天码888 | 欧美综合色区 | 天天操人人干 | 爱我久久视频免费观看影视 | 狠狠的搞| 日韩毛片高清免费 | 九七影院97影院理论片 | 青青青青在线成人视99 | 日本夜爽爽一区二区三区 | 国产 magnet | 天天操天天舔天天干 | 午夜噜噜噜私人影院在线播放 | 中文字幕一区日韩在线视频 | 亚洲精品久久久久久动漫剧情 | 成人免费性视频 | 四虎影院免费观看视频 | 日本免费一区二区三区中文 | 国产国拍亚洲精品福利 | 国产91久久最新观看地址 | 日本不卡三区 | 四虎影院官网 | 久久久精品午夜免费不卡 | 亚洲成人黄色 | 一二三区无线码2021 | 国产成人在线免费视频 | 97国产在线视频公开免费 | 久久大综合 | 不卡影视 | 久久久久琪琪免费影院 | 综合网伊人 |