14

for ループで else を使用する python プログラムに気付いたことはほとんどありません。

最近、終了時にループ変数の条件に基づいてアクションを実行するために使用しました。範囲内ですので。

forループでelseを使用するpythonicの方法は何ですか? 注目すべきユースケースはありますか?

そして、そうです。break ステートメントを使用するのは嫌いです。ループ条件を複雑に設定したいと思います。とにかく break ステートメントを使用したくない場合、それから利益を得ることができるでしょうか。

for ループには、最初のバージョンである言語の開始以来、else があることに注意してください。

4

8 に答える 8

15

PyPy よりも Pythonic と言えるものはありますか?

ctypes_configure/configure.py の 284 行目以降で発見したことを見てください。

    for i in range(0, info['size'] - csize + 1, info['align']):
        if layout[i:i+csize] == [None] * csize:
            layout_addfield(layout, i, ctype, '_alignment')
            break
    else:
        raise AssertionError("unenforceable alignment %d" % (
            info['align'],))

そしてここで、pypy/annotation/annrpython.py の 425 行目から ( clicky )

if cell.is_constant():
    return Constant(cell.const)
else:
    for v in known_variables:
        if self.bindings[v] is cell:
            return v
    else:
        raise CannotSimplify

pypy/annotation/binaryop.py の 751 行目から:

def is_((pbc1, pbc2)):
    thistype = pairtype(SomePBC, SomePBC)
    s = super(thistype, pair(pbc1, pbc2)).is_()
    if not s.is_constant():
        if not pbc1.can_be_None or not pbc2.can_be_None:
            for desc in pbc1.descriptions:
                if desc in pbc2.descriptions:
                    break
            else:
                s.const = False    # no common desc in the two sets
    return s

176 行目から始まる pypy/annotation/classdef.py の非ワンライナー:

def add_source_for_attribute(self, attr, source):
    """Adds information about a constant source for an attribute.
    """
    for cdef in self.getmro():
        if attr in cdef.attrs:
            # the Attribute() exists already for this class (or a parent)
            attrdef = cdef.attrs[attr]
            s_prev_value = attrdef.s_value
            attrdef.add_constant_source(self, source)
            # we should reflow from all the reader's position,
            # but as an optimization we try to see if the attribute
            # has really been generalized
            if attrdef.s_value != s_prev_value:
                attrdef.mutated(cdef) # reflow from all read positions
            return
    else:
        # remember the source in self.attr_sources
        sources = self.attr_sources.setdefault(attr, [])
        sources.append(source)
        # register the source in any Attribute found in subclasses,
        # to restore invariant (III)
        # NB. add_constant_source() may discover new subdefs but the
        #     right thing will happen to them because self.attr_sources
        #     was already updated
        if not source.instance_level:
            for subdef in self.getallsubdefs():
                if attr in subdef.attrs:
                    attrdef = subdef.attrs[attr]
                    s_prev_value = attrdef.s_value
                    attrdef.add_constant_source(self, source)
                    if attrdef.s_value != s_prev_value:
                        attrdef.mutated(subdef) # reflow from all read positions

同じファイルの後半、307 行目から始まる、わかりやすいコメント付きの例:

def generalize_attr(self, attr, s_value=None):
    # if the attribute exists in a superclass, generalize there,
    # as imposed by invariant (I)
    for clsdef in self.getmro():
        if attr in clsdef.attrs:
            clsdef._generalize_attr(attr, s_value)
            break
    else:
        self._generalize_attr(attr, s_value)
于 2009-03-26T14:56:44.983 に答える
6

forループがある場合、実際には条件ステートメントはありません。したがって、中絶したい場合は休憩を選択します。そうしないと、満足できなかった場合に完全に対処できます。

for fruit in basket:
   if fruit.kind in ['Orange', 'Apple']:
       fruit.eat()
       break
else:
   print 'The basket contains no desirable fruit'
于 2009-03-26T13:32:16.200 に答える
4

基本的に、次のようなブール値フラグを使用するループを単純化します。

found = False                # <-- initialize boolean
for divisor in range(2, n):
    if n % divisor == 0:
        found = True         # <-- update boolean
        break  # optional, but continuing would be a waste of time

if found:                    # <-- check boolean
    print n, "is composite"
else:
    print n, "is prime"

フラグの管理をスキップできます。

for divisor in range(2, n):
    if n % divisor == 0:
        print n, "is composite"
        break
else:
    print n, "is prime"

除数が見つかったときにコードを実行する自然な場所が既にあることに注意してくださいbreak。ここでの唯一の新機能は、すべての除数を試して何も見つからなかった場合にコードを実行する場所です。

