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
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
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
です。
これは、次のように最初の要素が必要な場合に機能しますmy_list.get(0)
>>> my_list = [1,2,3]
>>> next(iter(my_list), 'fail')
1
>>> my_list = []
>>> next(iter(my_list), 'fail')
'fail'
私はそれがあなたが求めたものではないことを知っていますが、それは他の人を助けるかもしれません.
おそらく、リストのセマンティクスにはあまり意味がなかったためです。ただし、サブクラス化することで簡単に独自のものを作成できます。
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()
.getを使用する代わりに、このようにリストを使用しても問題ありません。使用法の違いだけです。
>>> l = [1]
>>> l[10] if 10 < len(l) else 'fail'
'fail'
これを試して:
>>> i = 3
>>> a = [1, 2, 3, 4]
>>> next(iter(a[i:]), 'fail')
4
>>> next(iter(a[i + 1:]), 'fail')
'fail'
あなたができる合理的なことは、リストを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')
そのため、これについてさらに調査を行いましたが、これに固有のものは何もないことがわかりました。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
何が最速かを確認するためにベンチマークを行っていません。
辞書は検索用です。エントリが存在するかどうかを尋ねることは理にかなっています。リストは通常反復されます。L[10] が存在するかどうかを尋ねることは一般的ではなく、L の長さが 11 であるかどうかを尋ねます。
もし、あんたが
これを使用できます:
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)
''
ユースケースは基本的に、固定長の配列と行列を処理する場合にのみ関連するため、それらの長さを事前に知ることができます。その場合、通常は手で None または 0 で埋める前にそれらを作成して、実際に使用するインデックスが既に存在するようにします。
あなたはこれを言うことができます: 私はかなり頻繁に辞書に .get() が必要です。フルタイムのプログラマーとして 10 年間働いてきましたが、リストに載せる必要はなかったと思います。:)