PythonはしばしばAbstract Base Classes(PEP 3119で提案された)を持っていました。特に、コンテナタイプの場合、タイプ。Python 3の標準ライブラリを使用して文字列に似ていないシーケンスをテストする方法
:たとえば、from collections.abc import Sequence, Set
if isinstance(x, Sequence):
# Handle lists, tuples, or custom objects that behave like lists
elif isinstance(x, Set):
# Handle anything that behaves like a set
数回私をトリップの「落とし穴」の一つはstr
、bytes
、そしてbytearray
はすべて、より明らかにリストのようなオブジェクトに加えて、Sequence
秒と考えられているということです
from collections.abc import ByteString, Sequence
s = 'hello'
b = b'hello'
ba = bytearray(b'hello')
lst = [0, 1, 2]
t = (0, 1, 2)
islistlike = lambda x: isinstance(x, Sequence)
list(map(islistlike, [s, b, ba, lst, t])) # -> [True, True, True, True, True]
これは確かに理にかなっています。通常、これらの3つのタイプは、文字(またはバイト)のリストまたはタプルと同じように動作します。しかし、このオブジェクトはリストのようなものではなく、文字列のようなものであることを尋ねるのは、かなり一般的な使用例のようです。x
修正は簡単です:
islistlike = lambda x: isinstance(x, Sequence) and not isinstance(x, (str, ByteString))
list(map(islistlike, [s, b, ba, lst, t])) # -> [False, False, False, True, True]
しかし、それは、私は標準ライブラリで何かが欠けてるかしら共通十分なパターンになるように、これはそうです。
islistlike = lambda x: isinstance(x, abc)
は、上記の最後の例のように振る舞うということなPythonの標準ライブラリ内のすべてのabc
はありますか?Sequence
と文字列のような容器のどこかにデザインディスカッションはありますか? (私は標準ライブラリのドキュメントやPEP 3119.でこれに関連する何かを発見していない)
1.私の知る限りではありません。あなたが気づいているように、* "文字列のようなコンテナ" * *は、単一文字の文字列/バイトのシーケンスです( 'ByteString'は' Sequence'、偶数を継承します)ので、* "vs" *は実際には作成しませんセンス。多くの場合、文字列はシーケンスをとる関数やメソッドに対して完全に有効な引数とみなされるため、そうでない場合は明示的に指定する必要があります。 – jonrsharpe
@jonrsharpeコメントありがとう!状況に応じて「* vs *」が適切であると主張したいと思います。しばしば、私は文字列(バイトなど)を単一のアトミックなデータポイントとして考えています。文字列のようなアイテムのリストのようなコンテナを扱っているのですか、または単一の文字列のようなものです項目。これが起こる1つの場所は、たとえば、アイテムの型にディスパッチしたい再帰関数の中で、ネストされた辞書をフラット化するために再帰関数を使用することです。 – DGrady