2017-11-02 15 views
2

以下のメソッドは私のクラスにあり、作業を完了する前に自分自身をプライムしようとします。下塗りは、それに続く処理ループとしての作業を怠っています。この2つのループでは5つの線が繰り返されており、繰り返しをなくすための最良の方法は何か分かりません。この発電機を乾燥させる方法はありますか?

@classmethod 
def __get_start_words(cls, iterable, n, start_words): 
    iterator, buffer, sentinel = iter(iterable), Deque(maxlen=n), object() 
    for _ in range(n): 
     item = next(iterator, sentinel) 
     if item is sentinel: 
      # raise ValueError('iterable was too short to satisfy n') 
      break 
     buffer.append(item) 
     yield item 
    start_words[buffer.prefix] += 1 
    while True: 
     if buffer[0][-1] in cls.TERMINATORS: 
      start_words[buffer.suffix] += 1 
     item = next(iterator, sentinel) 
     if item is sentinel: 
      break 
     buffer.append(item) 
     yield item 

最後の5行をクラスまたはメソッドで一度だけ書くのに有効かつ明確な方法がありますか?

class Deque(collections.deque): 
    """Deque([iterable[, maxlen]]) -> Deque instance""" 

    @property 
    def prefix(self): 
     """Property allowing capture of all but last item in deque.""" 
     item = self.pop() 
     value = tuple(self) 
     self.append(item) 
     return value 

    @property 
    def suffix(self): 
     """Property allowing capture of all but first item in deque.""" 
     item = self.popleft() 
     value = tuple(self) 
     self.appendleft(item) 
     return value 

セカンドバージョン

prefixsuffixが何であるかについての質問への答えで


補遺

は、ここにDequeクラスであります

@classmethod 
def __get_start_words(cls, iterable, n, start_words): 
    iterator, buffer, count = iter(iterable), Deque(maxlen=n), 0 
    for item, count in zip(iterator, range(n)): 
     buffer.append(item) 
     yield item 
    if count + 1 < n: 
     raise ValueError('iterable was too short to satisfy n') 
    start_words[buffer.prefix] += 1 
    try: 
     while True: 
      if buffer[0][-1] in cls.TERMINATORS: 
       start_words[buffer.suffix] += 1 
      item = next(iterator) 
      buffer.append(item) 
      yield item 
    except StopIteration: 
     pass 

3番目のバージョンの方法のこの第三のバージョンはDanielから適応されています

:他人

を考慮に入れた後、以下の方法は、効率のために書かれたと言っていましたの洞察力のある答え:

@classmethod 
def __get_start_words(cls, iterable, n, start_words): 
    count, buffer = 0, Deque(maxlen=n) 
    for count, item in enumerate(iterable, 1): 
     yield item 
     buffer.append(item) 
     if count == n: 
      start_words[buffer.prefix] += 1 
     if count >= n and buffer[0][-1] in cls.TERMINATORS: 
      start_words[buffer.suffix] += 1 
    if count < n: 
     raise ValueError('iterable was too short to satisfy n') 

最終バージョン

この方法は、私の最初のバージョンよりも有意に良好である - ここに私を助けた人に感謝。

@classmethod 
def __get_start_words(cls, iterable, n, start_words): 
    buffer = Deque(maxlen=n) 
    for count, item in enumerate(iterable, 1): 
     yield item 
     buffer.append(item) 
     if count == n: 
      start_words[buffer.prefix] += 1 
     if count >= n and buffer[0][-1] in cls.TERMINATORS: 
      start_words[buffer.suffix] += 1 
    if len(buffer) < n: 
     raise ValueError('iterable was too short to satisfy n') 
+0

btw、 'buffer.prefix'と' buffer.suffix'とは何ですか? – quamrana

+0

私は、必要に応じて例外を発生させて、最初のループで論理チェックを行うことにしました。変更によって質問が無効になった場合、私はそれを喜んで削除します。 –

+1

おそらくSEのためのより良い質問:codereview – Aaron

答えて

4

使用for -loop:

@classmethod 
def __get_start_words(cls, iterable, n, start_words): 
    buffer = Deque(maxlen=n) 
    for idx, item in enumerate(iterable, 1): 
     buffer.append(item) 
     yield item 
     if idx == n: 
      start_words[buffer.prefix] += 1 
     if idx >= n and buffer[0][-1] in cls.TERMINATORS: 
      start_words[buffer.suffix] += 1 
    if len(buffer) < n: 
     raise ValueError('iterable was too short to satisfy n') 

2番目のバージョンではいくつかの考え:

@classmethod 
def __get_start_words(cls, iterable, n, start_words): 
    iterable = iter(iterable) 
    buffer = deque(islice(iterable, n-1)) 
    yield from buffer 
    if len(buffer) < n - 1: 
     raise ValueError('iterable was too short to satisfy n') 
    start_words[tuple(buffer)] += 1 
    for item in iterable: 
     buffer.append(item) 
     yield item 
     first = buffer.popleft() 
     if first[-1] in cls.TERMINATORS: 
      start_words[tuple(buffer)] += 1 
isliceを使用しているとき countは必要ありません:につながる

for item in islice(iterator, n): 
    buffer.append(item) 
    yield item 
if len(buffer) < n: 
    raise ValueError('iterable was too short to satisfy n') 

さらにリファクタリング

+0

提案していただきありがとうございます!コードを調べた後、いくつかのエラーチェックが行われるべきであることを認識し、最初のループを変更する代わりに例外を発生させて変更しました。あなたは例外的な事件について既によく書かれた答えを適用してもよろしいですか? –

+0

例外を発生させるためにコードを修正したためにコードを変更する理由がないと思っている場合は、私に知らせてください。これまでと同じように「育てる」。 –

+0

@NoctisSkytowerこれは基本的に私がそれにアプローチする方法です。カスタム 'raise StopIteration'アプローチを使ってループを複製しようとしているように見えました – Aaron

関連する問題