JavaScript の Python 化

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2025-01-14 22:19:48946ブラウズ

Pythonizing JavaScript

Python には、rangeenumeratezip など、反復可能なオブジェクトと反復子プロトコルに基づいて構築された強力なユーティリティ関数が多数あります。ジェネレーター関数と組み合わせることで、これらのプロトコルは 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 キーを使用してメソッドを定義する必要があります。 ArrayTypedArraySetMap などの多くの組み込みオブジェクトは、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 ユーティリティ

冒頭で述べたように、Python には上記のプロトコルに基づいた非常に便利な組み込みユーティリティがいくつかあります。 JavaScript には最近、

.drop() などのイテレーター用のヘルパー メソッドも追加されましたが、(おそらくまだ) Python にはさらに興味深いユーティリティがいくつかあります。 .filter()

実際に体験してみましょう!

理論部分は終わったので、いくつかの Python 関数の実装を始めましょう。

注: ここで示した実装はいずれも実稼働環境でそのまま使用しないでください。 エラー処理と境界条件のチェックが不足しています。

enumerate(iterable [,start])

Python の

は、入力シーケンスまたは反復可能オブジェクト内の各項目のタプルのシーケンスを返します。最初の位置にはカウントが含まれ、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

ジェネレーター関数を使用して、TypeScript でこれを実装してみましょう。 Python ドキュメントで説明されている実装をガイドとして使用できます
<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

repeat(elem [,n])
<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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。