ホームページ >バックエンド開発 >Python チュートリアル >JavaScript の Python 化
Python には、range
、enumerate
、zip
など、反復可能なオブジェクトと反復子プロトコルに基づいて構築された強力なユーティリティ関数が多数あります。ジェネレーター関数と組み合わせることで、これらのプロトコルは 2016 年頃からすべての Evergreen ブラウザーと Node.js で利用できるようになりましたが、私の意見では、その使用率は驚くほど低いです。この記事では、それを変えることを期待して、TypeScript を使用してこれらのヘルパー関数の一部を実装します。
反復子プロトコルは、一連の値を生成する標準的な方法です。オブジェクトがイテレータになるには、next
メソッドを実装してイテレータ プロトコルに準拠する必要があります。例:
<code class="language-typescript">const iterator = { i: 0, next() { return { done: false, value: this.i++ }; } };</code>
その後、next
メソッドを繰り返し呼び出して値を取得できます。
<code class="language-typescript">console.log(iterator.next().value); // → 0 console.log(iterator.next().value); // → 1 console.log(iterator.next().value); // → 2 console.log(iterator.next().value); // → 3 console.log(iterator.next().value); // → 4</code>
next
メソッドは、value
プロパティ (実際の値を含む) と done
プロパティ (反復子が使い果たされたかどうか、つまり値を生成できなくなったかどうかを指定する) を含むオブジェクトを返す必要があります。 MDN によると、どちらの属性も厳密には必須ではなく、両方が欠落している場合、戻り値は { done: false, value: undefined }
として扱われます。
Iterable Object プロトコルを使用すると、オブジェクトが独自の反復動作を定義できます。 Iterable Object プロトコルに準拠するには、オブジェクトはイテレータを返す Symbol.iterator
キーを使用してメソッドを定義する必要があります。 Array
、TypedArray
、Set
、Map
などの多くの組み込みオブジェクトは、for...of
ループを使用して反復できるようにこのプロトコルを実装しています。
たとえば、配列の場合、values
メソッドは配列の Symbol.iterator
メソッドとして指定されます。
<code class="language-typescript">console.log(Array.prototype.values === Array.prototype[Symbol.iterator]); // → true</code>
次のように、反復子と反復可能オブジェクトのプロトコルを組み合わせて反復可能反復子を作成できます。
<code class="language-typescript">const iterable = { i: 0, [Symbol.iterator]() { const iterable = this; return { next() { return { done: false, value: iterable.i++ }; } }; } };</code>
これら 2 つのプロトコルの名前は残念ながら非常に似ており、今でも私を混乱させています。
ご想像のとおり、反復子と反復可能オブジェクトの例は無限であり、値を永久に生成できることを意味します。これは非常に強力な機能ですが、簡単に罠になる可能性もあります。たとえば、for...of
ループで iterable を使用した場合、ループは永久に継続するか、Array.from
のパラメーターとして使用すると、配列が大きくなりすぎるため、JS は最終的に RangeError
をスローします。 🎜>
<code class="language-typescript">// 将无限循环: for (const value of iterable) { console.log(value); } // 将抛出 RangeError const arr = Array.from(iterable);</code>イテレーターとイテラブルが無限になる可能性がある理由は、それらが遅延評価されるためです。つまり、使用されたときにのみ値を生成します。
ジェネレーター関数
ジェネレーター関数は、function*
(または function *
、アスタリスクは function
キーワードと関数名の間の任意の場所に指定できます) を使用して指定され、関数の実行を中断し、 キーワード 、内部状態を維持しながら、後で中断したところから実行を再開します: yield
<code class="language-typescript">const iterator = { i: 0, next() { return { done: false, value: this.i++ }; } };</code>Python ユーティリティ
や .drop()
などのイテレーター用のヘルパー メソッドも追加されましたが、(おそらくまだ) Python にはさらに興味深いユーティリティがいくつかあります。 .filter()
注: ここで示した実装はいずれも実稼働環境でそのまま使用しないでください。 エラー処理と境界条件のチェックが不足しています。
enumerate(iterable [,start]) は、入力シーケンスまたは反復可能オブジェクト内の各項目のタプルのシーケンスを返します。最初の位置にはカウントが含まれ、2 番目の位置には項目が含まれます。
enumerate
<code class="language-typescript">console.log(iterator.next().value); // → 0 console.log(iterator.next().value); // → 1 console.log(iterator.next().value); // → 2 console.log(iterator.next().value); // → 3 console.log(iterator.next().value); // → 4</code>は、カウンタの開始位置を示すオプションの
パラメータも受け入れます: enumerate
start
<code class="language-typescript">console.log(Array.prototype.values === Array.prototype[Symbol.iterator]); // → true</code>
JavaScript の文字列は Iterable Object プロトコルを実装しているため、単純に文字列を
<code class="language-typescript">const iterable = { i: 0, [Symbol.iterator]() { const iterable = this; return { next() { return { done: false, value: iterable.i++ }; } }; } };</code>関数に渡して次のように呼び出すことができます:
enumerate
<code class="language-typescript">// 将无限循环: for (const value of iterable) { console.log(value); } // 将抛出 RangeError const arr = Array.from(iterable);</code>は組み込み
ライブラリの一部であり、指定された入力 repeat
を n 回繰り返します。n が指定されていない場合は無限に繰り返します。もう一度、Python ドキュメントの実装を出発点として使用できます。 itertools
elem
<code class="language-typescript">function* sequence() { let i = 0; while (true) { yield i++; } } const seq = sequence(); console.log(seq.next().value); // → 0; console.log(seq.next().value); // → 1; console.log(seq.next().value); // → 2; // 将无限循环,从 3 开始 for (const value of seq) { console.log(value); }</code>関数と
関数の実装は長くなるので省略しますが、ロジックは原文と同じでコードをTypeScriptで書き換えただけです) cycle
range
結論
注意すべき点の 1 つは、パフォーマンスがカウンターを使用したオリジナルの
ループには程遠いということです。多くの場合、これは重要ではありませんが、高パフォーマンスのシナリオでは間違いなく重要です。 PCM データをキャンバスに描画し、イテレータやジェネレータを使用すると、フレームが失われることが気になります。これは後から考えると明らかかもしれませんが、当時の私にはそうではありませんでした:D
for
乾杯!
以上がJavaScript の Python 化の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。