最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一個Python優(yōu)雅的數(shù)據(jù)分塊方法詳解

 更新時間:2022年05月09日 11:17:37   作者:金色旭光  
在做需求過程中有一個對大量數(shù)據(jù)分塊處理的場景,具體來說就是幾十萬量級的數(shù)據(jù),分批處理,每次處理100個。這時就需要一個分塊功能的代碼。本文為大家分享了一個Python中優(yōu)雅的數(shù)據(jù)分塊方法,需要的可以參考一下

1.背景

看到這個標(biāo)題你可能想一個分塊能有什么難度?還值得細(xì)說嗎,最近確實遇到一個有意思的分塊函數(shù),寫法比較巧妙優(yōu)雅,所以寫一個分享。

日前在做需求過程中有一個對大量數(shù)據(jù)分塊處理的場景,具體來說就是幾十萬量級的數(shù)據(jù),分批處理,每次處理100個。這時就需要一個分塊功能的代碼,剛好項目的工具庫中就有一個分塊的函數(shù)。拿過函數(shù)來用,發(fā)現(xiàn)還挺好用的,傳入列表和分塊大小,然后就能遍歷取出分好的數(shù)據(jù)。調(diào)用方式如下:

from xxx import chunk_fun
chunk_list = chunk_fun(arr, 100) # 對數(shù)據(jù)進(jìn)行分塊,指定塊的大小為100

for chunk in chunk_list:
    print(chunk)

然后我就對這個分塊函數(shù)產(chǎn)生了興趣,想看看這個小功能是如何實現(xiàn)的。如果讓我來寫一個分塊函數(shù),我知道Python中range函數(shù)可以指定步長,用這個特性就完全可以優(yōu)雅的實現(xiàn)分塊功能。

arr = [1,2,3,4,5,6,7,8,9,10]

step = 3
for i in range(0, len(arr), step):
    chunk = arr[i:i+step]
    print(chunk)
>>>
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
[10]

沒想到看到源碼竟然才用了3行代碼就實現(xiàn)了分塊,不僅支持列表等線性結(jié)構(gòu)的分塊,而且還支持集合這種非線性結(jié)構(gòu)的分塊。這讓我感到震撼,這3行代碼不是最優(yōu)雅的分塊方法,也是接近最優(yōu)雅的分塊方法了。廢話不多說,先上代碼:

from itertools import islice

def chunk_list(it, limit):
    it = iter(it)
    return iter(lambda: list(islice(it, limit)), [])

對于這3行代碼,有多少人第一眼沒看出功能的呢?反正我第一眼看的是一臉懵逼,有種不明覺厲的感覺

首先來看一下這個分塊函數(shù)的使用。

set_num = {1,2,3,4,5,6,7}

for temp_list in chunk_list(set_num, 2):
    print(temp_list)
>>>
[1, 2]
[3, 4]
[5, 6]
[7]

完全沒有使用顯示循環(huán)就把分塊這件事安排的明明白白的,而且才用了3行代碼,不包括函數(shù)的定義就只剩下2行代碼就搞定了。這是我見過最優(yōu)雅的分塊方法。然后我就花一點時間搞明白代碼是如何工作的。

那么這個分塊功能是如何實現(xiàn)的呢?主要有兩個知識點:迭代器切片islice+迭代器生成函數(shù)iter。通過這兩個函數(shù)的配合,完成了分塊功能。下面我詳細(xì)介紹這兩個方法的使用。

2.islice

islice是python內(nèi)置模塊itertool中的一個函數(shù),功能是對迭代器切片,傳入一個迭代器,返回從迭代器中的start位置到stop位置的元素,可缺省起始位置。

函數(shù)定義如下:

islice(iterable, [start, ] stop [, step])
  • iterable 可迭代對象
  • start 切片開始位置
  • stop 切片結(jié)束位置
  • step 步長

2.1示例

from itertools import islice
from collections import Iterator

iter_list = iter([1,2,3,4,5,6,7])
slice = islice(iter_list, 0, 7, 2)

