LEGB rule, totally confused ...

Discussion in 'Python' started by stef mientki, Aug 14, 2007.

  1. stef mientki

    stef mientki Guest

    hello,

    I've thought many times I finally understood the import / namespace rules,
    but again I'm totally lost :-(

    This is my library file

    # Module lib_test.py

    X = 1

    def Init():
    global X
    X = 3
    print 'Init', X

    def Run ():
    print X <=== UnboundLocalError: local variable
    'X' referenced before assignment
    X = X + 1
    print ' Run', X



    And this my main program in another file:

    import lib_test
    lib_test.Init()
    print lib_test.X

    lib_test.Run()
    print lib_test.X

    Why do I get the error ?
    Printing isn't assigning anything or am I missing something.
    Now if I remove "X = X + 1" I don't get an error ???
    Is this a problem of the traceback procedure or the IDE,
    or is Python not completely an interpreter, that reads line by line ???

    Please explain this to me.

    thanks,
    Stef Mientki
     
    stef mientki, Aug 14, 2007
    #1
    1. Advertising

  2. stef mientki wrote:

    > hello,
    >
    > I've thought many times I finally understood the import / namespace rules,
    > but again I'm totally lost :-(
    >
    > This is my library file
    >
    > # Module lib_test.py
    >
    > X = 1
    >
    > def Init():
    > global X
    > X = 3
    > print 'Init', X
    >
    > def Run ():
    > print X <=== UnboundLocalError: local variable
    > 'X' referenced before assignment
    > X = X + 1
    > print ' Run', X
    >
    >
    >
    > And this my main program in another file:
    >
    > import lib_test
    > lib_test.Init()
    > print lib_test.X
    >
    > lib_test.Run()
    > print lib_test.X
    >
    > Why do I get the error ?
    > Printing isn't assigning anything or am I missing something.
    > Now if I remove "X = X + 1" I don't get an error ???
    > Is this a problem of the traceback procedure or the IDE,
    > or is Python not completely an interpreter, that reads line by line ???
    >
    > Please explain this to me.


    This are the scoping-rules of python. A variable name on the left side of an
    name-binding/assignment operator (including augmented assignments, vulgo:
    += and brothers) will make the variable name a function-local.

    So

    x = 10
    def foo():
    print x
    x = 100

    makes x a local variable to foo, which of course can't be accessed in

    print x

    Diez
     
    Diez B. Roggisch, Aug 14, 2007
    #2
    1. Advertising

  3. stef mientki a écrit :
    > hello,
    >
    > I've thought many times I finally understood the import / namespace rules,
    > but again I'm totally lost :-(
    >
    > This is my library file
    >
    > # Module lib_test.py
    >
    > X = 1
    >
    > def Init():
    > global X
    > X = 3
    > print 'Init', X
    >
    > def Run ():
    > print X <=== UnboundLocalError: local variable
    > 'X' referenced before assignment
    > X = X + 1
    > print ' Run', X
    >
    >
    >
    > And this my main program in another file:
    >
    > import lib_test
    > lib_test.Init()
    > print lib_test.X
    >
    > lib_test.Run()
    > print lib_test.X
    >
    > Why do I get the error ?
    > Printing isn't assigning anything or am I missing something.


    If you use a global to *modify* it, you MUST declare "global X", either
    Python consider using a local.
    So for your error: at compile time, in Run(), it see that it must use a
    local X (because you set it) and generate ad-hoc bytecode, but when
    running X is not defined locally, so the error.

    > Now if I remove "X = X + 1" I don't get an error ???


    If you remove the "X =..." statement, then the compiler dont know
    a-priori if its local or global, so it search X in both namespaces.

    > Is this a problem of the traceback procedure or the IDE,
    > or is Python not completely an interpreter, that reads line by line ???


    Its compiled to buyte-code then interpreted from the byte-code.

    >
    > Please explain this to me.
    >
    > thanks,
    > Stef Mientki


    A+

    Laurent.
     
    Laurent Pointal, Aug 14, 2007
    #3
  4. stef mientki

    Neil Cerutti Guest

    On 2007-08-14, stef mientki <> wrote:
    > I've thought many times I finally understood the import /
    > namespace rules, but again I'm totally lost :-(
    >
    > This is my library file
    >
    > # Module lib_test.py
    >
    > X = 1
    >
    > def Init():
    > global X
    > X = 3
    > print 'Init', X
    >
    > def Run ():
    > print X <=== UnboundLocalError: local variable
    > 'X' referenced before assignment
    > X = X + 1
    > print ' Run', X


    From _Python Language Reference Manual_ see: '4.1 Naming and
    Binding' and '6.13 The global statement'.

    If a name is bound [assigned] in a block, it is a local
    variable of that block.

    ...

    The global statement is a declaration which holds for the
    entire current code block. It means that the listed identifiers
    are to be interpreted as globals. It would be impossible to
    assign to a global variable without global, although free
    variables may refer to globals without being declared global.

    Since your Init and Run functions both assign (bind) a value to
    X, X is assumed to be a local variable unless you say otherwise
    with a global statement.

    Note that the global statement in Init applies only in Init's
    code block. Run must have it's own 'global X' statement, if
    applicable.

    --
    Neil Cerutti
     
    Neil Cerutti, Aug 14, 2007
    #4
  5. stef mientki <> wrote:
    > def Run ():
    > print X <=== UnboundLocalError: local variable
    > 'X' referenced before assignment
    > X = X + 1
    >
    >Why do I get the error ?
    >Printing isn't assigning anything or am I missing something.
    >Now if I remove "X = X + 1" I don't get an error ???


    Several people have already explained the scoping rules acting
    here, but let's just look at how that error message is telling
    you everything you need to know to fix the problem.

    "local variable 'X' referenced before assignment"

    "local variable 'X'" immediately tells you that the 'X' in
    question is not your global 'X'.

    "referenced before assignment": well, 'print X' is surely a
    reference to 'X', and 'X = X + 1' is an assignment to it,
    and 'print X' appears before 'X = X + 1'. That this is the
    key you have confirmed experimentally.

    The question to ask here is "Why does Python think 'X' is
    local?" Everything else is answered by the error message.

    --
    \S -- -- http://www.chaos.org.uk/~sion/
    "Frankly I have no feelings towards penguins one way or the other"
    -- Arthur C. Clarke
    her nu becomeþ se bera eadward ofdun hlæddre heafdes bæce bump bump bump
     
    Sion Arrowsmith, Aug 14, 2007
    #5
  6. stef mientki

    stef mientki Guest

    Sion Arrowsmith wrote:
    > stef mientki <> wrote:
    >
    >> def Run ():
    >> print X <=== UnboundLocalError: local variable
    >> 'X' referenced before assignment
    >> X = X + 1
    >>
    >> Why do I get the error ?
    >> Printing isn't assigning anything or am I missing something.
    >> Now if I remove "X = X + 1" I don't get an error ???
    >>

    >
    > Several people have already explained the scoping rules acting
    > here, but let's just look at how that error message is telling
    > you everything you need to know to fix the problem.
    >
    > "local variable 'X' referenced before assignment"
    >
    > "local variable 'X'" immediately tells you that the 'X' in
    > question is not your global 'X'.
    >
    > "referenced before assignment": well, 'print X' is surely a
    > reference to 'X', and 'X = X + 1' is an assignment to it,
    > and 'print X' appears before 'X = X + 1'. That this is the
    > key you have confirmed experimentally.
    >
    > The question to ask here is "Why does Python think 'X' is
    > local?" Everything else is answered by the error message.
    >
    >

    Thanks guys, I beginning to see the light again,
    and if X is mutual the story is completely different,
    I still have to get used to these differences.

    cheers,
    Stef Mientki
     
    stef mientki, Aug 14, 2007
    #6
  7. > Thanks guys, I beginning to see the light again,
    > and if X is mutual the story is completely different,
    > I still have to get used to these differences.


    <nitpicking-for-the-sake-of-the-casual-reader>

    That's supposed to be "mutable", not "mutual".

    </nitpicking-for-the-sake-of-the-casual-reader>

    Diez
     
    Diez B. Roggisch, Aug 15, 2007
    #7
    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. James Gregory

    Size of a struct - totally confused

    James Gregory, Jan 30, 2004, in forum: C++
    Replies:
    11
    Views:
    3,200
    EventHelix.com
    Jan 31, 2004
  2. Replies:
    0
    Views:
    1,370
  3. Lloyd Sheen

    Totally confused

    Lloyd Sheen, Mar 6, 2008, in forum: ASP .Net
    Replies:
    5
    Views:
    354
    Lloyd Sheen
    Mar 28, 2008
  4. Giampaolo Rodola'
    Replies:
    17
    Views:
    1,070
    John Machin
    Jan 18, 2009
  5. eBob.com

    Newbie Totally Confused

    eBob.com, Feb 3, 2008, in forum: Javascript
    Replies:
    2
    Views:
    97
Loading...

Share This Page