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)

編集:元々、私は2つの間違いを犯しました。申し訳ありませんが、回答の両方のエラーを指摘していただきありがとうございます。

4

4 に答える 4

3

問題。

  1. __init__関数はすべての引数を基本クラスに転送しようとします。ただし、記述方法では1つの引数しか転送できず、コンストラクターは常に2番目の引数を予期します。Pythonでそれを行う適切な方法は次のとおりです。

    def __init__(self, default_factory, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.default_factory = default_factory
    
  2. この__setitem__関数は、まだ存在しないすべてのインデックスを埋めようとしますが、それ自体を見逃しているため(最終的には排他的であるkeyことに注意してください)、メソッドは失敗します。その場合に使用する必要があります。rangesuper().__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使用したため、クラスではなく関数のように扱われているためだと思います。defclassdef defaultlist(list):defaultlist

于 2012-04-30T07:34:49.277 に答える
1

あなたは解決策の近くにいます。スーパービルトイン関数の使用と引数パッキングの動作を混同しています。(注:@weronikaが指摘したように、クラスではなくdefを使用して質問にタイプミスがありましたが、エラーメッセージはクラスでテストされているコードからのものです)

これを試して:

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 に答える