2

我试图defaultlist通过类比来创建defaultdict. 这个想法是,有时我想要一个预先填充(实际上!)的列表,其中包含未明确设置值的所有索引处的一些元素。不同之defaultdict处在于我实际上并没有将默认值添加到列表中,除非由于用户分配而必须扩展列表。

1)这个设计有问题吗?

2)这是我要使用的实现。有什么问题吗?

class defaultlist(list):
  def __init__(self, default_factory, arg = ()):
    # note: cannot use arg = None since list(None) is not the same as list()
    # alternatively can use:
    # def __init__(self, default_factory, *args, **kwargs)
    self.default_factory = default_factory
    super().__init__(arg)

  def __getitem__(self, key):
    try:
      return super().__getitem__(key)
    except IndexError:
      return self.default_factory()

  def __setitem__(self, key, value):
    for i in range(len(self), key):
      self.append(self.default_factory())
    self.append(value)

编辑:最初,我有两个错误。抱歉,感谢您指出答案中的两个错误。

4

4 回答 4

3

问题。

  1. 您的__init__函数尝试将所有参数转发到基类。但是,您编写它的方式只能转发 1 个参数,并且构造函数将始终期望第二个参数。在 Python 中执行此操作的正确方法是:

    def __init__(self, default_factory, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.default_factory = default_factory
    
  2. __setitem__函数尝试填充所有尚不存在的索引,但您错过了key它本身——注意range最后是排他的——因此该super().__setitem__方法将失败。你应该.append在这种情况下使用。

    def __setitem__(self, key, value):
        try:
            super().__setitem__(key, value)
        except IndexError:
            for i in range(len(self), key):
                self.append(self.default_factory())
            self.append(value)
    
于 2012-04-30T07:44:25.443 回答
2

我认为您的原因TypeError只是您使用def而不是class在“ def defaultlist(list):”行中,因此defaultlist被视为函数而不是类。

于 2012-04-30T07:34:49.277 回答
1

您已接近解决方案。您正在混淆超级内置函数的使用和参数打包的工作方式。(注意:正如@weronika 指出的那样,您的问题中使用 def 而不是 class,但您的错误消息来自您的代码正在使用 class 进行测试)

尝试这个:

class defaultlist(list):
  def __init__(self, default_factory, arg = ()):
    super(defaultlist, self).__init__(arg)
    self.default_factory = default_factory

  def __getitem__(self, key):
    try:
      return super(defaultlist, self).__getitem__(key)
    except IndexError:
      return self.default_factory()

  def __setitem__(self, key, value):
    for i in range(len(self), key):
      self.append(self.default_factory())
    super(defaultlist, self).__setitem__(key, value)

lst = defaultlist(int, [3, 4, 5])
于 2012-04-30T08:37:21.917 回答
0

还有另一个问题,例如,如果您希望有一个默认列表。目前的__getitem__(..)实现将返回一个新列表,但不会将其存储在默认列表中。

解决方法很明显,例如在这个答案中:https ://stackoverflow.com/a/8749640/1143274

于 2015-07-05T03:20:24.127 回答