(訳)Pythonキーワードyieldの解釈--下編(stackoverflow)

4869 ワード

6.コードに戻る
(訳者注:これはこの質問に答える具体的な解釈です)
ビルダー:
# Here you create the method of the node object that will return the generator
def node._get_child_candidates(self, distance, min_dist, max_dist):

  # Here is the code that will be called each time you use the generator object :

  # If there is still a child of the node object on its left
  # AND if distance is ok, return the next child
  if self._leftchild and distance - max_dist < self._median:
            yield self._leftchild

  # If there is still a child of the node object on its right
  # AND if distance is ok, return the next child
  if self._rightchild and distance + max_dist >= self._median:
                yield self._rightchild

  # If the function arrives here, the generator will be considered empty
  # there is no more than two values : the left and the right children

呼び出し元:
# Create an empty list and a list with the current object referenceresult, candidates = list(), [self]

# Loop on candidates (they contain only one element at the beginning)

while candidates: 
    # Get the last candidate and remove it from the list 
    node = candidates.pop() 

    # Get the distance between obj and the candidate 
    distance = node._get_dist(obj) # If distance is ok, then you can fill the result 
    if distance <= max_dist and distance >= min_dist: 
        result.extend(node._values) 

    # Add the children of the candidate in the candidates list 
    # so the loop will keep running until it will have looked 
    # at all the children of the children of the children, etc. of the candidate
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))

return result

このコードにはいくつかの小さな部分が含まれています.
  • リストを反復しますが、反復ではリストが拡張され続けています.無限反復を引き起こす可能性があるため、これらのネストされたデータを反復する簡潔な方法です.candidates.extend(node._get_child_candidates(distance,min_dist,max_dist))はジェネレータのすべての値を使い果たしたが、whileは常に新しいジェネレータを生成し、前回とは異なる値を生成し、同じノードに作用しない以上、whileは絶えず新しいジェネレータを生成する.
  • extend()は反復器に作用し、パラメータを反復器の後ろに追加する反復器法である.

  • 通常、リストパラメータを渡します.
    >>> a = [1, 2]
    >>> b = [3, 4]
    >>> a.extend(b)
    >>> print(a)
    [1, 2, 3, 4]
    

    しかし、あなたのコードにはジェネレータがあります.これはいいです.なぜなら、
  • すべての値
  • を2回読む必要はありません
  • サブオブジェクトはたくさんありますが、メモリに格納する必要はありません.

  • Pythonはメソッドのパラメータがリストであるかどうかに関心がないため、これは効果的です.Pythonは反復可能であることを望んでいるので、このパラメータはリスト、メタグループ、文字列、ジェネレータ...これはducktypingと呼ばれています.これもPythonがこんなに素晴らしい理由の一つですが、これはもう別の問題です.
    ここで止まって、ジェネレータの高度な使い方を見てみましょう.
    7.制御ジェネレータが尽きる
    >>> class Bank(): # let's create a bank, building ATMs
    ...  crisis = False...  def create_atm(self) :
    ...      while not self.crisis :
    ...          yield "$100"
    >>> hsbc = Bank() # when everything's ok the ATM gives you as much as you want
    >>> corner_street_atm = hsbc.create_atm()
    >>> print(corner_street_atm.next())
    $100
    
    >>> print(corner_street_atm.next())
    $100
    
    >>> print([corner_street_atm.next() for cash in range(5)])
    ['$100', '$100', '$100', '$100', '$100']
    
    >>> hsbc.crisis = True # crisis is coming, no more money!
    >>> print(corner_street_atm.next())
    
    
    >>> wall_street_atm = hsbc.create_atm() # it's even true for new ATMs
    >>> print(wall_street_atm.next())
    
    
    >>> hsbc.crisis = False # trouble is, even post-crisis the ATM remains empty
    >>> print(corner_street_atm.next())
    
    
    >>> brand_new_atm = hsbc.create_atm() # build a new one to get back in business
    >>> for cash in brand_new_atm :
    ...  print cash
    
    $100
    $100
    $100
    $100
    $100
    $100
    $100
    $100
    $100
    ...
    

    これは、いくつかのリソースへのアクセスを制御するのに役立ちます.
    8.Itertools、あなたの親友
    itertoolsには多くの特殊な反復法が含まれている.反復器をコピーしたいと思ったことがありますか?2つの反復器を直列に接続しますか?ネストされたリストをグループ化しますか?新しいリストのzip/mapを作成する必要はありませんか?
    import itertoolsだけ
    例が必要ですか?試合中に4頭の馬がゴールに着く可能性のある順番を見てみましょう.
    >>> horses = [1, 2, 3, 4]
    >>> races = itertools.permutations(horses)
    >>> print(races)
    
    
    >>> print(list(itertools.permutations(horses)))
    [(1, 2, 3, 4), 
    (1, 2, 4, 3),
     (1, 3, 2, 4), 
    (1, 3, 4, 2), 
    (1, 4, 2, 3), 
    (1, 4, 3, 2), 
    (2, 1, 3, 4), 
    (2, 1, 4, 3), 
    (2, 3, 1, 4),
    (2, 3, 4, 1),
    (2, 4, 1, 3), 
    (2, 4, 3, 1), 
    (3, 1, 2, 4), 
    (3, 1, 4, 2), 
    (3, 2, 1, 4), 
    (3, 2, 4, 1), 
    (3, 4, 1, 2),
    (3, 4, 2, 1), 
    (4, 1, 2, 3), 
    (4, 1, 3, 2), 
    (4, 2, 1, 3),
    (4, 2, 3, 1), 
    (4, 3, 1, 2), 
    (4, 3, 2, 1)]
    

    9.反復器の内部メカニズムを理解する
    反復は反復可能なオブジェクト(iter()メソッドを実装)と反復器(next()メソッドを実装)を実装するプロセスである.反復可能オブジェクトは、反復器を取得できる任意のオブジェクトです.反復器は、反復可能なオブジェクトを反復できるオブジェクトです.
    もっとこの文章を見てhttp://effbot.org/zone/python-for-statement.htm