Jon*_*han 11 python list subclassing
我正在尝试创建一个非常有用的列表collections.defaultdict.以下设计很好地工作:
class defaultlist(list):
def __init__(self, fx):
self._fx = fx
def __setitem__(self, index, value):
while len(self) <= index:
self.append(self._fx())
list.__setitem__(self, index, value)
Run Code Online (Sandbox Code Playgroud)
以下是您使用它的方式:
>>> dl = defaultlist(lambda:'A')
>>> dl[2]='B'
>>> dl[4]='C'
>>> dl
['A', 'A', 'B', 'A', 'C']
Run Code Online (Sandbox Code Playgroud)
我应该将什么添加到默认列表以支持以下行为?
>>> dl = defaultlist(dict)
>>> dl[2]['a'] = 1
>>> dl
[{}, {}, {'a':1}]
Run Code Online (Sandbox Code Playgroud)
jsb*_*eno 17
在你给出的例子中,你首先尝试在列表中检索一个不存在的值,就像你一样dl[2]['a'],Python首先检索列表中的第三个(索引2)元素,然后继续获取名为'a'的元素object - 因此你必须对方法实现自动扩展行为__getitem__,如下所示:
class defaultlist(list):
def __init__(self, fx):
self._fx = fx
def _fill(self, index):
while len(self) <= index:
self.append(self._fx())
def __setitem__(self, index, value):
self._fill(index)
list.__setitem__(self, index, value)
def __getitem__(self, index):
self._fill(index)
return list.__getitem__(self, index)
Run Code Online (Sandbox Code Playgroud)
c0f*_*0de 12
有一个可用的python包:
$ pip install defaultlist
Run Code Online (Sandbox Code Playgroud)
默认情况下,添加的索引填充为 None。
>>> from defaultlist import defaultlist
>>> l = defaultlist()
>>> l
[]
>>> l[2] = "C"
>>> l
[None, None, 'C']
>>> l[4]
>>> l
[None, None, 'C', None, None]
Run Code Online (Sandbox Code Playgroud)
同样支持切片和负指数
>>> l[1:4]
[None, 'C', None]
>>> l[-3]
'C'
Run Code Online (Sandbox Code Playgroud)
可以通过 lambda 创建简单的工厂函数。
>>> l = defaultlist(lambda: 'empty')
>>> l[2] = "C"
>>> l[4]
'empty'
>>> l
['empty', 'empty', 'C', 'empty', 'empty']
Run Code Online (Sandbox Code Playgroud)
还可以实现高级工厂功能:
>>> def inc():
... inc.counter += 1
... return inc.counter
>>> inc.counter = -1
>>> l = defaultlist(inc)
>>> l[2] = "C"
>>> l
[0, 1, 'C']
>>> l[4]
4
>>> l
[0, 1, 'C', 3, 4]
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请参阅文档。
| 归档时间: |
|
| 查看次数: |
6256 次 |
| 最近记录: |