print(slice)
>>>
<itertools.islice object at 0x7fc864e5aef8>

print(isinstance(slice, Iterator))
>>> 
True

print(list(slice))
>>>
[1, 3, 5, 7]

指定start為0,stop為7,step2,得到一個新的迭代器,元素是從1開始的步長為2取到的數(shù)據(jù)。

2.2只指定步長

islice可以只傳入步長參數(shù),當(dāng)沒有start和stop時,默認(rèn)從start為起點,stop為終點。

from itertools import islice

iter_list = iter([1,2,3,4,5,6,7])

slice = islice(iter_list, 2)
print(list(slice))

slice = islice(iter_list, 2)
print(list(slice))

slice = islice(iter_list, 2)
print(list(slice))

slice = islice(iter_list, 2)
print(list(slice))

slice = islice(iter_list, 2)
print(list(slice))

slice = islice(iter_list, 2)
print(list(slice))

slice = islice(iter_list, 2)
print(list(slice))
>>>
[1, 2]
[3, 4]
[5, 6]
[7]
[]
[]
[]

除了獲得切片之外,以上代碼還說明了兩個非常重要的特征,是否有留意?

第一個:那就是切片能夠保留位置信息,多次調(diào)用切片功能,當(dāng)前取值是從上一次結(jié)尾的地方開始的。比如第一次取值1、2,結(jié)尾位置是3;第二次就從3開始取到了3、4;第三次從5開始取到5、6。原因islice是對迭代器切片,迭代器取值會記住位置信息。

第二個:當(dāng)?shù)晁械脑刂?,返回空?shù)組。將原始列表迭代完之后不會報錯,而是一直返回空數(shù)組。

有了上面這種使用方法就為分塊提供了可能性,如果要使用islice來分塊,只需要在一個死循環(huán)里調(diào)用islice取值,當(dāng)取值為[]時退出循環(huán)即可??赏ㄟ^如下方法實現(xiàn):

from itertools import islice

def chunk(it, limit):
    it = iter(it)
    while True:
        temp = list(islice(it, limit))
        if temp == []:
            break
        yield temp

iter_list = iter([1,2,3,4,5,6,7])

for temp_list in chunk(iter_list, 2):
    print(temp_list)
>>>
[1, 2]
[3, 4]
[5, 6]
[7]

這樣就完成了使用islice就完成了分塊的功能,但是看上可不是很優(yōu)雅,又有while循環(huán),又有yield關(guān)鍵值。

不優(yōu)雅關(guān)鍵在于需要循環(huán)調(diào)用切片函數(shù)而且還需要判斷跳出循環(huán)的條件。那么有沒有一個既可以循環(huán)調(diào)用又能判斷結(jié)束條件的函數(shù)呢?還真的有的,那就是iter。

3.iter

iter()方法用來創(chuàng)建迭代器,iter()本質(zhì)上就是調(diào)用可迭代對象的__iter__方法,返回一個迭代器對象。關(guān)于iter的常規(guī)使用,可參見另一篇文章一篇文章講清楚迭代器和生成器

3.1常規(guī)使用

常見的iter的使用方法是,對一個可迭代對象調(diào)用iter方法,讓其變成一個迭代器,可以通過next取值。

list = [1,2,3,4,5,6,7]
iter_list = iter(list)

print(next(iter_list))
print(next(iter_list))
print(next(iter_list))
>>>
1
2
3

3.2進(jìn)階使用

iter還有一種不常用的方法,來看iter函數(shù)的定義

iter(object[, sentinel])
  • object -- 支持迭代的集合對象。
  • sentinel -- 如果傳遞了第二個參數(shù),則參數(shù) object 必須是一個可調(diào)用的對象(如,函數(shù)),此時,iter 創(chuàng)建了一個迭代器對象,每次調(diào)用這個迭代器對象的__next__()方法時,都會調(diào)用 object。

