Pythonic ways to use 'else' in a for loop [duplicate]
I have hardly ever noticed a python program that uses else in a for loop.
I recently used it to perform an action based on the loop variable condition while exiting; as it is in the scope.
What is the pythonic way to use an else in a for loop? Are there any notable use cases?
And, yea. I dislike using break statement. I'd rather set the looping condition complex. Would I be able to get any benefit out of it, if I don't like to use break statement anyway.
Worth noting that for loop has an else since the language inception, the first ever version.
Asked by: Oliver282 | Posted: 06-12-2021
Answer 1
What could be more pythonic than PyPy?
Look at what I discovered starting at line 284 in ctypes_configure/configure.py:
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'],))
And here, from line 425 in pypy/annotation/annrpython.py (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
In pypy/annotation/binaryop.py, starting at line 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
A non-one-liner in pypy/annotation/classdef.py, starting at line 176:
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
Later in the same file, starting at line 307, an example with an illuminating comment:
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)
Answered by: Julia232 | Posted: 07-01-2022
Answer 2
If you have a for loop you don't really have any condition statement. So break is your choice if you like to abort and then else can serve perfectly to handle the case where you were not happy.
for fruit in basket:
if fruit.kind in ['Orange', 'Apple']:
fruit.eat()
break
else:
print 'The basket contains no desirable fruit'
Answered by: Marcus483 | Posted: 07-01-2022
Answer 3
Basically, it simplifies any loop that uses a boolean flag like this:
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"
and allows you to skip the management of the flag:
for divisor in range(2, n):
if n % divisor == 0:
print n, "is composite"
break
else:
print n, "is prime"
Note that there is already a natural place for code to execute when you do find a divisor - right before the break
. The only new feature here is a place for code to execute when you tried all divisor and did not find any.
This helps only in conjuction with break
. You still need booleans if you can't break (e.g. because you looking for the last match, or have to track several conditions in parallel).
Oh, and BTW, this works for while loops just as well.
any/all
Nowdays, if the only purpose of the loop is a yes-or-no answer, you might be able to write it much shorter with the any()
/all()
functions with a generator or generator expression that yields booleans:
if any(n % divisor == 0
for divisor in range(2, n)):
print n, "is composite"
else:
print n, "is prime"
Note the elegancy! The code is 1:1 what you want to say!
[This is as effecient as a loop with a break
, because the any()
function is short-circuiting, only running the generator expression until it yeilds True
. In fact it's usually even faster than a loop. Simpler Python code tends to have less overhear.]
This is less workable if you have other side effects - for example if you want to find the divisor. You can still do it (ab)using the fact that non-0 value are true in Python:
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"
but as you see this is getting shaky - wouldn't work if 0 was a possible divisor value...
Answered by: Lydia326 | Posted: 07-01-2022Answer 4
Without using break
, else
blocks have no benefit for for
and while
statements. The following two examples are equivalent:
for x in range(10):
pass
else:
print "else"
for x in range(10):
pass
print "else"
The only reason for using else
with for
or while
is to do something after the loop if it terminated normally, meaning without an explicit break
.
After a lot of thinking, I can finally come up with a case where this might be useful:
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
Answered by: Kellan149 | Posted: 07-01-2022
Answer 5
Perhaps the best answer comes from the official Python tutorial:
break and continue Statements, and else Clauses on Loops:
Answered by: Ada202 | Posted: 07-01-2022Loop statements may have an else clause; it is executed when the loop terminates through exhaustion of the list (with for) or when the condition becomes false (with while), but not when the loop is terminated by a break statement
Answer 6
I was introduced to a wonderful idiom in which you can use a for
/break
/else
scheme with an iterator to save both time and LOC. The example at hand was searching for the candidate for an incompletely qualified path. If you care to see the original context, please see the original question.
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
What makes the use of for
/else
so great here is the elegance of avoiding juggling a confusing boolean around. Without else
, but hoping to achieve the same amount of short-circuiting, it might be written like so:
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
I think the use of else
makes it more elegant and more obvious.
Answer 7
A use case of the else
clause of loops is breaking out of nested loops:
while True:
for item in iterable:
if condition:
break
suite
else:
continue
break
It avoids repeating conditions:
while not condition:
for item in iterable:
if condition:
break
suite
Answered by: Max135 | Posted: 07-01-2022
Answer 8
Here you go:
a = ('y','a','y')
for x in a:
print x,
else:
print '!'
It's for the caboose.
edit:
# 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 '!'
edit:
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
Answered by: Elian480 | Posted: 07-01-2022
Similar questions
python - What is the Pythonic way to write this loop?
for jr in json_reports:
jr['time_created'] = str(jr['time_created'])
python - How do you make this code more pythonic?
Could you guys please tell me how I can make the following code more pythonic?
The code is correct. Full disclosure - it's problem 1b in Handout #4 of this machine learning course. I'm supposed to use newton's algorithm on the two data sets for fitting a logistic hypothesis. But they use matlab & I'm using scipy
...
python - Pythonic way to return list of every nth item in a larger list
Say we have a list of numbers from 0 to 1000. Is there a pythonic/efficient way to produce a list of the first and every subsequent 10th item, i.e. [0, 10, 20, 30, ... ]?
Yes, I can do this using a for loop, but I'm wondering if there is a neater way to do this, perhaps even in one line?
python - Can this be made more pythonic?
I came across this (really) simple program a while ago. It just outputs the first x primes. I'm embarrassed to ask, is there any way to make it more "pythonic" ie condense it while making it (more) readable? Switching functions is fine; I'm only interested in readability.
Thanks
from math import sqrt
def isprime(n):
if n ==2:
return True
if n % 2 ==0 : # evens
return False
max = in...
python - What is the pythonic way to unpack tuples?
This question already has answers here:
python - Pythonic way to check if a file exists?
This question already has answers here:
python - Pythonic way to create a numpy array from a list of numpy arrays
I generate a list of one dimensional numpy arrays in a loop and later convert this list to a 2d numpy array. I would've preallocated a 2d numpy array if i knew the number of items ahead of time, but I don't, therefore I put everything in a list.
The mock up is below:
>>> list_of_arrays = map(lambda x: x*ones(2), range(5))
>>> list_of_arrays
[array([ 0., 0.]), array([ 1., 1.]), ar...
python - What is the most pythonic way to check if an object is a number?
Given an arbitrary python object, what's the best way to determine whether it is a number? Here is is defined as acts like a number in certain circumstances.
For example, say you are writing a vector class. If given another vector, you want to find the dot product. If given a scalar, you want to scale the whole vector.
Checking if something is int, float, ...
python - More pythonic way to write this?
I have this code here:
import re
def get_attr(str, attr):
m = re.search(attr + r'=(\w+)', str)
return None if not m else m.group(1)
str = 'type=greeting hello=world'
print get_attr(str, 'type') # greeting
print get_attr(str, 'hello') # world
print get_attr(str, 'attr') # None
Which works, but I am not particularly fond of this line:
return None if not m e...
python - Taking list's tail in a Pythonic way?
from random import randrange
data = [(randrange(8), randrange(8)) for x in range(8)]
And we have to test if the first item equals to one of a tail. I am curious, how we would do it in most simple way without copying tail items to the new list? Please take into account this piece of code gets executed many times in, say, update() method, and therefore it has to be quick as possible.
Using ...
python - Is it pythonic for a function to return multiple values?
In python, you can have a function return multiple values. Here's a contrived example:
def divide(x, y):
quotient = x/y
remainder = x % y
return quotient, remainder
(q, r) = divide(22, 7)
This seems very useful, but it looks like it can also be abused ("Well..function X already computes what we need as an intermediate value. Let's have X return that value also").
W...
python - A pythonic way to insert a space before capital letters
I've got a file whose format I'm altering via a python script. I have several camel cased strings in this file where I just want to insert a single space before the capital letter - so "WordWordWord" becomes "Word Word Word".
My limited regex experience just stalled out on me - can someone think of a decent regex to do this, or (better yet) is there a more pythonic way to do this that I'm missing?
python - Is there a more Pythonic way to merge two HTML header rows with colspans?
I am using BeautifulSoup in Python to parse some HTML. One of the problems I am dealing with is that I have situations where the colspans are different across header rows. (Header rows are the rows that need to be combined to get the column headings in my jargon) That is one column may span a number of columns above or below it and the words need to be appended or prepended based on the spanning. Below is a routine to d...
python - What is the pythonic way to share common files in multiple projects?
Lets say I have projects x and y in brother directories: projects/x and projects/y.
There are some utility funcs common to both projects in myutils.py and some db stuff in mydbstuff.py, etc.
Those are minor common goodies, so I don't want to create a single package for them.
Questions arise about the whereabouts of such files, possible changes to PYTHONPATH, proper way to import, etc.
What is th...
python - pythonic way to compare compound classes?
I have a class that acts as an item in a tree:
class CItem( list ):
pass
I have two trees, each with CItem as root, each tree item has some dict members (like item._test = 1). Now i need to compare this trees. I can suggest to overload a comparison operator for CItem:
class CItem( list ):
def __eq__( self, other ):
# first compare items as lists
if not list.__eq...
python - Pythonic URL Parsing
There are a number of questions about how to parse a URL in Python, this question is about the best or most Pythonic way to do it.
In my parsing I need 4 parts: the network location, the first part of the URL, the path and the filename and querystring parts.
http://www.somesite.com/base/first/secon...
list - Pythonic way to get some rows of a matrix
I was thinking about a code that I wrote a few years ago in Python, at some point it had to get just some elements, by index, of a list of lists.
I remember I did something like this:
def getRows(m, row_indices):
tmp = []
for i in row_indices:
tmp.append(m[i])
return tmp
Now that I've learnt a little bit more since then, I'd use a list comprehension like this:
python - What is the Pythonic way to write this loop?
for jr in json_reports:
jr['time_created'] = str(jr['time_created'])
python - How do you make this code more pythonic?
Could you guys please tell me how I can make the following code more pythonic?
The code is correct. Full disclosure - it's problem 1b in Handout #4 of this machine learning course. I'm supposed to use newton's algorithm on the two data sets for fitting a logistic hypothesis. But they use matlab & I'm using scipy
...
python - Pythonic Swap of 2 lists elements
I found that I have to perform a swap in python and I write something like this:
arr[first], arr[second] = arr[second], arr[first]
I suppose this is not so pythonic. Does somebody know how to do a swap in python more elegant?
EDIT:
I think another example will show my doubts:
self.memberlist[someindexA], self.memberlist[someindexB] = self.memberlist[som...
Still can't find your answer? Check out these communities...
PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python