在Python裡面有一個模組collections,解釋是資料類型容器模組。這裡面有一個collections.defaultdict()常被用到。主要說說這個東西。
綜述:
這裡的defaultdict(function_factory)建構的是一個類似dictionary的對象,其中keys的值,自行決定賦值,但是values的類型,是function_factory的類別實例,而且具有預設值。例如default(int)則建立一個類似dictionary對象,裡面任何的values都是int的實例,而且就算是一個不存在的key, d[key] 也有一個預設值,這個預設值是int()的預設值0.
defaultdict
dict subclass that calls a factory function to supply missing values。
這是一個簡短的解釋
defaultdict屬於內建函數dict的子類,呼叫工廠函數提供缺少的值。
比較暈,什麼是工廠函數:
來自python 核心程式設計的解釋
Python 2.2 統一了類型和類, 所有的內建類型現在也都是類, 在這基礎之上, 原來的
內建轉換函數象int(), type(), list() 等等, 現在都成了工廠函數。 也就是說雖然他
們看起來有點象函數, 實質上他們是類。當你調用它們時, 實際上是產生了該類型的一個實
例, 就像工廠生產貨物一樣。
下面這些大家熟悉的工廠函數在舊的Python 版裡被稱為內建函數:
int(), long(), float(), complex()
str(), unicode(), basestring ()
list(), tuple()
type()
以前沒有工廠函數的其他類型,現在也都有了工廠函數。除此之外,那些支援新風格的類別
的全新的資料類型,也加入了相應的工廠函數。下面列出了這些工廠函數:
dict()
bool()
set(), frozenset()
object()
classmethod()
statobject()
classmethod()
易statobject()classmethod()()
file()
再看看它的使用:
import collections s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)] d = collections.defaultdict(list) for k, v in s: d[k].append(v) list(d.items())
這裡就開始有點明白了,原來defaultdict可以接受一個內建函數list作為參數。其實呢,list()本身是內建函數,但是再經過更新後,python裡面所有東西都是對象,所以list改編成了類,引入list的時候產生一個類別的實例。
還是不太明白,再看defaultdict的help解釋
class collections.defaultdict([default_factory[, ...]])
Returns a new dictionary-like object. defaultdic
Returns a new dictionary-like object. defaultdic class. It overrides one method and adds one writable instance variable. The remaining functionality is the same as for the dict class and is not documented here.ary首先說了,collections.defaultdict會返回一個類似diction的對象,不是完全一樣的對象。這個defaultdict和dict類,幾乎是一樣的,除了它重載了一個方法和增加了一個可寫的實例變數。 (可寫的實例變量,我還是沒明白)The first argument provides the initial value for the default_factory attribute; it defaults to None. All remaining arguments are treated the same as defaults to None. All remaining arguments are treated the same as defaults to None. All remaining arguments are treated the same as structif the were passedf. arguments.defaultdict objects support the following method in addition to the standard dict operations:__missing__(key)If the default_factory at bute is None tribute sceptorr. f default_factory is not None, it is called without arguments to provide a default value for the given key, this value is inserted in the dictionary for the key, and returned.主要關注這個話,如果default_factory不是Nactory 這個參數不是Nactory 這個參數的形式被調用,提供一個預設值給___missing__方法的key。 這個預設值將會作為key插入到資料字典裡,然後回傳。 十分暈。有扯出了個__missing__方法,這個__missing__方法就是collections.defaultdict()的內建方法。 If calling default_factory raises an exception this exception is propagated unchanged.This method is called by the __getitem__() method not ct class turn quested class s goundor lead questor sct class le questor swor lead noter 片語 dior lead questor swor noter ctor lead questor swor notswor ct 書; ised by __getitem__ ().Note that __missing__() is not called for any operations besides __getitem__(). This means that get() will, like normal dictionaries, return None as a default rather winging default r instance variable:default_factoryThis attribute is used by the __missing__() method; it is initialized from the first argument to the constructor, if present, orabone, ifo了。直接看範例:import collections s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)] # defaultdict d = collections.defaultdict(list) for k, v in s: d[k].append(v) # Use dict and setdefault g = {} for k, v in s: g.setdefault(k, []).append(v) # Use dict e = {} for k, v in s: e[k] = v ##list(d.items()) ##list(g.items()) ##list(e.items())
看看結果
list(d.items()) [('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])] >>> list(g.items()) [('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])] >>> list(e.items()) [('blue', 4), ('red', 1), ('yellow', 3)] >>> d defaultdict(<class 'list'>, {'blue': [2, 4], 'red': [1], 'yellow': [1, 3]}) >>> g {'blue': [2, 4], 'red': [1], 'yellow': [1, 3]} >>> e {'blue': 4, 'red': 1, 'yellow': 3} >>> d.items() dict_items([('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]) >>> d["blue"] [2, 4] >>> d.keys() dict_keys(['blue', 'red', 'yellow']) >>> d.default_factory <class 'list'> >>> d.values() dict_values([[2, 4], [1], [1, 3]])t.setdefault()比較相似
python help上也这么说了
When each key is encountered for the first time, it is not already in the mapping; so an entry is automatically created using the default_factory function which returns an empty list. The list.append() operation then attaches the value to the new list. When keys are encountered again, the look-up proceeds normally (returning the list for that key) and the list.append() operation adds another value to the list. This technique is simpler and faster than an equivalent technique using dict.setdefault():
说这种方法会和dict.setdefault()等价,但是要更快。
有必要看看dict.setdefault()
setdefault(key[, default])
If key is in the dictionary, return its value. If not, insert key with a value of default and return default. default defaults to None.
如果这个key已经在dictionary里面存着,返回value.如果key不存在,插入key和一个default value,返回Default. 默认的defaults是None.
但是这里要注意的是defaultdict是和dict.setdefault等价,和下面那个直接赋值是有区别的。从结果里面就可以看到,直接赋值会覆盖。
从最后的d.values还有d[“blue”]来看,后面的使用其实是和dict的用法一样的,唯一不同的就是初始化的问题。defaultdict可以利用工厂函数,给初始keyi带来一个默认值。
这个默认值也许是空的list[] defaultdict(list), 也许是0, defaultdict(int).
再看看下面的这个例子。
defaultdict(int) 这里的d其实是生成了一个默认为0的带key的数据字典。你可以想象成 d[key] = int default (int工厂函数的默认值为0)
d[k]所以可以直接读取 d[“m”] += 1 就是d[“m”] 就是默认值 0+1 = 1
后面的道理就一样了。
>>> s = 'mississippi' >>> d = defaultdict(int) >>> for k in s: ... d[k] += 1 ... >>> list(d.items()) [('i', 4), ('p', 2), ('s', 4), ('m', 1)]