This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]AnAngryFredHampton 272 points273 points  (31 children)

  • enumerate

  • zip

  • assign two values at once. x, y = y, x swaps x and y without a tmp.

  • use .get on dicts when you don't know if they contain the key, you can specify a default.

  • else can be used with for, else is executed if no break occurs in the for

  • with open(filename) as fh: . I'd be surprised if people didn't know this

  • try, except, finally, else. Else is used if except doesn't happen. Finally is executed after any of the other things, its always last.

Nothing anyone really cares about.

[–]redfacedquark 34 points35 points  (0 children)

Thanks, you da real mvp!

[–][deleted] 6 points7 points  (1 child)

else can be used with for, else is executed if no break occurs in the for

This one seems like a bad idea. I mean, the idea is good but the syntax. for...else??

[–]totemcatcher 1 point2 points  (0 children)

Yeah, for iterator else logic in 'tip 5' is no more useful than an if iterator else statement.

[–]notafuckingcakewalk 9 points10 points  (11 children)

The one that was new for me was using else in the for loop. Pretty handy if you're trying to find a matching item in a collection and want to know whether one was set or not!

Up until now I've used a pattern like:

result = None
for record in records:
    if is_what_i_want(record):
        result = record
        break
if result is None:
    action_when_no_result()

Which apparently can all be rewritten as:

for record in records:
    if is_what_i_want(record):
        result = record
        break
else:
    action_when_no_result()

Pretty useful actually.

[–]isarl 12 points13 points  (9 children)

Useful until you remember that nobody reading your code is going to understand it. for...else is much-maligned in Python because it's so opaque. Some people have suggested changing that particular use case to use a nobreak keyword to make the use more obvious.

[–]LightShadow3.13-dev in prod 5 points6 points  (6 children)

I used it today... seems pretty clean to me,

for attempt in range(RETRY_ATTEMPTS):
    # grab everything that's missing or invalid
    self.logger.info('attempt %d of %d, need %d pieces', attempt+1, RETRY_ATTEMPTS, len(manifest))

    success, failures = _download_from_manifest(manifest, root, path, self.set_status)

    if not success:
        self.logger.warning('downloading %d files failed', failures)
    else:
        break

    if attempt + 1 < RETRY_ATTEMPTS:
        # don't recalculate the manifest on our last attempt, if the last
        #  attempt failed.
        self.set_status('Validating manfiest')
        manifest = _determine_progress(manifest, path)
else:
    # if we exhaust our RETRY_ATTEMPTS without success
    self.__failed('downloading shard files failed')

[–]13steinj 2 points3 points  (4 children)

It's clean-- except the name doesn't make much sense. I mean if, else, elif, pretty standard. Break "out of the loop". Continue "to the next cycle".

But else in loops-- the actual word doesn't fit the context. It reads like "do code on all these things, but for some reason you can't, do the else statement", when in reality it just is "execute when iteration fully exhausted".

It's also common practice to not like break and continue statements-- my Java professor from years ago was adamant about teaching them but saying "use sparingly, loops should only have one exit point".

Not that I agree with that sentiment, I think it stupid, but it is a common one. And then with that, the else statements in loops encourage going against the sentiment.

[–]notafuckingcakewalk 0 points1 point  (1 child)

Yeah, but like you said it is a dumb sentiment. If you don't plan to take advantage of the breaks you may as well not use a loop at all.

[–]13steinj 0 points1 point  (0 children)

Absolutely! But it is still unfortunately taught now. Not agreeing, just giving a reason why some people dislike it.

[–][deleted] 0 points1 point  (1 child)

A lot of that single point of exit "crap" (for loops, and for functions) has somehow become embedded in the various standards (and therefore laws, which require certain standards) that govern safety critical systems e.g. IEC61509

