为了避免字典中取出的值为None,通常会使用dict的setdefult方法:
1 2 |
|
当字典中存在key时,无论value是否为None,setdefault方法都会忽略default值,直接返回value。为了避免这种情况,引入了一段重复代码逻辑,每次取一个key都要这样写:
1 2 |
|
代码可读性下降了,决定采用采用子类化内建类型的方式重构。重构后代码如下:
1 2 3 |
|
重构过程中,先写doctest,alwaysdefaultdict.py文件内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
这时候执行测试的结果是:
$ nosetests --with-doctest alwaysdefaultdict.py
F
......
Traceback (most recent call last):
......
Failed example:
d.setdefault('key','default')
Expected:
'default'
Got:
''
......
Failed example:
d.get('key')
Expected:
'default'
Got:
''
......
Failed example:
d.setdefault('key','newvalue')
Expected:
'default'
Got:
''
----------------------------------------------------------------------
Ran 1 test in 0.035s
FAILED (failures=1)
然后实现代码逻辑,最后代码如下:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#-*- coding:utf-8 -*- | |
''' | |
重载setdefault方法,当key存在,并且value为空字符串或None时,也会设置为defaultvalue。 | |
>>> d = alwaysdefaultdict() | |
>>> d.setdefault('key','') | |
'' | |
>>> d.setdefault('key','default') | |
'default' | |
>>> d.get('key') | |
'default' | |
>>> d.setdefault('key','newvalue') | |
'default' | |
>>> d.get('no_key') | |
>>> d['newkey']='newvalue' | |
>>> d.get('newkey') | |
'newvalue' | |
>>> d['newkey'] | |
'newvalue' | |
''' | |
class alwaysdefaultdict(dict): | |
def setdefault(self, key, defaultvalue): | |
if self.has_key(key): | |
if self.get(key): | |
return self.get(key) | |
else: | |
del self[key] | |
return super(alwaysdefaultdict, self).setdefault(key, defaultvalue) |
执行doctest的结果:
$ nosetests --with-doctest alwaysdefaultdict.py
.
----------------------------------------------------------------------
Ran 1 test in 0.096s
OK