以SortedList為例詳解Python的defaultdict對(duì)象使用自定義類型的方法
寫(xiě)在前面
最近寫(xiě)周賽題, 逃不開(kāi)的一種題型是設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu), 也就是第三題, 做這種題需要的就是對(duì)語(yǔ)言中的容器以及常用排序查找算法的掌握, 而我只熟悉了最基本的一些方法, 做起這些題來(lái)總是超時(shí)…
為了搞定這些題, 我決定學(xué)習(xí)一下大佬們的做法, 特別是優(yōu)先隊(duì)列的方法維護(hù)有序容器以及有序列表等容器, 這些都在Python
中封裝好了, 用起來(lái)很是方便, 但是采用defaultdict
的時(shí)候, 其缺省數(shù)據(jù)類型常常需要與題目給出的特定結(jié)構(gòu)匹配, 這就需要定義一個(gè)新的數(shù)據(jù)類型, 下面我就以一種十分常用的結(jié)構(gòu)SortedList
為例, 設(shè)置自定義的數(shù)據(jù)類型(本例為將默認(rèn)的升序列表變成降序列表).
其他的數(shù)據(jù)結(jié)構(gòu)當(dāng)然也可以根據(jù)下面列出的方法來(lái)改, 主要知識(shí)點(diǎn)就是函數(shù)與類的運(yùn)用了
第一種方法: 封裝成函數(shù)
首先導(dǎo)入需要的函數(shù), 其中neg
方法可以用lambda x: -x
代替, 本質(zhì)上是一樣的, 下面寫(xiě)的代碼這兩種均可.
from collections import defaultdict from sortedcontainers import (SortedList as SL, SortedKeyList as SKL) from operator import neg # or `lambda x: -x`
然后我們來(lái)看第一種方法, 其實(shí)封裝成函數(shù)本質(zhì)上就是將自定義對(duì)象作為函數(shù)返回值, 下面給出兩種實(shí)現(xiàn), 其實(shí)不傳入?yún)?shù)也可以, 但是這樣的話下面的第15
行就不能使用了, 只能通過(guò)add()
來(lái)添加值, 還是有局限的.
代碼中的d2
直接用一個(gè)新的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])
就會(huì)提示:TypeError: reverseSL_no_args() takes 0 positional arguments but 1 was given
, 但是add()
方法不會(huì)有問(wèn)題.
第二種方法: 類封裝
這種方法比較復(fù)雜, 并且有一個(gè)小坑, 這里先看第一個(gè)類的代碼.
我這里實(shí)現(xiàn)了兩個(gè)類, 其中mySL1
采用的是組合
的面向?qū)ο笤O(shè)計(jì)方法, mySL2
用的是繼承
. 第一種代碼比較多, 因?yàn)槔锩嫣砑恿艘粋€(gè)組件SortedList
, 就需要重寫(xiě)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ù)情況. 不寫(xiě)的話還得調(diào)用get()
方法, 進(jìn)行字典值(values
)數(shù)據(jù)的輸出, 這里為方便就直接轉(zhuǎn)換為List
類型了, 如果不轉(zhuǎn)換, 沒(méi)辦法在類外通過(guò)list()
進(jìn)行轉(zhuǎn)換, 因?yàn)檫@樣得到的數(shù)據(jù)不是可迭代對(duì)象, 通過(guò)直接輸出值的類型, 可以得到<class '__main__.mySL1'>
.
然后是第二個(gè)類, 繼承語(yǔ)法簡(jiǎn)潔明了, 直接調(diào)用父類的初始化方法, 但是這里需要注意的是, 繼承SortedList
類的代碼這里就不能用了, 因?yàn)槿绻€是使用SortedList
, 在__init__
中修改key
就會(huì)提示斷言錯(cuò)誤, assert key is None
, 這個(gè)問(wèn)題讓我比較困惑, 甚至覺(jué)得可能繼承的方法行不通,(下面是模塊的__new__方法的源碼) 我知道了問(wèn)題的所在.
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')
這里模塊的作者提供了一個(gè)SortedList
的子類, 叫做SortedKeyList
, 顧名思義, 就是提供了一種可以寫(xiě)入key
的類, 這時(shí)候繼承這個(gè)類就不會(huì)有問(wèn)題了.
其實(shí)在上面的函數(shù)調(diào)用那塊, 就已經(jīng)有所提示, 輸出結(jié)果中的類型, 就顯示是
SortedKeyList
, 這個(gè)類型就是修改了key
(使得key is not None
)之后得到的對(duì)象. 大家可以嘗試一下, 如果不修改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) # 或者直接通過(guò)列表初始化 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)建, 其實(shí)最后還是用到了SortedKeyList
這個(gè)子類.
到此這篇關(guān)于以SortedList為例詳解Python的defaultdict對(duì)象使用自定義類型的方法的文章就介紹到這了,更多相關(guān)Python defaultdict內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
pandas DataFrame 交集并集補(bǔ)集的實(shí)現(xiàn)
這篇文章主要介紹了pandas DataFrame 交集并集補(bǔ)集的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06Python數(shù)據(jù)擬合實(shí)現(xiàn)最小二乘法示例解析
這篇文章主要為大家介紹了Python數(shù)據(jù)擬合實(shí)現(xiàn)最小二乘法的示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-10-10基于Python實(shí)現(xiàn)地標(biāo)景點(diǎn)識(shí)別功能
地標(biāo)景點(diǎn)識(shí)別是一種基于計(jì)算機(jī)視覺(jué)技術(shù)的應(yīng)用,旨在通過(guò)對(duì)圖像進(jìn)行分析和處理,自動(dòng)識(shí)別出圖片中的地標(biāo)景點(diǎn),本文將介紹地標(biāo)景點(diǎn)識(shí)別的背景和原理,并使用Python編程語(yǔ)言來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的地標(biāo)景點(diǎn)識(shí)別系統(tǒng),感興趣的朋友可以參考下2024-01-01python實(shí)現(xiàn)圖片變亮或者變暗的方法
這篇文章主要介紹了python實(shí)現(xiàn)圖片變亮或者變暗的方法,涉及Python中Image模塊操作圖片的相關(guān)技巧,需要的朋友可以參考下2015-06-06解決編碼問(wèn)題:UnicodeDecodeError: 'utf-8' codec
這篇文章主要介紹了快速解決編碼問(wèn)題:UnicodeDecodeError: 'utf-8' codec can't decod,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05Python爬蟲(chóng):通過(guò)關(guān)鍵字爬取百度圖片
本文主要介紹了Python爬蟲(chóng):通過(guò)關(guān)鍵字爬取百度圖片的方法。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02