ホームページ  >  記事  >  バックエンド開発  >  Python でイテレータとジェネレータを使用する方法

Python でイテレータとジェネレータを使用する方法

PHPz
PHPz転載
2023-05-22 12:13:21910ブラウズ

1. イテレータ (foreach)

1. 反復可能オブジェクト

組み込み __iter__ メソッドを持つものは反復可能オブジェクトと呼ばれます。

Python の組み込みの str、list、tuple、dict、set、file はすべて反復可能なオブジェクトです。

x = 1.__iter__  # SyntaxError: invalid syntax

# 以下都是可迭代的对象
name = 'nick'.__iter__
print(type(name))  # 'method-wrapper'>

2. イテレータ オブジェクト

イテラブル オブジェクトの __iter__ メソッドを実行し、得られる戻り値がイテレータ オブジェクトです。

文字列とリストのみがインデックス値に依存しますが、他の反復可能オブジェクトはインデックス値に依存できず、反復子オブジェクトのみを使用できます。

  • には組み込みの __iter__ メソッドがあり、このメソッドを実行するとイテレータ自体が取得されます。

  • 組み込みの __next__ メソッド。このメソッドを実行すると、反復子オブジェクトの値が取得されます。

s = 'hello'
iter_s = s.__iter__()
print(type(iter_s))  # 'str_iterator'> iter_s为迭代器对象

while True:
    try:
        print(iter_s.__next__())
    except StopIteration:
        break
#hello

3. イテレータには、iter() と next() という 2 つの基本メソッドがあります。

s = 'hello'
iter_s = iter(s) # 创建迭代器对象
print(type(iter_s))  #  iter_s为迭代器对象

while True:
    try:
        print(next(iter_s)) # 输出迭代器的下一个元素

    except StopIteration:
        break
# hello

4. for イテレータ ループ

通常の for ステートメントを使用して反復可能なオブジェクトを直接調べることができます

for ループはイテレータ ループと呼ばれ、in Object の後に反復可能である必要があります。 。

#str
name = 'nick' 
for x in name:
    print(x)

#list
for x in [None, 3, 4.5, "foo", lambda: "moo", object, object()]:
    print("{0}  ({1})".format(x, type(x)))

#dict
d = {
    '1': 'tasty',
    '2': 'the best',
    '3 sprouts': 'evil',
    '4': 'pretty good'
}

for sKey in d:
    print("{0} are {1}".format(sKey, d[sKey]))

#file
f = open('32.txt', 'r', encoding='utf-8')
for x in f:
    print(x)
f.close()

5. イテレータの実装 (__next__ と __iter__)

2 つのメソッド __iter__() と __next__() をクラスに実装した後、それをイテレータとして使用できます。

  • # __iter__() メソッドは、__next__() メソッドを実装する特別な反復子オブジェクトを返し、StopIteration 例外を通じて反復の完了を識別します。

  • __next__() メソッドは、次の反復子オブジェクトを返します。

  • StopIteration 例外は、無限ループを防ぐために反復の完了を識別するために使用されます。__next__() メソッドでは、指定されたサイクル数が完了した後に StopIteration 例外がトリガーされるように設定できます。反復を終了します。

数値を返す反復子を作成します。初期値は 1 で、徐々に 1 ずつ増加し、20 回の反復後に実行を停止します:

class MyNumbers:
  def __iter__(self):
    self.a = 1
    return self
 
  def __next__(self):
    if self.a <= 20:
      x = self.a
      self.a += 1
      return x
    else:
      raise StopIteration
 
myclass = MyNumbers()
myiter = iter(myclass)
 
for x in myiter:
  print(x)

1。範囲をシミュレートします

class Range:
    def __init__(self, n, stop, step):
        self.n = n
        self.stop = stop
        self.step = step

    def __next__(self):
        if self.n >= self.stop:
            raise StopIteration
        x = self.n
        self.n += self.step
        return x

    def __iter__(self):
        return self


for i in Range(1, 7, 3):
    print(i)

#1
#4

2. フィボナッチ数列

class Fib:
    def __init__(self):
        self._a = 0
        self._b = 1

    def __iter__(self):
        return self

    def __next__(self):
        self._a, self._b = self._b, self._a + self._b
        return self._a


