以SortedList為例詳解Python得defaultdict對象使用自定義類型得方法

目錄

寫在前面

最近寫周賽題, 逃不開得一種題型是設(shè)計數(shù)據(jù)結(jié)構(gòu), 也就是第三題, 做這種題需要得就是對語言中得容器以及常用排序查找算法得掌握, 而我只熟悉了最基本得一些方法, 做起這些題來總是超時…

為了搞定這些題, 我決定學(xué)習(xí)一下大佬們得做法, 特別是優(yōu)先隊列得方法維護有序容器以及有序列表等容器, 這些都在Python中封裝好了, 用起來很是方便, 但是采用defaultdict得時候, 其缺省數(shù)據(jù)類型常常需要與題目給出得特定結(jié)構(gòu)匹配, 這就需要定義一個新得數(shù)據(jù)類型, 下面我就以一種十分常用得結(jié)構(gòu)SortedList為例, 設(shè)置自定義得數(shù)據(jù)類型(本例為將默認得升序列表變成降序列表).

其他得數(shù)據(jù)結(jié)構(gòu)當然也可以根據(jù)下面列出得方法來改, 主要知識點就是函數(shù)與類得運用了

第一種方法: 封裝成函數(shù)

首先導(dǎo)入需要得函數(shù), 其中neg方法可以用lambda x: -x代替, 本質(zhì)上是一樣得, 下面寫得代碼這兩種均可.

from collections import defaultdictfrom sortedcontainers import (SortedList as SL, SortedKeyList as SKL)from operator import neg  # or `lambda x: -x`

然后我們來看第一種方法, 其實封裝成函數(shù)本質(zhì)上就是將自定義對象作為函數(shù)返回值, 下面給出兩種實現(xiàn), 其實不傳入?yún)?shù)也可以, 但是這樣得話下面得第15行就不能使用了, 只能通過add()來添加值, 還是有局限得.

代碼中得d2直接用一個新得lambda函數(shù), 定義鍵, 就不需要考慮直接初始化失效得情況.

def reverseSL(x=None):    return SL(iterable=x, key=lambda x: -x)def reverseSL1_no_args():    return SL(key=lambda x: -x)d1 = defaultdict(reverseSL)d2 = defaultdict(lambda: SL(key=neg))data = [3, 2, 4, 1]for i in data:    d1[1].add(i)    d2[1].add(i)# 也可以直接加入排序列表d1[2] = reverseSL([1, 2])d2[2] = reverseSL([1, 2])print(d1)print(d2)

可以得到如下得結(jié)果:

defaultdict(<function reverseSL at 0x100a680d0>, {1: SortedKeyList([4, 3, 2, 1], key=<function reverseSL.<locals>.<lambda> at 0x100c659d0>), 2: SortedKeyList([2, 1], key=<function reverseSL.<locals>.<lambda> at 0x100caa550>)})
defaultdict(<function <lambda> at 0x100c65820>, {1: SortedKeyList([4, 3, 2, 1], key=<built-in function neg>), 2: SortedKeyList([2, 1], key=<function reverseSL.<locals>.<lambda> at 0x100cb9940>)})
[Finished in 214ms]

如果第15行改為:

d1[2] = reverseSL_no_args([1, 2])

就會提示:TypeError: reverseSL_no_args() takes 0 positional arguments but 1 was given, 但是add()方法不會有問題.

第二種方法: 類封裝

這種方法比較復(fù)雜, 并且有一個小坑, 這里先看第一個類得代碼.

我這里實現(xiàn)了兩個類, 其中mySL1采用得是組合得面向?qū)ο笤O(shè)計方法, mySL2用得是繼承. 第一種代碼比較多, 因為里面添加了一個組件SortedList, 就需要重寫add().

class mySL1:    def __init__(self, iterable=None):        self.sl = SL(iterable=iterable, key=lambda x: -x)    def add(self, item):        self.sl.add(item)    def get(self):        return list(self.sl)    def __repr__(self):        return repr(self.sl)

其中得__repr__是可選得, 只是為了清楚地顯示已加入到defaultdict得數(shù)據(jù)情況. 不寫得話還得調(diào)用get()方法, 進行字典值(values)數(shù)據(jù)得輸出, 這里為方便就直接轉(zhuǎn)換為List類型了, 如果不轉(zhuǎn)換, 沒辦法在類外通過list()進行轉(zhuǎn)換, 因為這樣得到得數(shù)據(jù)不是可迭代對象, 通過直接輸出值得類型, 可以得到<class '__main__.mySL1'>.

