7

Python の文字列は不変であり、バッファ インターフェイスをサポートしています。.split()スライスまたはメソッドを使用する場合、新しい文字列ではなく、古い文字列の一部を指すバッファーを返すと効率的です。ただし、毎回新しい文字列オブジェクトが作成されます。なんで?私が見る唯一の理由は、ガベージ コレクションが少し難しくなる可能性があることです。

True: 通常の状況では、メモリ オーバーヘッドは線形であり、目立ちません。コピーは高速で、割り当ても高速です。しかし、Python ではすでに多くのことが行われているので、そのようなバッファは努力する価値があるでしょうか?

編集:

このように部分文字列を形成すると、メモリ管理がはるかに複雑になるようです。任意の文字列の 20% のみが使用され、残りの文字列の割り当てを解除できない場合は、単純な例です。メモリ アロケータを改善して、文字列の割り当てを部分的に解除できるようにすることはできますが、おそらくほとんど反証になるでしょう。とにかく、bufferまたはmemoryviewメモリがクリティカルになった場合、すべての標準機能をエミュレートできます。コードはそれほど簡潔ではありませんが、何かを得るには何かをあきらめなければなりません。

4

3 に答える 3

3

基礎となる文字列表現は長さを追跡していてもnull-terminatedであるため、接尾辞ではない部分文字列を参照する文字列オブジェクトを持つことはできません。これは、suffice と non-suffice を異なる方法で処理するために多くの複雑さを追加するため、提案の有用性をすでに制限しています (そして、null で終わる文字列をあきらめると、他の結果がもたらされます)。

文字列の部分文字列を参照できるようにすることは、多くのガベージ コレクションと文字列の処理を複雑にすることを意味します。文字列ごとに、各文字またはインデックスの各範囲を参照するオブジェクトの数を追跡する必要があります。これは、多くstructの文字列オブジェクトとそれらを処理する操作が複雑になることを意味し、おそらく大幅に速度が低下します。

python3 から始まる文字列には 3 つの異なる内部表現があり、物事が面倒すぎて保守できなくなるという事実を追加してください。また、あなたの提案はおそらく受け入れられるのに十分な利点を与えていません。


この種の「最適化」のもう 1 つの問題は、「大きな文字列」の割り当てを解除する場合です。

a = "Some string" * 10 ** 7
b = a[10000]
del a

この操作の後、巨大な文字列である が割り当て解除されるのbを防ぐ部分文字列が得られます。a確かに小さな文字列のコピーを作成できますが、b = a[:10000](または別の大きな数) の場合はどうでしょうか? 10000 文字は、コピーを避けるために最適化を使用する必要がある大きな文字列のように見えますが、メガバイトのデータを解放することを妨げています。ガベージ コレクターは、大きな文字列オブジェクトの割り当てを解除してコピーを作成する価値があるかどうかをチェックし続ける必要があり、これらすべての操作はできるだけ高速である必要があります。そうしないと、時間パフォーマンスが低下します。

プログラムで使用される文字列の 99% は「小さい」(最大 10k 文字) ため、コピーは非常に高速ですが、提案する最適化は非常に大きな文字列で有効になり始めます (たとえば、巨大なテキストからサイズ 100k の部分文字列を取得する) であり、非常に小さい文字列では非常に遅くなります。これは一般的なケース、つまり最適化する必要があるケースです。


重要だと思われる場合は、自由に PEP を提案し、実装と、提案の速度/メモリ使用量の結果の変化を示してください。本当に努力する価値がある場合は、Python の将来のバージョンに含まれる可能性があります。

于 2013-08-04T11:30:45.123 に答える
3

それがスライスの仕組みです。スライスは常に浅いコピーを実行するため、次のようなことができます

>>> x = [1,2,3]
>>> y = x[:]

文字列の例外を作成することは可能ですが、それは本当に価値があるのでしょうか? Eric Lippert は、.NET ではそれを行わないという彼の決定についてブログに書きました。彼の主張は Python にも当てはまると思います。

この質問も参照してください。

于 2013-08-04T10:45:48.343 に答える