Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #34093 > unrolled thread

amazing scope?

Started byandrea crotti <andrea.crotti.0@gmail.com>
First post2012-11-30 11:11 +0000
Last post2012-11-30 17:57 -0500
Articles 5 — 4 participants

Back to article view | Back to comp.lang.python


Contents

  amazing scope? andrea crotti <andrea.crotti.0@gmail.com> - 2012-11-30 11:11 +0000
    Re: amazing scope? Ulrich Eckhardt <ulrich.eckhardt@dominolaser.com> - 2012-11-30 12:23 +0100
      Re: amazing scope? andrea crotti <andrea.crotti.0@gmail.com> - 2012-11-30 16:05 +0000
      Re: amazing scope? Chris Angelico <rosuav@gmail.com> - 2012-12-01 03:08 +1100
      Re: amazing scope? Dave Angel <d@davea.name> - 2012-11-30 17:57 -0500

#34093 — amazing scope?

Fromandrea crotti <andrea.crotti.0@gmail.com>
Date2012-11-30 11:11 +0000
Subjectamazing scope?
Message-ID<mailman.380.1354273891.29569.python-list@python.org>
I wrote a script, refactored it and then introducing a bug as below:

def record_things():
    out.write("Hello world")

if __name__ == '__main__':
    with open('output', 'w') as out:
        record_things()


but the shocking thing is that it didn't actually stopped working, it
still works perfectly!

What my explanation might be is that the "out" is declared at module
level somehow,
but that's not really intuitive and looks wrong, and works both on
Python 2.7 and 3.2..

[toc] | [next] | [standalone]


#34097

FromUlrich Eckhardt <ulrich.eckhardt@dominolaser.com>
Date2012-11-30 12:23 +0100
Message-ID<thhmo9-ie6.ln1@satorlaser.homedns.org>
In reply to#34093
Am 30.11.2012 12:11, schrieb andrea crotti:
> I wrote a script, refactored it and then introducing a bug as below:
>
> def record_things():
>      out.write("Hello world")

This is a function. Since "out" is not a local variable, it is looked up 
in the surrounding namespace at the time the function is called.


> if __name__ == '__main__':
>      with open('output', 'w') as out:
>          record_things()

This is not in a function, so binding variables affects the containing 
namespace. This includes binding the context manager to "out". Note that 
you could have moved the whole code into a function (e.g. one called 
main()) and then you would have gotten the expected failure.


> What my explanation might be is that the "out" is declared at module
> level somehow, but that's not really intuitive and looks wrong, and
> works both on Python 2.7 and 3.2..

Other than in C/C++/Java and others, indention doesn't introduce a new 
scope, but I understand your intuition. Even simpler, this is how my 
early Python code looked like, in the absence of the C ternary operator 
and the distinction between a variable declaration and an assignment:

  foo = None
  if some_condition:
      foo = 'bar'
  else:
      foo = 'baz'

More idiomatic would have been this:

  if some_condition:
      foo = 'bar'
  else:
      foo = 'baz'


Summary: I'd say that everything is fine. ;)

Uli

[toc] | [prev] | [next] | [standalone]


#34098

Fromandrea crotti <andrea.crotti.0@gmail.com>
Date2012-11-30 16:05 +0000
Message-ID<mailman.384.1354291543.29569.python-list@python.org>
In reply to#34097
Well I knew that this works fine, even if I feel a bit guilty to do
this, and better is:

foo = 'bar' if some_condition else 'baz'

Anyway for me the suprise is that something that is defined *later* at
the module scope is found in a function which is defined *earlier*.

[toc] | [prev] | [next] | [standalone]


#34099

FromChris Angelico <rosuav@gmail.com>
Date2012-12-01 03:08 +1100
Message-ID<mailman.385.1354291733.29569.python-list@python.org>
In reply to#34097
On Sat, Dec 1, 2012 at 3:05 AM, andrea crotti <andrea.crotti.0@gmail.com> wrote:
> Well I knew that this works fine, even if I feel a bit guilty to do
> this, and better is:
>
> foo = 'bar' if some_condition else 'baz'
>
> Anyway for me the suprise is that something that is defined *later* at
> the module scope is found in a function which is defined *earlier*.

It's assigned to earlier. It's no different from C code like this:

int foo;

void blah()
{
    /* do stuff with foo */
}

int main()
{
    foo = 1;
}


In Python, the "int foo;" is implicit, but the scope is the same.

ChrisA

[toc] | [prev] | [next] | [standalone]


#34113

FromDave Angel <d@davea.name>
Date2012-11-30 17:57 -0500
Message-ID<mailman.395.1354316296.29569.python-list@python.org>
In reply to#34097
On 11/30/2012 11:05 AM, andrea crotti wrote:
> Well I knew that this works fine, even if I feel a bit guilty to do
> this, and better is:
>
> foo = 'bar' if some_condition else 'baz'
>
> Anyway for me the suprise is that something that is defined *later* at
> the module scope is found in a function which is defined *earlier*.

It would have been nice if you had indicated in your original post just
*what* you considered "shocking" about the code sample.  The code was
valid, and we all had to guess what about it was puzzling you.  Like
most others, I first guessed you were confused about the definition
being in an if statement.  Then I thought you were confused by the with
statement, since it's not as obvious that "as" binds the name to the
object in the same way as assignment.

But I never would have guessed that you were confused about the order of
execution in a module.

The source code in a module is executed in order, including function
definitions defined at top level.  However, such a function definition's
execution creates a function object, and assigns a global name (usually)
to that object.  It does not "execute" the object.  When that function
is executed later, it then looks for global variables for stuff that's
not defined within its own scope.  So by the time the function
references the 'out' name, it's been successfully added to the global
namespace.



-- 

DaveA

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web