シーケンスの一部をシーケンスのコピーを作らずにビルトイン関数に渡す方法

まだ自己解決していないが、問題提起だけ再度まとめておく。リストや文字列などのシーケンスの一部をビルトイン関数(やビルトインクラスのメソッド)、例えば、reversed()やcmp()などの引数やオブジェクトとして使用する場合、新たなインスタンスを作らないといけない。

L = [0, 1, 2, 3, 4, 5]
L[:3] = reversed(L[:3])  # reversed()の引数でL[:3]とした時にインスタンスが発生。これが不満。

そこで、以下のように同じシーケンスのコピーを作らずにシーケンスの一部を取り出したいが、

L = [0, 1, 2, 3, 4, 5]
L2 = (L[k] for k in xrange(0, 3))  # インデックス3より小さいシーケンスをジェネレータで取り出す

ここでの、L2をreversed()やcmp()に直接渡せない。通常、シーケンスの一部をビルトイン関数に渡す場合は、スライシングして新しいインスタンスを作り、それに対して呼び出してやるしかないと思われる(ほんとに方法がないのか…?)。


ジェネレータを保持するラッパークラスを作り、そのオブジェクトをreversed()などに渡し、参照のタイミングで[]でジェネレータの値を取得できるようにしてやれば良いと一瞬思ったが、[]によるランダムアクセスはジェネレータの場合できないので、そういったアルゴリズムを使っている関数に対してはジェネレータでは根本的に無理な気もしてきた…。


それだったら、そもそもシーケンスを直接ラッパークラスで保持して、スライスしたいインデックスをコンストラクタで入れてあげて、[]で参照する際にオフセットして取り出してあげるようにすればできるような気もする。そういった第3者的なスライシング用オブジェクトを自前で用意するのも汎用性を損なうという点から不満であるが、「効率の良さ」と「ビルトイン関数を使える」という2つのメリットのためには仕方ないのか…。この実装方法も後で考えて見るつもり…。