3 ms·
TFA's use-case for for/else does not convince me: for server in servers: if server.check_availability(): primary_server = server
by TekMol 1y ago
TFA's use-case for for/else does not convince me:
for server in servers:
if server.check_availability():
primary_server = server
break
else:
primary_server = backup_server
deploy_application(primary_server)
As it is shorter to do this:
primary_server = backup_server
for server in servers:
if server.check_availability():
primary_server = server
break
deploy_application(primary_server)
- macleginn 1y agoI would say that the main benefit of for/else is readability and ease of writing since nothing needs to be front-loaded. (The downside is an arguably redundant addition to the basic syntax, of course.)
- wesselbindt 1y agoIf you replace the assignment in the else clause with something side-effectful it does make sense. But even then it harms the readability of the code to such a ridiculous extent. I've never not regretted adding an else clause to a for loop. Any cognitive benefits from Python's approach to for loops closely mirroring natural language just go out the window.
- Loranubi 1y agoI do like the else clause with for loops. However most people are not familiar with it, and also `else:` as a keyword is confusing. I always remember it as `no break:`.
- stevesimmons 1y agoI think of it as "otherwise:"
- int_19h 1y agoThat's still confusing though. The problem here is that `else` is semantically attached to `break`, but syntactically attached to the body of the loop. The latter makes it look like it executes if the loop body didn't, if you interpret it in the most straightforward way. IMO a better design would be to have a block that always executes at the end of the loop - there's even a reasonable keyword for it, `finally` - but gets a boolean flag indicating whether there was a break or not: for server in servers: if server.check_availability(): primary_server = server break finally did_break: if not did_break: primary_server = backup_server Or better yet, make `break` take an optional argument (which defaults to `True` if unspecified), and that's what you get in `finally`. So this could be written: for server in servers: if server.check_availability(): break server finally server: primary_server = server if server is not None else backup_server
- hk__2 1y agoWhat about this? for server in servers: if server.check_availability(): primary_server = server break else: logger.warning("Cannot find a valid server") # <--- primary_server = backup_server deploy_application(primary_server)
- TekMol 1y agoYes, that might be a better example.
- zahlman 1y agoThis kind of search can be done a variety of different ways, and is worth abstracting, e.g.: def first(candidates, predicate, default): try: return next(c for c in candidates if predicate(c)) except StopIteration: return default deploy_application(first(servers, Server.check_availability, backup_server))
- sowhat25 1y agoGreat, first() comes part of more_itertools !
- zahlman 1y ago`more_itertools` is definitely on my shortlist of things I wish were in the Python standard library. (The list of things I'd like to see cut out, is probably considerably longer. But that's mainly on aesthetic principles; it's probably not creating a significant maintenance burden.) And yet somehow I keep forgetting about it in the exact moments when it would probably make my life easier.
- nostoc 1y agoInstead of catching the `StopIteration` exception, you can simply provide a default case to `next` : next((c for c in candidates if predicate(c)), default)
- zahlman 1y agoIndeed. I was thinking of ways to generalize for the case where a default isn't desired, then decided against introducing that complexity in the example, then forgot that I could re-simplify further.
- paolosimone 1y agoIf the team is familiar with Functional Programming concepts, I'd actually suggest available_servers = (server for server in servers if server.check_availability()) primary_server = next(available_servers, backup_server) deploy_application(primary_server) which IMHO better conveys the intent to the reader (i.e. focus on "what to do" over "how to do it")
- HelloNurse 1y agoThe shorter version that saves the else: line assigns primary_server twice: it is OK for an assignment but a potential problem if doing something less trivial, and very ugly style in any case.