2017-05-04 3 views
3

多くの単語を含む文字列を与えられた場合、単語の順序を逆にしたいと思います。入力がThanks for all the fishの場合、出力はfish the all for Thanksになります。Pythonでのyieldの問題|ヘルパー関数の使用

私はジェネレータを使用してこれを解決しようとしています。新しいリストの作成を避けるためです。 私は、次の解決策を考え出した:

from itertools import islice 

def foo(s, begin, end): 
    for elem in islice(s, begin, end): 
     yield elem 

def baz(s): 
    i = len(s) 
    j = len(s) 

    while True: 
     i -= 1 
     if i == -1: 
      foo(s, i+1, j) 
      break 
     if s[i] == ' ': 
      foo(s, i+1, j) 
      yield ' ' 
      j = i 


s = "Thanks for all the fish" 
g = baz(s) 
for x in g: print(x, end='') 

しかし、このコードの出力は" "(スペースのみの文字列)です。一方

私は直接の代わりにそれらをもたらすの要素をprintた場合、それが動作します:

from itertools import islice 

def foo(s, begin, end): 
    for elem in islice(s, begin, end): 
     print(elem, end='') 

def baz(s): 
    i = len(s) 
    j = len(s) 

    while True: 
     i -= 1 
     if i == -1: 
      foo(s, i+1, j) 
      break 
     if s[i] == ' ': 
      foo(s, i+1, j) 
      print(' ', end='') 
      j = i 


s = "Thanks for all the fish" 
g = baz(s) 

これは動作し、出力fish the all for Thanksとして持っています。しかし、私はそれを印刷することはできません、私は正しい発電機を持ってほしいです。

from itertools import islice 

def baz(s): 
    i = len(s) 
    j = len(s) 

    while True: 
     i -= 1 
     if i == -1: 
      for elem in islice(s, i+1, j): 
       yield elem 
      break 
     if s[i] == ' ': 
      for elem in islice(s, i+1, j): 
       yield elem 
      yield ' ' 
      j = i 


s = "Thanks for all the fish" 
g = baz(s) 
for x in g: print(x, end='') 

これの出力はfish the all for Thanks次のとおりです。

は最後に、私はfooへの呼び出しを避けるならば、それはまた、働くことを発見しました。 このバージョンは私に欲しいもの(正確なジェネレータ)を提供しますが、その機能の中にコードを繰り返しています。

yield exchangeのスレッド交換スレッドを赤字にしていますが、間違っている可能性があります。 私が理解したことは、次のyield文が見つかるか、関数が終了するまでジェネレータが実行されるということです。 この問題は、これが正確に動作する方法ではないと私に思い出させますが、それ以外は私は無知です。

最初のコードスニペットのようにヘルパー関数を使用してこれを解決するにはどうすればよいですか?

答えて

2

あなたは発電機からyield要素successivlyするyield from foo(...)(もPEP-380 on "Syntax for Delegating to a Subgenerator"参照)またはfor whatever in foo(...): yield whateverを使用することができます。

def baz(s): 
    i = len(s) 
    j = len(s) 

    while True: 
     i -= 1 
     if i == -1: 
      yield from foo(s, i+1, j) # yield from syntax 
      break 
     if s[i] == ' ': 
      for item in foo(s, i+1, j): # for-loop over generator 
       yield item 
      yield ' ' 
      j = i 

をしかし、@trentclはコメントで述べたように、あなたのケースでは、あなたがする必要はありませんfoo -helper機能は基本的に何をするのですかisliceもあります。だから、単にislicefooを置き換えることができます:

def baz(s): 
    i = len(s) 
    j = len(s) 

    while True: 
     i -= 1 
     if i == -1: 
      yield from islice(s, i+1, j) # yield from syntax 
      break 
     if s[i] == ' ': 
      for item in islice(s, i+1, j): # for-loop over generator 
       yield item 
      yield ' ' 
      j = i 
+2

実際には、 'foo'は何もしません。あなたはislice(s、i + 1、j)からちょうど 'yieldできます。 – trentcl

+0

両方のおかげです。 @trentcl 'foo'は' no-op'とは何を意味しますか? –

+0

@FranciscoFigari 'foo'関数は必要ありません。このコメントに基づいて、私は 'foo'なしで' islice'を直接使用した2番目の例を追加しました。 – MSeifert

関連する問題