これは と組み合わせてのみ役立ちますbreak。ブレークできない場合でもブール値が必要です (たとえば、最後の一致を探している場合や、複数の条件を並行して追跡する必要がある場合など)。

ああ、ところで、これは while ループでも同様に機能します。

任意/すべて

今日では、ループの唯一の目的が yes または no の答えである場合、ブール値を生成するジェネレーターまたはジェネレーター式を使用してany()/関数を使用すると、はるかに短く記述できる場合があります。all()

if any(n % divisor == 0 
       for divisor in range(2, n)):
    print n, "is composite"
else:
    print n, "is prime"

エレガンスに注目!コードはあなたが言いたいことを1:1に!

[これは、 を含むループと同じくらい効率的です。breakなぜなら、any()関数はショートサーキットであり、生成器の式を生成するまで実行するだけだからですTrue。実際、通常はループよりも高速です。より単純な Python コードは、聞き取りが少なくなる傾向があります。]

他の副作用がある場合、たとえば除数を見つけたい場合など、これはあまり機能しません。Python では 0 以外の値が true であるという事実を使用して、まだ (ab) 実行できます。

divisor = any(d for d in range(2, n) if n % d == 0)
if divisor:
    print n, "is divisible by", divisor
else:
    print n, "is prime"

しかし、ご覧のとおり、これは不安定になっています-0が可能な除数値である場合は機能しません...

于 2009-12-30T16:03:08.313 に答える
3

を使用しないbreakと、ブロックはandステートメントelseに対して何のメリットもありません。次の 2 つの例は同等です。forwhile

for x in range(10):
  pass
else:
  print "else"

for x in range(10):
  pass
print "else"

orを使用elseする唯一の理由は、ループが正常に終了した場合、つまり明示的な.forwhilebreak

よく考えた結果、これが役立つケースを最終的に思いつきました。

def commit_changes(directory):
    for file in directory:
        if file_is_modified(file):
            break
    else:
        # No changes
        return False

    # Something has been changed
    send_directory_to_server()
    return True
于 2009-03-26T13:36:16.313 に答える
2

おそらく最良の答えは、公式のPythonチュートリアルから得られます。

ステートメントを中断して続行し、それ以外の場合はループの句

ループステートメントにはelse句が含まれる場合があります。リストが使い果たされてループが終了したとき(with for)または条件がfalseになったとき(with while)に実行されますが、breakステートメントによってループが終了したときは実行されません。

于 2009-03-30T07:46:48.057 に答える
0

for//スキームを反復子とともに使用して、時間と LOC の両方を節約breakできる素晴らしいイディオムを紹介されました。else手元の例は、不完全修飾パスの候補を検索していました。元のコンテキストを確認したい場合は、元の質問を参照してください。

def match(path, actual):
    path = path.strip('/').split('/')
    actual = iter(actual.strip('/').split('/'))
    for pathitem in path:
        for item in actual:
            if pathitem == item:
                break
        else:
            return False
    return True

ここでfor/elseを非常に優れたものにしているのは、紛らわしいブール値をジャグリングするのを避けるという優雅さです。なしelseで、しかし同じ量の短絡を達成することを望んでいる場合、次のように記述できます。

def match(path, actual):
    path = path.strip('/').split('/')
    actual = iter(actual.strip('/').split('/'))
    failed = True
    for pathitem in path:
        failed = True
        for item in actual:
            if pathitem == item:
                failed = False
                break
        if failed:
            break
    return not failed

elseを使用すると、よりエレガントで明白になると思います。

于 2013-12-31T20:15:58.793 に答える
0

ループの句の使用例は、elseネストされたループから抜け出すことです。

while True:
    for item in iterable:
        if condition:
            break
        suite
    else:
        continue
    break

条件の繰り返しを回避します。

while not condition:
    for item in iterable:
        if condition:
            break
        suite
于 2022-02-03T17:05:36.300 に答える
-1

どうぞ:

a = ('y','a','y')
for x in a:
  print x,
else:
  print '!'

カブース用です。

編集:

# What happens if we add the ! to a list?

def side_effect(your_list):
  your_list.extend('!')
  for x in your_list:
    print x,

claimant = ['A',' ','g','u','r','u']
side_effect(claimant)
print claimant[-1]

# oh no, claimant now ends with a '!'

編集:

a = (("this","is"),("a","contrived","example"),("of","the","caboose","idiom"))
for b in a:
  for c in b:
    print c,
    if "is" == c:
      break
  else:
    print
于 2009-03-26T13:39:31.300 に答える