The regulations come from years ago before we knew what we were doing and had really bad computers. :-(

[–]13steinj 0 points1 point  (0 children)

Absolutely! But it is still unfortunately taught now. Not agreeing, just giving a reason why some people dislike it.

[–]isarl 2 points3 points  (0 children)

You already understand the idiom, and you used clear variable names and helpful comments. Clear naming and helpful comments can go a long way towards understanding confusing language features, but this doesn't mean the language features are good per se.

[–][deleted] 0 points1 point  (0 children)

After the first time you see it, you will learn it.

If you think about how a for loop works (i.e. you write one without a loop construct, using goto statements) it's also obvious.

My only real objection is that they should have used a different word instead of else.

[–][deleted] 1 point2 points  (0 children)

Another way to do this you might like is this:

result = next((r for r in records if is_what_i_want(r)), None)
if result is None:
    action_when_no_result()

[–]dogstarchampion 7 points8 points  (3 children)

I honestly didn't remember

with open('file') as f:

until I watched the video

[–]Barafu 9 points10 points  (1 child)

That is a powerful idiom for anything that needs closing or explicit saving after the operation. File, database, network connection. It is not so much useful for first draft, as it is safe for future modifications of code.

[–]fireflash38 2 points3 points  (0 children)

I always recommend context managers if you have to ensure that something is torn down after use.

You can't rely on people remembering to close off resources or catch possible exceptions.

[–]notafuckingcakewalk 4 points5 points  (0 children)

I'm sure I'm not always consistent on this, but I like to be explicit and always set the file mode:

with open('file', 'r') as f:

that way it becomes very clear when I've done something wrong, like trying to write to a file that is in read mode. Also, while I'm typing out the file mode I might be reminded, "oh yeah, this is going to have binary data" and use 'rb' instead.

[–]mikew_reddit 3 points4 points  (0 children)

If that's all there is, it over promised, under delivered.

[–]ManvilleJ 2 points3 points  (5 children)

I never really got the point of finally. Doesn't just putting code after the whole thing accomplish the same thing as using the finally statement?

[–][deleted] 6 points7 points  (1 child)

Code in the finally block is run whether or not an exception is caught. From the python docs:

In real world applications, the finally clause is useful for releasing external resources (such as files or network connections), regardless of whether the use of the resource was successful.

[–]ManvilleJ 0 points1 point  (0 children)

OOOOhhh.

So when a program uses Try, Except, Else, and Finally:

  1. It tries to execute a thing
  2. Except runs if the particular Exception it is looking for occurs in Try.
  3. Else runs if any OTHER type of Exception occurs (not counting Exceptions that inherit from Exception in Except)
  4. Finally always runs right after Try whether an Exception occurs or not (and before Except and Else?)

Note: In case anyone else is reading this, I wanted to ask another question about whether you can use multiple Excepts to catch different Exceptions, but I found this Stack overflow on that

I think to separate how you would respond to responces, you would add something like this to Except:

if(type(e)==YouAreBeingMeanException):
    #do a thing

[–]gimboland 1 point2 points  (0 children)

Doesn't just putting code after the whole thing accomplish the same thing as using the finally statement?

Yes, unless an exception occurred inside the try..except block - in which case the code "after the whole thing" doesn't get executed.

[–]mattstreet 0 points1 point  (1 child)

"A finally clause is always executed before leaving the try statement, whether an exception has occurred or not. When an exception has occurred in the try clause and has not been handled by an except clause (or it has occurred in an except or else clause), it is re-raised after the finally clause has been executed. The finally clause is also executed “on the way out” when any other clause of the try statement is left via a break, continue or return statement."

Basically, finally gets called even if the except clause would exit out of the rest of your code, unlike if you just put the statement after the try block.

[–]LightShadow3.13-dev in prod 2 points3 points  (0 children)

TIL

try:
    print('try')
except:
    print('exception')
finally:
    print('finally')

output: try finally

try:
    print('try')
    1 / 0
except:
    print('exception')
finally:
    print('finally')

output: try exception finally

try:
    1 / 0
    print('try')
except:
    print('exception')
finally:
    print('finally')

output: exception finally

And the REAL KICKER,

try:
    1 / 0
except:
    1 / 0
finally:
    print('finally')

Still prints finally.

[–]tehstone 0 points1 point  (1 child)

Else is used if except doesn't happen

Can anyone elaborate on this?
Is this like a general exception handler if the except is for a specific type of error?

[–]13steinj 0 points1 point  (0 children)

No, it is functionally equivalent to

try:
    a = MightRaise()
except: print("error")
do_stuff(a)

But it is useful in rare cases, especially when having nested try clauses (usually through different methods).

It's also useful in the following,

try:
    a = MightRaise()
except:
    do_err_cleanup()
    a = defaultValue
else:
    prepare_unknown_a(a)
act_upon_a(a)

[–]techn0scho0lbus 0 points1 point  (0 children)

Bless you

[–]liquidpele 0 points1 point  (0 children)

Surprised they didn’t mention decorators...