我制作了一个名为CustomDict
的dict包装器,它由键和CustomValues
组成。CustomValue定义了__iadd__
(+=
)操作。此操作将对象添加到名为self.lines
的列表中
class CustomValue:
def __init__(self):
self.lines = []
def __iadd__(self, line):
self.lines.append(line)
class CustomDict:
def __init__(self):
self.data = {}
def __getitem__(self, key):
if key not in self.data:
self.data[key] = CustomValue()
return self.data[key]
# this doesn't feel pythonic
def __setitem__(self, key, value):
pass
def main():
d = CustomDict()
d['key0'] += 'Line 1'
d['key0'] += 'Line 2'
d['key1'] += 'Line 3'
d['key1'] += 'Line 4'
print(d)
这是我在调试器中看到的调用d['key0'] += 'Line 1'
后发生的情况:
d.__getitem__('key0').__iadd__('Line 1')
d.__setitem__('key0', None)
正如您所看到的,我必须用pass
定义__setitem__
,因为这样调用时,参数value
是None
。现在它可以工作了,但我有一个对__setitem__
的冗余调用。如果我删除并注释掉它,我会得到以下错误:
TypeError: 'CustomDict' object does not support item assignment
正确的做法是什么
默认dict编辑
基于user2357112 supports Monica answer我写了以下内容:
import collections
class Key:
def __init__(self):
self.lines = []
def __iadd__(self, line):
self.lines.append(line)
def missing():
return Key()
d = collections.defaultdict(missing)
d['key0'] += 'Line 1'
print(d['key0'])
但问题是新密钥没有插入回defaultdict,print语句打印None
。我做错了什么
Dict子类编辑
我使用Jordan Brière's answer检查了CustomDict中的结果,发现有一些冗余键。我写了一个__repr__
测试:
class CustomValue:
def __init__(self):
self.lines = []
def __iadd__(self, line):
self.lines.append(line)
return self
def __repr__(self):
return 'CustomValue {}, {}'.format(self.__hash__(), self.lines)
class CustomDict(dict):
def __missing__(self, key):
key = self[key] = CustomValue()
return key
def __repr__(self):
return '\n'.join(['{}: {}'.format(key, self[key]) for key in self])
def main():
d = CustomDict()
d['key0'] += 'Line 1'
d['key0'] += 'Line 2'
d['key1'] += 'Line 3'
d['key1'] += 'Line 4'
print(d)
其中打印:
CustomValue 1090233, ['Line 1', 'Line 2']: CustomValue 1090233, ['Line 1', 'Line 2']
key0: CustomValue 1090233, ['Line 1', 'Line 2']
CustomValue 1090235, ['Line 3', 'Line 4']: CustomValue 1090235, ['Line 3', 'Line 4']
key1: CustomValue 1090235, ['Line 3', 'Line 4']
正如您所看到的,一些自定义值是键,这不是我想要的
如果不想提供(或使用)有意义的项分配运算符,则不应使用
+=
+=
是一个赋值。任务分配。您的CustomValue
可以提供一个append
方法或其他方法来代替+=
我在这里看到3个合理的选择。第一个是将
CustomValue
更改为使用除+=
之外的其他内容。第二个是更改CustomDict
以提供有意义的__setitem__
第三点是放弃这些
CustomDict
和CustomValue
类,只使用stdlibcollections.defaultdict(list)
:^{} 是一个
dict
子类,它使用提供的工厂函数为缺少的键生成默认值。它比你的CustomDict
更高效,功能更丰富实际上,您应该将
dict
子类化,并重写实现所需的操作。拥有一个内部data
字典是多余的。例如相关问题 更多 >
编程相关推荐