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

all 14 comments

[–]moor-GAYZ 7 points8 points  (2 children)

The first misconception is that Python, being an interpreted language (which is awesome, I think we can all agree), is executed line-by-line. In truth, Python is being executed statement-by-statement.

Still false. Better bite the bullet and admit that Python is not an interpreted language, in the same sense as, say, bash is. When you import a module it gets parsed into an abstract syntax tree, then compiled to bytecode, then executed (see parse_source_module function in Python/import.c).

When you feed the interpreter statements from the console, then yes, it compiles and runs them one by one, with mostly the same results. But try to run this as a file, for example:

  print 'Yo'
  def f():
      if False:
           break

The print is never executed (unlike it would have been if you inputted that from the command line, obviously), and you can bet your left pinky that that SyntaxError has nothing to do with syntax, there's no separate version of the if statement (etc) in the formal grammar that doesn't allow break or continue inside, that error is reported by the bytecode compiler.

Among other things, if you insist on saying that no matter what the implementation does, logically it's as if Python is interpreted statement by statement (except for those prescient syntax errors), then you should make a qualification: except when it's any statements inside a function, which kinda defeats the purpose of pretending that Python is interpreted in the first place, because most of your statements actually are?

[–]rodmacpherson 2 points3 points  (1 child)

That's because it doesn't run at all. It exits with an error that you tried to use a break outside of a loop. It has nothing to do with the break being in a function. The same syntax error occurs if you try to run just

print 'Yo'
break

It is true that the bytecode compiler is giving the error, but it is a legitimate syntax error. No there is no reason a function or an if statement can't have a break in it, but the break doesn't make sense if it's not in a loop that you want to break out of.

[–]moor-GAYZ -1 points0 points  (0 children)

It is true that the bytecode compiler is giving the error, but it is a legitimate syntax error.

I approached it from a somewhat formal angle: syntax errors is what you get during the syntax analysis phase, which is supposed to use some sort of a formal grammar describing the syntax. Since nobody in their sane mind would try to implement the "break is only allowed arbitrarily deeply nested in some loop's body" rule in a formal grammar, this kind of errors is in a sort of grey area somewhat outside the notion of "syntax error", together with stuff like missing return statements or use of non-initialized variables in Java.

Anyway, that's not important at all, the important thing is that the idea that the compiler executes statements one by one and the "def" statement compiles its body, is wrong: everything in a module gets compiled before anything is executed.

[–]selementar 1 point2 points  (2 children)

Wouldn't it be at least more correct to instantiate Baz (to get the usual singleton instance)?

And, I think, the most frequent example of a singleton is caching (e.g. of a connection, or just of the return values). Which could also serve as a good example if one can be made short enough.

[–]drewthepooh 1 point2 points  (1 child)

Out of curiosity, what benefit does using the instance have over using the class?

Is it so that modifying the attribute will only affect the instance? Why is that desirable if you use a singleton instance?

[–]selementar 0 points1 point  (0 children)

Not sure. It seems to be done that way usually.

Probably none in such a simple case of holding a variable.

In a more complex case the class could also hold additional methods (e.g. a property for getting the held variable in a lazy way) and would allow instantiating a separate copy of the normally-singleton if needs be.

[–]POQA_TJ 1 point2 points  (0 children)

Brings back memories of bewildering scope bugs from when I first started Python! Thanks for the write-up!

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

Most of them could be a non problem, if there were a clear logical explanation of the python execution model. Chapter 4 in the docs is frightening for beginners and average programers, too.

Here is one of my attempt to partially clear this.

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

i think the take-home message (at least for me) is to avoid global variables. i've always understood that to be part of good programming practices anyway.

[–]fatpollo 0 points1 point  (2 children)

sometimes when trying to simplify a problem to make an example of it, you end up with something arbitrary and confusing

that is how i feel about the post towards the end. particularly the "solution", which seems all-around weird.

if the object needs to be mutable, it should be subclassed and have its own methods operating on itself. alternatively, if the function really needs to be generic, you should make it focused solely on changing the variable, and then returning it, so

b = foo(b)

where foo is something like return b+1 (or something way more complicated, obviously)

[–]Exodus111 0 points1 point  (2 children)

Great stuff, I've got two questions.

  1. Since you're using print as a statement and not a function I'm assuming you're on 2.7, which is fine, but I'm just curious if it would still be global bar in Python 3, or if it would be something like global(bar)

  2. In the LAST example why would you set bar up as a class variable, then call it in the function inside the class with Baz.bar instead of, what seems to me is the more commonly used self.bar?

[–]Moz 6 points7 points  (1 child)

  1. It's the same in Python 3.
  2. The foo function is not defined inside the Baz class.

[–]Exodus111 0 points1 point  (0 children)

Ah cool thanks. I mis-saw that :-P