也就是說如果iter函數(shù)如果傳了第二個參數(shù),那么第一個參數(shù)就必須是一個可調(diào)用對象,每一次調(diào)用next函數(shù)時,實際上就是調(diào)用第一個參數(shù),如果結(jié)果等于第二個參數(shù),那就是迭代完成了。

聽起來有點彎彎繞,跑一個示例就清楚了。

import random

def get_random():
    return random.randint(1,5)

demo = iter(get_random, 4)

print(next(demo))
print(next(demo))
print(next(demo))
print(next(demo))
print(next(demo))
print(next(demo))
print(next(demo))
>>>
3
2
1
2
Traceback (most recent call last):
  File "islice_demo.py", line 62, in <module>
    print(next(demo))
StopIteration

iter傳入第一個參數(shù)是一個函數(shù)get_random,函數(shù)的功能是獲取1-5之間的隨機數(shù),第二個參數(shù)是4,也就是說如果函數(shù)返回的數(shù)值是4,那算迭代完成。每一次調(diào)用next取值就會調(diào)用get_random函數(shù),直到結(jié)果為4。當(dāng)?shù)瓿芍螅瑫伋鲆粋€StopIteration的異常。

上面是通過next調(diào)用,如果是通過for循環(huán)調(diào)用,就不會拋出異常,for循環(huán)會捕獲異常。

import random

def get_random():
    return random.randint(1,5)

demo = iter(get_random, 4)

for i in demo:
    print(i)
>>>
1
5

這個功能剛好可以實現(xiàn)調(diào)用某一個函數(shù),又能判斷退出條件,如果現(xiàn)在再把分塊的代碼擺上來,能否實現(xiàn)優(yōu)雅的分塊呢?

from itertools import islice

def chunk(it, limit):
    it = iter(it)
    while True:
        temp = list(islice(it, limit))
        if temp == []:
            break
        yield temp

iter_list = iter([1,2,3,4,5,6,7])

for temp_list in chunk(iter_list, 2):
    print(temp_list)

4.islice 和 iter 組合使用

islice 提供分塊功能,iter 提供循環(huán)調(diào)用islice的功能和判斷退出的功能,最后在兩個函數(shù)的的配合使用下,完成了優(yōu)雅的分塊。

便于理解的示例:

from itertools import islice

def chunk_list(it, limit):
    it = iter(it)
    # 實現(xiàn)分塊的內(nèi)函數(shù)
    def iter_fun():
        return list(islice(it, limit))

    return iter(iter_fun, [])

it = [1,2,3,4,5,6,7]
chunk = chunk_list(it, 2)

print(next(chunk))
print(next(chunk))
print(next(chunk))
print(next(chunk))
print(next(chunk))
>>> 
[1, 2]
[3, 4]
[5, 6]
[7]
Traceback (most recent call last):
  File "chunk_demo.py", line 44, in <module>
    print(next(chunk))
StopIteration

最終的示例:

from itertools import islice

def chunk_list(it, limit):
    it = iter(it)
    return iter(lambda: list(islice(it, limit)), [])

iter 第一個參數(shù)傳入lambda表達(dá)式,有一個更貼合場景的叫法是無頭函數(shù)。 lambda: list(islice(it, limit))。沒有傳入?yún)?shù),函數(shù)體是islice(it, limit);

第二個參數(shù)是空列表[],作為迭代退出的判斷。

工作原理:

當(dāng)使用for循環(huán)遍歷分塊函數(shù)時,每循環(huán)一次就通過iter調(diào)用islice一次,將分塊結(jié)果list處理,然后返回。直到islice返回空列表,iter根據(jù)第二個參數(shù)判斷退出循環(huán)。

5.總結(jié)

分塊函數(shù)的優(yōu)點:

  • 實現(xiàn)很優(yōu)雅
  • 支持的分塊的數(shù)據(jù)類型豐富。不單是列表,只要能夠迭代的都可以。

分塊的實現(xiàn)主要有兩個思路:

  • 使用islice來完成迭代器切片,實現(xiàn)分塊的功能。但是需要多次調(diào)用islice直到迭代完成
  • iter 提供調(diào)用功能,并判斷迭代退出條件

