官术网_书友最值得收藏!

3.1.7 轉換并計算數據

在實際應用中,對序列的操作方式有很多,有時需要先對序列數據做轉換或過濾,再對序列做聚集,如執行sum()、min()、max()等操作。

一個非常優雅的做數據計算與轉換的操作就是使用一個生成器表達式參數。如計算平方和可以這樣操作,示例如下:


num_list = [1, 2, 3, 4, 5]
print(sum(x * x for x in num_list))

更多的示例如下:


import os
file_list = os.listdir('dirname')
if any(name.endswith('.py') for name in file_list):
    print('There be python!')
else:
    print('Sorry, no python.')

# Output a tuple as CSV
course = ('python', 20, 0.3)
print(','.join(str(x) for x in course))

# Data reduction across fields of a data structure
course_info = [
    {'name':'python', 'score': 100.0},
    {'name':'java', 'score': 85.0},
    {'name':'c', 'score': 90.0},
    {'name':'c++', 'score': 95.0}
]
min_score = min(cf['score'] for cf in course_info)
print(min_score)

該示例演示了當生成器表達式作為一個單獨參數傳遞給函數時候的巧妙語法。下面這些語句是等效的:


# 顯式傳遞一個生成器表達式對象
print(sum((x * x for x in num_list)))
# 更加優雅的實現方式,省略了括號
print(sum(x * x for x in num_list))

使用一個生成器表達式作為參數比先創建一個臨時列表更加高效和優雅。如不使用生成器表達式,可能會使用如下實現方式:


num_list = [1, 2, 3, 4, 5]
print(sum([x * x for x in num_list]))

這種方式同樣可以達到想要的效果,但是它會多一個步驟——創建一個額外的列表。這對于小型列表可能沒什么關系,但是如果元素數量非常大,則需創建一個巨大的、僅僅使用一次就被丟棄的臨時數據結構。而生成器方案會以迭代的方式轉換數據,因此更省內存。

在使用一些聚集函數比如min()和max()的時候可能更加傾向于使用生成器版本,它們接收一個key關鍵字參數。如對于前面的示例,我們可以考慮如下的實現方式:


print(min(cf['score'] for cf in course_info))
print(min(course_info, key=lambda cf: cf['score']))

擴展:字符串連接優先使用join,而不是+。

字符串的連接在編程過程中會經常遇到。Python中的字符串是不可變對象,一旦創建便不能更改。這個特性對Python中的字符串連接有一些影響。當連接次數比較多時,join操作的效率明顯高于“+”操作。

使用“+”操作,每執行一次便會在內存中申請一塊新的內存空間,并將上一次操作的結果和本次的右操作數復制到新申請的內存空間,致使在N次連接操作過程中,需要申請N-1個內存,從而嚴重影響效率。使用“+”操作字符串的時間復雜度近似為O(n2)。

當用join()方法連接字符串時,首先會計算需要申請的總內存空間,然后一次性申請所需內存并將字符序列中的每一個元素復制到內存中,所以join操作的時間復雜度為O(n)。

對于字符串的連接,特別是大規模字符串的處理,盡量優先使用join操作。

主站蜘蛛池模板: 安国市| 湘潭市| 夹江县| 南江县| 大洼县| 安顺市| 榆社县| 六枝特区| 昌图县| 永春县| 红原县| 卢氏县| 犍为县| 凤台县| 河间市| 乌兰察布市| 奇台县| 靖州| 乌拉特中旗| 浙江省| 沧州市| 商水县| 济南市| 柘荣县| 洛浦县| 子洲县| 德江县| 肇州县| 蒙阴县| 延寿县| 新宾| 个旧市| 惠来县| 松原市| 渭源县| 夏津县| 城固县| 乌审旗| 安化县| 内江市| 腾冲县|