f1 = Fib()
for i in f1:
    if i > 100:
        break
    print(&#39;%s &#39; % i, end=&#39;&#39;)

# 1 1 2 3 5 8 13 21 34 55 89

2. ジェネレーター

1. yield

Pythonでは、yieldを使用する関数をジェネレーターと呼びます。

ジェネレーターはイテレータを返す特別な関数であり、反復操作にのみ使用できます。言い換えれば、ジェネレータはイテレータです。

ジェネレーターの呼び出しプロセス中、yield が発生するたびに、関数は一時停止して現在実行中の情報をすべて保存し、yield の値を返し、次回 next() で現在の位置から続行します。メソッドが実行されます。実行します。

ジェネレータ関数を呼び出してイテレータ オブジェクトを返します。

yieldの後に複数の値 (任意の型) を続けることができますが、戻り値はタプル型になります。

  • #反復子をカスタマイズする方法を提供します

  • #yield は関数を一時停止し、現在の戻り値を提供できます
  • import sys
    
    
    def fibonacci(n):  # 函数 - 斐波那契
        a, b, counter = 0, 1, 0
        while True:
            if counter > n:
                return
            yield a
            a, b = b, a + b
            counter += 1
    
    
    f = fibonacci(10)  #f 是一个生成器
    print(type(f))  # &#39;generator&#39;>
    
    while True:
        try:
            print(next(f), end=" ")
        except StopIteration:
            sys.exit()
  • yield と return:

    同じこと: どちらも関数内で使用され、どちらも値を返すことができ、戻り値には型も数値もありません。
  • 相違点: return は値を 1 回だけ返すことができ、yield は複数の値を返すことができます
  • 2. カスタム range() メソッド
  • def my_range(start, stop, step=1):
        while start < stop:
            yield start
            start += 1
    
    
    g = my_range(0, 3)
    print(f"list(g): {list(g)}")
複合バージョン:

def range(*args, **kwargs):
    if not kwargs:
        if len(args) == 1:
            count = 0
            while count < args[0]:
                yield count
                count += 1
        if len(args) == 2:
            start, stop = args
            while start < stop:
                yield start
                start += 1
        if len(args) == 3:
            start, stop, step = args
            while start < stop:
                yield start
                start += step

    else:
        step = 1

        if len(args) == 1:
            start = args[0]
        if len(args) == 2:
            start, stop = args

        for k, v in kwargs.items():
            if k not in [&#39;start&#39;, &#39;step&#39;, &#39;stop&#39;]:
                raise (&#39;参数名错误&#39;)

            if k == &#39;start&#39;:
                start = v
            elif k == &#39;stop&#39;:
                stop = v
            elif k == &#39;step&#39;:
                step = v

        while start < stop:
            yield start
            start += step


for i in range(3):
    print(i)  # 0,1,2

for i in range(99, 101):
    print(i)  # 99,100

for i in range(1, 10, 3):
    print(i)  # 1,4,7

for i in range(1, step=2, stop=5):
    print(i)  # 1,3

for i in range(1, 10, step=2):
    print(i)  # 1,3,5,7,9

3. ジェネレーター式 (i.for .in)

リスト内包表記の [] を () に置き換えて、ジェネレーター式モードを取得します。

利点: リスト内包表記と比較して、メモリを節約でき、一度にメモリ内に 1 つの値しか生成できません。

t = (i for i in range(10))
print(t)  # <generator object  at 0x00000000026907B0>
print(next(t))  # 0
print(next(t))  # 1

例:

with open(&#39;32.txt&#39;, &#39;r&#39;, encoding=&#39;utf8&#39;) as f:
    nums = [len(line) for line in f]  # 列表推导式相当于直接给你一筐蛋

print(max(nums))  # 2


with open(&#39;32.txt&#39;, &#39;r&#39;, encoding=&#39;utf8&#39;) as f:
    nums = (len(line) for line in f)  # 生成器表达式相当于给你一只老母鸡。

print(max(nums))  # ValueError: I/O operation on closed file.

以上がPython でイテレータとジェネレータを使用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。