345

list に辞書のような安全な「get」メソッドがないのはなぜですか?

>>> d = {'a':'b'}
>>> d['a']
'b'
>>> d['c']
KeyError: 'c'
>>> d.get('c', 'fail')
'fail'

>>> l = [1]
>>> l[10]
IndexError: list index out of range
4

13 に答える 13

142

aは連想コレクション (値は名前に関連付けられている) であるため、例外をスローせずにキーが存在するかどうかを確認 (およびその値を返す) するのは非効率的ですが、非常に簡単である.getため、最終的にはおそらく安全なメソッドはありません。dictリスト要素にアクセスする例外を避けるため (lenメソッドが非常に高速であるため)。この.getメソッドを使用すると、辞書の 37 番目の項目に直接アクセスするのではなく、名前に関連付けられた値を照会できます (これは、リストに求めているものに似ています)。

もちろん、これは自分で簡単に実装できます。

def safe_list_get (l, idx, default):
  try:
    return l[idx]
  except IndexError:
    return default

__builtins__.listのコンストラクターにモンキー パッチを適用することもできますが__main__、ほとんどのコードでは使用されないため、それほど広範囲の変更にはなりません。独自のコードで作成したリストでこれを使用したいだけの場合は、メソッドをサブクラス化listして追加するだけgetです。

于 2011-02-26T07:23:05.220 に答える
105

これは、次のように最初の要素が必要な場合に機能しますmy_list.get(0)

>>> my_list = [1,2,3]
>>> next(iter(my_list), 'fail')
1
>>> my_list = []
>>> next(iter(my_list), 'fail')
'fail'

私はそれがあなたが求めたものではないことを知っていますが、それは他の人を助けるかもしれません.

于 2014-04-11T04:56:54.153 に答える
64

おそらく、リストのセマンティクスにはあまり意味がなかったためです。ただし、サブクラス化することで簡単に独自のものを作成できます。

class safelist(list):
    def get(self, index, default=None):
        try:
            return self.__getitem__(index)
        except IndexError:
            return default

def _test():
    l = safelist(range(10))
    print l.get(20, "oops")

if __name__ == "__main__":
    _test()
于 2011-02-26T07:40:37.473 に答える
47

.getを使用する代わりに、このようにリストを使用しても問題ありません。使用法の違いだけです。

>>> l = [1]
>>> l[10] if 10 < len(l) else 'fail'
'fail'
于 2011-02-26T07:46:29.963 に答える
19

これを試して:

>>> i = 3
>>> a = [1, 2, 3, 4]
>>> next(iter(a[i:]), 'fail')
4
>>> next(iter(a[i + 1:]), 'fail')
'fail'
于 2014-11-10T17:50:10.677 に答える
16

あなたができる合理的なことは、リストをdictに変換してから、getメソッドでアクセスすることです:

>>> my_list = ['a', 'b', 'c', 'd', 'e']
>>> my_dict = dict(enumerate(my_list))
>>> print my_dict
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'}
>>> my_dict.get(2)
'c'
>>> my_dict.get(10, 'N/A')
于 2014-09-19T17:17:17.260 に答える
8

そのため、これについてさらに調査を行いましたが、これに固有のものは何もないことがわかりました。list.index(value) を見つけたときは興奮しました。指定されたアイテムのインデックスを返しますが、特定のインデックスで値を取得するためのものはありません。したがって、safe_list_get ソリューションを使用したくない場合は、かなり良いと思います。シナリオに応じて仕事を終わらせることができる if ステートメントの 1 つのライナーを次に示します。

>>> x = [1, 2, 3]
>>> el = x[4] if len(x) > 4 else 'No'
>>> el
'No'

「いいえ」の代わりに「なし」を使用することもできます。これはより理にかなっています。

>>> x = [1, 2, 3]
>>> i = 2
>>> el_i = x[i] if len(x) == i+1 else None

また、リストの最初または最後のアイテムだけを取得したい場合、これは機能します

end_el = x[-1] if x else None

これらを関数にすることもできますが、それでも IndexError 例外ソリューションが気に入りました。私はソリューションのダミーバージョンを試してsafe_list_get、少しシンプルにしました (デフォルトなし):

def list_get(l, i):
    try:
        return l[i]
    except IndexError:
        return None

何が最速かを確認するためにベンチマークを行っていません。

于 2014-06-20T16:16:34.990 に答える
4

辞書は検索用です。エントリが存在するかどうかを尋ねることは理にかなっています。リストは通常​​反復されます。L[10] が存在するかどうかを尋ねることは一般的ではなく、L の長さが 11 であるかどうかを尋ねます。

于 2011-02-26T07:34:15.200 に答える
2

もし、あんたが

  1. ワンライナーが欲しい、
  2. 必要のない幸せなコード パスを除いて、try / を使用しないことを好みます。
  3. デフォルト値をオプションにしたい、

これを使用できます:

list_get = lambda l, x, d=None: d if not l[x:x+1] else l[x]

使用法は次のようになります。

>>> list_get(['foo'], 4) == None
True
>>> list_get(['hootenanny'], 4, 'ho down!')
'ho down!'
>>> list_get([''], 0)
''
于 2020-07-29T03:18:18.097 に答える
-2

ユースケースは基本的に、固定長の配列と行列を処理する場合にのみ関連するため、それらの長さを事前に知ることができます。その場合、通常は手で None または 0 で埋める前にそれらを作成して、実際に使用するインデックスが既に存在するようにします。

あなたはこれを言うことができます: 私はかなり頻繁に辞書に .get() が必要です。フルタイムのプログラマーとして 10 年間働いてきましたが、リストに載せる必要はなかったと思います。:)

于 2011-02-26T08:30:33.800 に答える