Techioz Blog

リスト上でメソッドチェーンを実行できますか?

概要

Ruby ではこのようなことをやります。私は Ruby 出身なので、メソッドチェーンを非常に簡単に実行できます。例を見てみましょう。リストからすべての偶数を選択し、それに 5 を追加したい場合。

nums = [...]
nums.select {|x| x % 2 == 0 }.map { |x| x + 5 }

Python では次のようになります

nums = [...]
list(map(lambda x: x + 5, filter(lambda x: x % 2 == 0, nums)))

Python の構文はひどいようです。 Google で調べてみましたが、良い答えは見つかりませんでした。私が見たのは、カスタム オブジェクトを使用してこのようなことをどのように実現できるかということだけでしたが、このようにリストを処理するものは何もありませんでした。何かが足りないのでしょうか?

デバッグ コンソールでは、いくつかの ActiveRecord オブジェクトを配列で取得することが非常に便利で、メソッドをチェーンしてエンティティを処理してデバッグすることができました。 Python では、作業が多すぎるように思えます。

解決策

Ruby では、すべての列挙可能なオブジェクトに Enumerable インターフェイスが含まれているため、あなたが言及したような便利なメソッドをすべて取得できます。しかし、Python にはイテラブルに共通のスーパークラスがありません。イテラブルは文字通り「iter をサポートするもの」として定義され、すべてのイテラブルのスーパークラスのふりをする Iterable と呼ばれる抽象クラスがありますが、実際にはメソッドを提供しておらず、継承内にありません。すべてのイテラブルのチェーン (add を記述して + をオーバーライドできるのと同じ方法で、dunder メソッドの魔法を使用して isinstance と issubclass の動作をオーバーライドします)。

Alakazam ライブラリはまさにこの機能を実装しています。 (開示: 私はこのライブラリの作成者および管理者ですが、まさにあなたが求めていることを実行するので、ここで言及します)

Alakazam は、任意の Python 反復可能オブジェクトをラップし、すべての組み込み Python シーケンス メソッド、すべての itertools モジュール、およびデフォルトでは Python に含まれていないその他のいくつかの便利なストリーム指向メソッドをメソッドとして提供する Alakazam クラスを提供します。 。上記の例を考えてみましょう

nums.select {|x| x % 2 == 0 }.map { |x| x + 5 }

Python では次のようになります

list(map(lambda x: x + 5, filter(lambda x: x % 2 == 0, nums)))

アラカザムの場合は次のようになります

zz.of(nums).filter(lambda x: x % 2 == 0).map(lambda x: x + 5).list()

または、Alakazam のラムダ構文を使用する

zz.of(nums).filter(_1 % 2 == 0).map(_1 + 5).list()

Alakazam の filter や map などのメソッドは、必要に応じて Python の動作に合わせて遅延するため、反復可能オブジェクトを消費して単一のリスト結果を生成するには、最後に list() を記述する必要があります。