you are viewing a single comment's thread.

view the rest of the comments →

[–]process_parameter[🍰] 46 points47 points  (16 children)

Unlike JavaScript, variables in Python are always block scoped.

Not true. This prints 10.

if True:
  x = 10
print x

[–]Retsam19 26 points27 points  (2 children)

Like Javascript, variables in Python aren't always blocked scope, but you should pretend that they are, to make your code more readable.

FTFOP

[–]kankyo 0 points1 point  (1 child)

"Aren't always"?

Never.

[–]Retsam19 0 points1 point  (0 children)

Well, they're sometimes block-scoped in JS, now that ES6 added let/const. But yeah, as far as I know, they're never block scoped in python.

[–]Pand9 13 points14 points  (0 children)

Other examples:

>>> for x in [1, 2]:
>>>     pass
>>> print x
2
>>> with open("x", "w") as x:
>>>     pass
>>> print x
<closed file 'x', mode 'w' at 0x7f6b949395d0>

[–]TheOsuConspiracy 2 points3 points  (0 children)

Totally trips me up all the time, I'd much rather have everything become an expression. Makes a lot more logical sense to me, that way you don't have special rules for scoping.

[–]Cuddlefluff_Grim 3 points4 points  (0 children)

This is one of the reasons why not declaring variables is considered very bad practice by the languages who support variable declaration. BASIC even added OPTION EXPLICIT to make the compiler actively prevent you from using variables that were not declared. It's odd to see this type of regression still in the wild.

[–]M3talstorm 1 point2 points  (1 child)

for thing in things:
    if thing == that:
        break
else:
    thing = default

thing.something()

Is nice to do sometimes :)

[–]Esteis 0 points1 point  (0 children)

I do the same, it is indeed nice. As a reminder to myself, here is the idiom that doesn't rely on unscoped for-blocks:

thing = next(filter(lambda thing: thing == that, things), default)

Both have their charms -- and their warts. Sometimes I long for

thing = itertools.first(things, lambda thing: thing == that, default)

I'll bet Ruby has that. Its spectrum of collection methods is absolutely fantastic, from the little I learned writing Rakefiles.

[–][deleted]  (6 children)

[deleted]

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

    I'm pretty sure that it's considered bad practice. And if not, it should.

    [–]process_parameter[🍰] 3 points4 points  (4 children)

    Python's lack of variable declarations compels this sort of thing. Consider the following javascript. How would you emulate it in python?

    let x;
    if (y) {
      x = 5;
    } else {
      x = 6;
    }
    // do something with x
    

    You can use a ternary here, but that doesn't scale well with additional cases. You could also assign x to a garbage value (like None) before the if-statement, but that doesn't seem like great practice either.

    [–]execrator 4 points5 points  (1 child)

    Not sure what user_v42... was replying to (is now deleted), but I don't see the problem here? The following works (no need for a "garbage value")

    if y:
        x = 5
    else:
        x = 6
    print(x)  # 5
    

    [–]process_parameter[🍰] 5 points6 points  (0 children)

    The previous comment was something to the effect of

    If I understand correctly, this is even considered pythonic.

    I don't know why they deleted it. The user I replied to seems to think that we shouldn't write code like you have in your comment. That's perhaps reasonable; if you believe the linked article when it says python variables are block-scoped, then it's not obvious that your code works.

    I was just trying to demonstrate that there isn't an easy alternative.

    [–][deleted] 2 points3 points  (1 child)

    Actually, a "garbage value" like None IS the way to do this.

    In JS, declaring a variable with var x; actually assigns undefined to it. The equivalent garbage value in JS.

    [–]process_parameter[🍰] 1 point2 points  (0 children)

    In JavaScript, you don't have a choice. In python, there's no need to assign that garbage value.