我经常需要将字符映射到连续ID的字典,所以我执行以下操作:

ids = defaultdict()
ids.default_factory = ids.__len__

由于在这里使用__len__方法,有什么奇怪的可能出错吗?

分析解答

每次都需要分配default_factory太糟糕了。也许尝试这样的事情

class ConsecutiveIds(defaultdict):
    def __init__(self):
        super(ConsecutiveIds, self)
        self.default_factory = lambda: len(self)

d = ConsecutiveIds()

删除时似乎有一个异常会重复旧值

In [4]: d = ConsecutiveIds()

In [5]: d[0]
Out[5]: 0

In [6]: d[10]
Out[6]: 1

In [7]: d[20]
Out[7]: 2

In [8]: d
Out[8]: 
ConsecutiveIds(<function __main__.ConsecutiveIds.__init__.<locals>.<lambda>()>,
               {0: 0, 10: 1, 20: 2})

In [9]: del d[10]

In [10]: d[30]
Out[10]: 2

In [11]: d
Out[11]: 
ConsecutiveIds(<function __main__.ConsecutiveIds.__init__.<locals>.<lambda>()>,
               {0: 0, 20: 2, 30: 2})

ikamen的回答中似乎没有出现异常现象,但更简洁的说,您可以说:

class ConsecutiveIds(defaultdict):
    def __init__(self):
        super(ConsecutiveIds, self)
        self.default_factory = self.next_int
        self.index = 0

    def next_int(self):
        result = self.index
        self.index += 1
        return result

这可以进一步细化为

class ConsecutiveIds(defaultdict):
    def __init__(self):
        super(ConsecutiveIds, self)
        counter = itertools.count()
        self.default_factory = lambda: next(counter)