amazing scope?

Discussion in 'Python' started by andrea crotti, Nov 30, 2012.

  1. 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..
     
    andrea crotti, Nov 30, 2012
    #1
    1. Advertising

  2. 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
     
    Ulrich Eckhardt, Nov 30, 2012
    #2
    1. Advertising

  3. On Sat, Dec 1, 2012 at 3: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'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
     
    Chris Angelico, Nov 30, 2012
    #3
  4. andrea crotti

    Dave Angel Guest

    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
     
    Dave Angel, Nov 30, 2012
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Paul Opal
    Replies:
    12
    Views:
    975
    Paul Opal
    Oct 11, 2004
  2. ann
    Replies:
    13
    Views:
    682
    Patricia Shanahan
    Sep 13, 2005
  3. Mike Painter
    Replies:
    0
    Views:
    438
    Mike Painter
    Nov 2, 2006
  4. andrea crotti

    Re: amazing scope?

    andrea crotti, Nov 30, 2012, in forum: Python
    Replies:
    0
    Views:
    143
    andrea crotti
    Nov 30, 2012
  5. Prasad, Ramit

    RE: amazing scope?

    Prasad, Ramit, Nov 30, 2012, in forum: Python
    Replies:
    0
    Views:
    141
    Prasad, Ramit
    Nov 30, 2012
Loading...

Share This Page