「in」を使用して配列内の Python オブジェクトの属性と一致させる
質問
夢を見ていたかどうかは覚えていないが、次のようなことができる機能があったような記憶がある。
foo in iter_attr(array of python objects, attribute name)
ドキュメントに目を通しましたが、この種のことは明らかなリストされたヘッダーに該当しません
解決
リスト内包表記を使用すると一時リストが作成され、検索対象のシーケンスが大きい場合はメモリをすべて消費する可能性があります。シーケンスが大きくない場合でも、リストを構築するということは、シーケンス全体を反復して実行することを意味します。 in
検索を開始できます。
一時リストはジェネレータ式を使用することで回避できます。
foo = 12
foo in (obj.id for obj in bar)
今、限り obj.id == 12
の始まり近くに bar
, 場合でも検索は高速になります。 bar
無限に長いです。
@Mattが示唆したように、使用することをお勧めします hasattr
内のオブジェクトのいずれかが bar
が欠けている可能性があります id
属性:
foo = 12
foo in (obj.id for obj in bar if hasattr(obj, 'id'))
他のヒント
特定の属性を持つオブジェクトのリストを取得したいと考えていますか?そうであれば、 リスト内包表記 これを行う正しい方法です。
result = [obj for obj in listOfObjs if hasattr(obj, 'attributeName')]
いつでも自分で書くことができます。
def iterattr(iterator, attributename):
for obj in iterator:
yield getattr(obj, attributename)
タプル、リストなど、反復されるものであれば何でも動作します。
私は Python が大好きです。Python を使用すると、このような処理が非常にシンプルになり、必要以上に面倒な作業がなくなり、実際に使用すると、このような処理が非常にエレガントになります。
いいえ、夢を見ていたわけではありません。Python には非常に優れたリスト理解システムがあり、リストを非常にエレガントに操作できます。これは、達成したい内容に応じて、いくつかの方法で実行できます。本質的に、あなたがやっていることは「リスト内の項目に対して criteria.matches の場合」と言っているので、結果を反復処理するか、結果を新しいリストにダンプするだけです。
例をあげていきます Python を理解する それはとてもエレガントで、彼らは私よりも賢いからです。ここでは、ディレクトリ内のファイルのリストを取得し、正規表現の基準に一致するすべてのファイルのリストをフィルタリングしています。
files = os.listdir(path) test = re.compile("test\.py$", re.IGNORECASE) files = [f for f in files if test.search(f)]
たとえば、最後に一致した場合に式が true を返すものであれば、正規表現を使用せずにこれを行うことができます。filter() 関数を使用するなどの他のオプションもありますが、選ぶとしたらこれを選択します。
エリック・シップル
あなたが考えている機能はおそらく operator.attrgettter
. 。たとえば、各オブジェクトの「id」属性の値を含むリストを取得するには、次のようにします。
import operator
ids = map(operator.attrgetter("id"), bar)
リストに id == 12 のオブジェクトが含まれているかどうかを確認したい場合は、きちんと効率的な方法 (つまり、リスト全体を不必要に反復しません)その方法は次のとおりです。
any(obj.id == 12 for obj in bar)
リストの遅延反復を維持しながら、attrgetter で 'in' を使用したい場合は、次のようにします。
import operator,itertools
foo = 12
foo in itertools.imap(operator.attrgetter("id"), bar)
私が考えていたことはリスト内包表記を使用して実現できますが、これをもう少しきちんとした方法で行う関数があると思いました。
つまり「bar」はオブジェクトのリストであり、そのすべてが属性「id」を持ちます。
神話上の機能的な方法:
foo = 12
foo in iter_attr(bar, 'id')
リストの理解方法:
foo = 12
foo in [obj.id for obj in bar]
振り返ってみると、リストを理解する方法はとにかく非常に巧妙です。
ある程度のサイズのものを検索する予定がある場合は、辞書または辞書セットを使用するのが最善の策です。それ以外の場合は、基本的に、必要な要素に到達するまでイテレータのすべての要素を反復処理する必要があります。
これが必ずしもパフォーマンス重視のコードではない場合は、リスト内包の方法が機能するはずです。ただし、反復子のすべての要素を調べてから、必要なものが見つかるまで再度 BACK するため、かなり非効率であることに注意してください。
Python には最も効率的なハッシュ アルゴリズムの 1 つがあることを思い出してください。ご都合に合わせてご利用ください。
私は思う:
#!/bin/python
bar in dict(Foo)
あなたが考えていることです。Python の辞書 (Python バージョンのハッシュ テーブル) 内に特定のキーが存在するかどうかを確認しようとする場合、確認する方法が 2 つあります。まず、 has_key()
辞書に添付されているメソッド、2 番目は上記の例です。ブール値を返します。
これであなたの質問の答えが得られるはずです。
さて、話は少し逸れますが、これを リスト内包表記 以前に与えられた答え(もう少し明確にするため)。 リスト内包表記 基本的なものからリストを作成する for ループ 修飾子付き。例として(少しわかりやすくするために)、 in dict
の言語構造 リスト内包表記:
二次元の辞書を持っているとします。 foo
キーを含む 2 次元辞書のみが必要です bar
. 。これを行う比較的簡単な方法は、 リスト内包表記 次のような条件付きです。
#!/bin/python
baz = dict([(key, value) for key, value in foo if bar in value])
注意してください if bar in value
ステートメント**の最後にある、これは、 リスト内包表記 条件を満たすキーと値のペアのみを保持します。** この場合 baz
は、bar を含む foo の辞書のみを含む新しい辞書です (コード例で何も見逃していないことを願っています...)リスト内包表記のドキュメントを参照する必要があるかもしれません。 docs.python.org チュートリアル そしてで secnetix.de, 、今後質問がある場合は、どちらのサイトも参考になります)。