python3にはflattenがないとか言われるけどyield fromがあるので別に困らない。
とある言語には配列のflatten()があるようで、いまだによくpythonが引き合いに出されるのだが、小生は正直困ったことがあまりない。
用途もさることながら、実装にもまったく苦にはならない。
PEP380 サブジェネレータへの移譲
python3.3以降には、PEP380 サブジェネレータへの移譲 が備わっているためだ。
端的にいえば、自身のyeildに、他の iterable の出力を連結する機能である。
これを使えば、多段配列のflattenは、多段サブジェネレータとして実に簡潔に記述できる。
汎用性を考慮した上で馬鹿正直に書いてみた。
章題の通りで。 無限階層対応のflattenである。(事実上はスタックフレームの上限の影響を受ける)
isiterable()は、builtinで有ると思ったらなかった。残念。
pythonでは、iterableを判定するのは __iter__() を持っているかどうかのみらしい。
tupleとlistもgeneratorもこれに当てはまるので、エコな判定方法であるとは言える。
加えて、文字列 str インスタンスも実は iterable であるという落とし穴があるにはある。
これを"馬鹿正直"に回避すると、isiterableのような有様になる。
やや不本意だが iterable であれば未知のオブジェクトでも確実に展開はするはずだ。
入力をlistに絞ればisiterableはもっとサボれる。strかlistかを判定できれば良いので別関数にする必然性も薄れる。
わざわざtuple返しを用意してるのは「配列実体を返したい」という需要もどうやらあるらしいことを考慮したが故。
基本的に小生はgeneratorのままで使うことが多い。
正味せいぜい5行。これなら毎回書いてもまるで苦になるまい。
ネットにはやたらワンライナーにこだわる一派もあるが、yield from のほうがメモリ効率的には有利だと思われる。
flatten は yield from でできるよ。 と書いてるひともいるんだが....
ちょっと調べたら、2015年からyield from で flattenできますよという投稿は見当たる。
貼ってあるソースも似たようなものだ。
moduleもあることはある。
たかだが5行のために使うのもなあ。
Discussion