有興趣的讀者可看看iter的實現(xiàn),能夠明白為什么迭代器能記住位置,這是本文分塊的一個核心知識點。

這一個簡單的代碼讓我感受到Python的奇妙,兩個函數(shù)默契的配合,十分優(yōu)雅的完成了分塊功能。同時我明白Python語言的宗旨是簡易優(yōu)雅,但是簡易并不簡單,想要實現(xiàn)優(yōu)雅需要扎實的基礎(chǔ)和深厚的知識儲備。追求Pythonic,需要學(xué)習(xí)理解的還有很多。

以上就是一個Python優(yōu)雅的數(shù)據(jù)分塊方法詳解的詳細(xì)內(nèi)容,更多關(guān)于Python數(shù)據(jù)分塊的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • python多線程實現(xiàn)同時執(zhí)行兩個while循環(huán)的操作

    python多線程實現(xiàn)同時執(zhí)行兩個while循環(huán)的操作

    這篇文章主要介紹了python多線程實現(xiàn)同時執(zhí)行兩個while循環(huán)的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-05-05
  • 解決Python logging模塊無法正常輸出日志的問題

    解決Python logging模塊無法正常輸出日志的問題

    今天小編就為大家分享一篇解決Python logging模塊無法正常輸出日志的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-02-02
  • Python3.7下安裝pyqt5的方法步驟(圖文)

    Python3.7下安裝pyqt5的方法步驟(圖文)

    這篇文章主要介紹了Python3.7下安裝pyqt5的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • python中的gunicorn配置和使用教程

    python中的gunicorn配置和使用教程

    這篇文章主要介紹了python中的gunicorn配置和使用教程,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06
  • Flask框架信號用法實例分析

    Flask框架信號用法實例分析

    這篇文章主要介紹了Flask框架信號用法,結(jié)合實例形式分析了Blinker的安裝及信號的接收等相關(guān)操作技巧,需要的朋友可以參考下
    2018-07-07
  • python將unicode和str互相轉(zhuǎn)化的實現(xiàn)

    python將unicode和str互相轉(zhuǎn)化的實現(xiàn)

    這篇文章主要介紹了python將unicode和str互相轉(zhuǎn)化的實現(xiàn),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-05-05
  • 利用python批量爬取百度任意類別的圖片的實現(xiàn)方法

    利用python批量爬取百度任意類別的圖片的實現(xiàn)方法

    這篇文章主要介紹了利用python批量爬取百度任意類別的圖片的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Python 實現(xiàn)一個計時器

    Python 實現(xiàn)一個計時器

    這篇文章主要介紹了Python 實現(xiàn)一個計時器的方法,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • NumPy對數(shù)組按索引查詢實戰(zhàn)方法總結(jié)

    NumPy對數(shù)組按索引查詢實戰(zhàn)方法總結(jié)

    數(shù)組的高級操作主要是組合數(shù)組,拆分?jǐn)?shù)組,tile數(shù)組和重組元素,下面這篇文章主要給大家介紹了關(guān)于NumPy對數(shù)組按索引查詢的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • tensorflow 打印內(nèi)存中的變量方法

    tensorflow 打印內(nèi)存中的變量方法

    今天小編就為大家分享一篇tensorflow 打印內(nèi)存中的變量方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07

最新評論

林口县| 登封市| 长宁区| 武义县| 观塘区| 通化县| 内黄县| 文山县| 朔州市| 肃北| 葫芦岛市| 福鼎市| 县级市| 儋州市| 罗源县| 尉氏县| 安泽县| 昭苏县| 故城县| 南溪县| 诸城市| 巴彦淖尔市| 疏勒县| 东方市| 黑山县| 河北区| 淅川县| 安庆市| 华蓥市| 侯马市| 鹿邑县| 会理县| 绥滨县| 汕尾市| 武邑县| 荥阳市| 蒲江县| 玉屏| 咸丰县| 大理市| 政和县|