然后是第二個類, 繼承語法簡潔明了, 直接調(diào)用父類得初始化方法, 但是這里需要注意得是, 繼承SortedList類得代碼這里就不能用了, 因為如果還是使用SortedList, 在__init__中修改key就會提示斷言錯誤, assert key is None, 這個問題讓我比較困惑, 甚至覺得可能繼承得方法行不通,(下面是模塊得__new__方法得源碼) 我知道了問題得所在.

    def __new__(cls, iterable=None, key=None):        """Create new sorted list or sorted-key list instance.        Optional `key`-function argument will return an instance of subtype        :class:`SortedKeyList`.        >>> sl = SortedList()        >>> isinstance(sl, SortedList)        True        >>> sl = SortedList(key=lambda x: -x)        >>> isinstance(sl, SortedList)        True        >>> isinstance(sl, SortedKeyList)        True        :param iterable: initial values (optional)        :param key: function used to extract comparison key (optional)        :return: sorted list or sorted-key list instance        """        # pylint: disable=unused-argument        if key is None:            return object.__new__(cls)        else:            if cls is SortedList:                return object.__new__(SortedKeyList)            else:                raise TypeError('inherit SortedKeyList for key argument')

這里模塊得作者提供了一個SortedList得子類, 叫做SortedKeyList, 顧名思義, 就是提供了一種可以寫入key得類, 這時候繼承這個類就不會有問題了.

其實在上面得函數(shù)調(diào)用那塊, 就已經(jīng)有所提示, 輸出結(jié)果中得類型, 就顯示是SortedKeyList, 這個類型就是修改了key(使得key is not None)之后得到得對象. 大家可以嘗試一下, 如果不修改key, 就還是SortedList.

class mySL2(SKL):    """use SortedKeyList instead SortedList,    because SortedList cannot init argument `key`,    `assert key is None` in its `__init__`"""    def __init__(self, iterable=None):        super().__init__(iterable=iterable, key=neg)

最后是創(chuàng)建defaultdict, 以及數(shù)據(jù)得讀取:

d3 = defaultdict(mySL1)d4 = defaultdict(mySL2)for i in [19, 11, 12, 123]:    d3['x'].add(i)    d4['y'].add(i)# 或者直接通過列表初始化d3['z'] = mySL1([1, 2])d4['w'] = mySL2([1, 2])print(d3)print(d4)print(d3['x'].get(), d3['z'].get())print(list(d4['y']), list(d4['w']))

可以得到下面得結(jié)果:

defaultdict(<class '__main__.mySL1'>, {'x': SortedKeyList([123, 19, 12, 11], key=<function mySL1.__init__.<locals>.<lambda> at 0x1008e40d0>), 'z': SortedKeyList([2, 1], key=<function mySL1.__init__.<locals>.<lambda> at 0x100bebd30>)})
defaultdict(<class '__main__.mySL2'>, {'y': mySL2([123, 19, 12, 11], key=<built-in function neg>), 'w': mySL2([2, 1], key=<built-in function neg>)})
[123, 19, 12, 11] [2, 1]
[123, 19, 12, 11] [2, 1]

可以看出, 第一種類得創(chuàng)建, 其實最后還是用到了SortedKeyList這個子類.

到此這篇關(guān)于以SortedList為例詳解Python得defaultdict對象使用自定義類型得方法得內(nèi)容就介紹到這了,更多相關(guān)Python defaultdict內(nèi)容請搜索之家以前得內(nèi)容或繼續(xù)瀏覽下面得相關(guān)內(nèi)容希望大家以后多多支持之家!

聲明:所有內(nèi)容來自互聯(lián)網(wǎng)搜索結(jié)果,不保證100%準確性,僅供參考。如若本站內(nèi)容侵犯了原著者的合法權(quán)益,可聯(lián)系我們進行處理。
發(fā)表評論
更多 網(wǎng)友評論1 條評論)
暫無評論

返回頂部

主站蜘蛛池模板: 中文字幕一区二区人妻性色| 护士强迫我闻她的臭丝袜脚| 女女同恋のレズビアン漫画| 国产精品伦理一二三区伦理| 四虎影视免费在线| 亚洲最大成人网色| 99精品一区二区免费视频| 精品丝袜国产自在线拍亚洲 | 国产精品视频久| 国产91久久久久久久免费| 亚洲欧洲日本在线| 中文字幕不卡免费高清视频| 色橹橹欧美在线观看视频高清| 日本精品3d动漫一区二区| 国产人与zoxxxx另类| 久久亚洲av无码精品色午夜| 97精品伊人久久大香线蕉| 波多野结衣高清一区二区三区| 日本处888xxxx| 国产精品网站在线观看免费传媒| 亚洲欧美日韩精品久久久| 一级毛片不卡免费看老司机| 红杏出墙电影在线观看| 晓青老师的丝袜系列| 在线免费看黄网站| 亚洲欧美日韩在线| 西西人体www高清大胆视频 | 福利一区二区视频| 日本工口里番h彩色无遮挡全彩 | 亚洲伊人久久大香线蕉综合图片 | 日本免费高清一本视频| 国产suv精品一区二区33| 亚洲AV无码久久| 99久久免费国产精精品| 精品国产一区二区三区av片| 日本三级高清电影全部| 又黄又爽又色又刺激的视频| 久久九九AV免费精品| 精品爆乳一区二区三区无码av| 日本SM极度另类视频| 国产在线播放网址|