Tkinter WEIRDNESS or Python WEIRDNESS?

Discussion in 'Python' started by steve, Mar 12, 2005.

  1. steve

    steve Guest

    In a nutshell, my problem is that I am getting this runtime error, and
    I have no clue why. Please bear in mind its my first python program:

    "localvariable 'currentAbility' referenced before asignment"

    in this function which is a callback for a button:

    def nextThing():
    if lookingAtAbilities == 1:
    currentAbility = currentAbility + 1
    if currentAbility not in ability:
    currentAbility = 0
    clearScreen()
    ability[currentAbility].draw(currentAbility)
    drawMainButtons()
    else:
    currentCreature = currentCreature + 1
    if currentCreature not in creature:
    currentCreature = 0
    clearScreen()
    creature[currentCreature].draw(currentCreature)
    drawMainButtons()

    now the thing is, both lookingAtAbilities and currentAbility are
    global variables. In fact, they are both assigned at the same part of
    the program, right at the start. yet lookingAtAbilities is
    recognized as a global by this function, and currentAbility is not,
    generating this runtime error.

    here is the structure of the code:

    ----------------------------------------
    import string
    import types
    from Tkinter import *

    # globals
    lookingAtAbilities = 1
    currentAbility = 2

    (snip: some class and function definitions)

    def nextThing():
    if lookingAtAbilities == 1:
    currentAbility = currentAbility + 1
    if currentAbility not in ability:
    currentAbility = 0
    clearScreen()
    ability[currentAbility].draw(currentAbility)
    drawMainButtons()
    else:
    currentCreature = currentCreature + 1
    if currentCreature not in creature:
    currentCreature = 0
    clearScreen()
    creature[currentCreature].draw(currentCreature)
    drawMainButtons()

    def drawMainButtons():
    back = Button(win, text="prev", command=prevThing)
    back.grid(row=20, column=0)
    next = Button(win, text="next", command=nextThing)
    next.grid(row=20, column=1)

    # START OF EXECUTION #

    masterWin = Tk()
    win = Frame(masterWin)
    win.grid()

    drawMainButtons()
    masterWin.mainloop()
    ------------------------------------------

    This has me flumoxed

    thanks if you can work it out,

    Steve
    steve, Mar 12, 2005
    #1
    1. Advertising

  2. steve said unto the world upon 2005-03-12 00:06:
    > In a nutshell, my problem is that I am getting this runtime error, and
    > I have no clue why. Please bear in mind its my first python program:
    >
    > "localvariable 'currentAbility' referenced before asignment"
    >
    > in this function which is a callback for a button:
    >
    > def nextThing():
    > if lookingAtAbilities == 1:
    > currentAbility = currentAbility + 1
    > if currentAbility not in ability:
    > currentAbility = 0
    > clearScreen()
    > ability[currentAbility].draw(currentAbility)
    > drawMainButtons()
    > else:
    > currentCreature = currentCreature + 1
    > if currentCreature not in creature:
    > currentCreature = 0
    > clearScreen()
    > creature[currentCreature].draw(currentCreature)
    > drawMainButtons()
    >
    > now the thing is, both lookingAtAbilities and currentAbility are
    > global variables. In fact, they are both assigned at the same part of
    > the program, right at the start. yet lookingAtAbilities is
    > recognized as a global by this function, and currentAbility is not,
    > generating this runtime error.
    >
    > here is the structure of the code:


    <SNIP>

    > This has me flumoxed
    >
    > thanks if you can work it out,
    >
    > Steve


    Hi Steve,

    While both lookingAtAbilities and currentAbility are names in the
    global namespace, nextThing() doesn't know that ;-).

    The first mention of if lookingAtAbilities in nextThing() is:
    .. if lookingAtAbilities == 1:
    This is a reference to the name, so the interpreter fetches
    lookingAtAbilities value from the first namespace in which it finds
    such a name. (The global namespace.)

    By contrast, the first mention of currentAbility is:
    .. currentAbility = currentAbility + 1
    So, the interpreter `creates' (I am a bit fuzzy on the terminology and
    not an accomplished Pythoner) a name in the function local namespace
    and then looks to see what value to point the name at. When it sees it
    should have currentAbility (a name without a value as yet) point to
    currentAbility + 1, it barfs.

    One way to fix it, is to put `global currentAbility' at the top of
    your function definition. (Many frown on globals as it messes with the
    namespaces, and gives bad mojo.)

    Another would be to pass currentAbility in to your function as an
    argument.

    Yet another (and probably the best) would be to wrap your code into a
    class and then reference self.currentAbility.

    Still another (but one not so good for clarity or beauty) would be to
    put a line like:
    temp = currentAbility # temp a name to reference global scope name
    # before assignment to follow.

    Perhaps more expert voices will chime in and say better things. :)

    HTH,

    Brian vdB
    Brian van den Broek, Mar 12, 2005
    #2
    1. Advertising

  3. steve wrote:
    > In a nutshell, my problem is that I am getting this runtime error, and
    > I have no clue why. Please bear in mind its my first python program:
    >
    > "localvariable 'currentAbility' referenced before asignment"
    >


    If you're assigning an object to a name, it will be assigned to that
    name in local namespace. So, in your case, you are doing augmented
    assignment on a local name that does not yet exist (hence the error
    message). You need to tell the interpreter that what you want is assign
    to that name in global namespace. You can do this by using the 'global'
    statement, as in:

    >>> my_global = 1
    >>> def some_func():

    .... global my_global
    .... my_global += 1
    >> some_func()
    >> my_global

    2


    --

    Vincent Wehren
    Vincent Wehren, Mar 12, 2005
    #3
  4. steve

    steve Guest

    Brian van den Broek <> wrote in message news:<>...
    > steve said unto the world upon 2005-03-12 00:06:
    > > In a nutshell, my problem is that I am getting this runtime error, and
    > > I have no clue why. Please bear in mind its my first python program:
    > >
    > > "localvariable 'currentAbility' referenced before asignment"
    > >
    > > in this function which is a callback for a button:
    > > now the thing is, both lookingAtAbilities and currentAbility are
    > > global variables. In fact, they are both assigned at the same part of
    > > the program, right at the start. yet lookingAtAbilities is
    > > recognized as a global by this function, and currentAbility is not,
    > > generating this runtime error.
    > >
    > > here is the structure of the code:

    >
    > <SNIP>
    >
    > > This has me flumoxed
    > >
    > > thanks if you can work it out,
    > >
    > > Steve

    >
    > Hi Steve,
    >
    > While both lookingAtAbilities and currentAbility are names in the
    > global namespace, nextThing() doesn't know that ;-).
    >
    > The first mention of if lookingAtAbilities in nextThing() is:
    > . if lookingAtAbilities == 1:
    > This is a reference to the name, so the interpreter fetches
    > lookingAtAbilities value from the first namespace in which it finds
    > such a name. (The global namespace.)
    >
    > By contrast, the first mention of currentAbility is:
    > . currentAbility = currentAbility + 1
    > So, the interpreter `creates' (I am a bit fuzzy on the terminology and
    > not an accomplished Pythoner) a name in the function local namespace
    > and then looks to see what value to point the name at. When it sees it
    > should have currentAbility (a name without a value as yet) point to
    > currentAbility + 1, it barfs.


    Thanks to both of you, this has fixed the problem. I wouldnt have
    guessed that in a million years.

    But it leads me to ask what is the use of something being in the
    gloabl namespace if it cant be accessed globally?

    I also find the continual need for objects to reference their own
    variables by prefixing 'self' annoying. It seems that Python is the
    reverse of my assuptions. whats the rationale for that?

    > One way to fix it, is to put `global currentAbility' at the top of
    > your function definition. (Many frown on globals as it messes with the
    > namespaces, and gives bad mojo.)
    >
    > Another would be to pass currentAbility in to your function as an
    > argument.
    >
    > Yet another (and probably the best) would be to wrap your code into a
    > class and then reference self.currentAbility.
    >
    > Still another (but one not so good for clarity or beauty) would be to
    > put a line like:
    > temp = currentAbility # temp a name to reference global scope name
    > # before assignment to follow.
    >
    > Perhaps more expert voices will chime in and say better things. :)
    >
    > HTH,
    >
    > Brian vdB
    steve, Mar 12, 2005
    #4
  5. steve said unto the world upon 2005-03-12 18:46:
    > Brian van den Broek <> wrote in message news:<>...
    >
    >>steve said unto the world upon 2005-03-12 00:06:
    >>
    >>>In a nutshell, my problem is that I am getting this runtime error, and
    >>>I have no clue why. Please bear in mind its my first python program:
    >>>
    >>>"localvariable 'currentAbility' referenced before asignment"
    >>>
    >>>in this function which is a callback for a button:
    >>>now the thing is, both lookingAtAbilities and currentAbility are
    >>>global variables. In fact, they are both assigned at the same part of
    >>>the program, right at the start. yet lookingAtAbilities is
    >>>recognized as a global by this function, and currentAbility is not,
    >>>generating this runtime error.
    >>>
    >>>here is the structure of the code:

    >>
    >><SNIP>
    >>
    >>>This has me flumoxed
    >>>
    >>>thanks if you can work it out,
    >>>
    >>>Steve

    >>
    >>Hi Steve,
    >>
    >>While both lookingAtAbilities and currentAbility are names in the
    >>global namespace, nextThing() doesn't know that ;-).
    >>
    >>The first mention of if lookingAtAbilities in nextThing() is:
    >>. if lookingAtAbilities == 1:
    >>This is a reference to the name, so the interpreter fetches
    >>lookingAtAbilities value from the first namespace in which it finds
    >>such a name. (The global namespace.)
    >>
    >>By contrast, the first mention of currentAbility is:
    >>. currentAbility = currentAbility + 1
    >>So, the interpreter `creates' (I am a bit fuzzy on the terminology and
    >>not an accomplished Pythoner) a name in the function local namespace
    >>and then looks to see what value to point the name at. When it sees it
    >>should have currentAbility (a name without a value as yet) point to
    >>currentAbility + 1, it barfs.

    >
    >
    > Thanks to both of you, this has fixed the problem. I wouldnt have
    > guessed that in a million years.


    Hi Steve,

    you're welcome. I'm just glad I've finally understood enough to offer
    helpful answers :) (Though note the self-correction at the end of
    this post.)

    > But it leads me to ask what is the use of something being in the
    > gloabl namespace if it cant be accessed globally?


    I think that your question shows there is some residual confusion.
    Things in the global namespace can be accessed just fine. The issue
    with your code was that, while you had a global name currentAbility in
    the global namespace sitting around just waiting to be accessed, your
    first use of that name in your function was to assign it.

    Assignments are by default to names in the local namespace. If you'd
    put the global line in, you'd have told the interpreter to make the
    assignment in the global scope. Without this, your function told the
    interpreter to create a new name in the local namespace and make it
    refer to the object to the right of the '=' which, in your case, was
    not well-defined.

    There is a certain logic to making assignments be assignments within
    the active namepace by default. There may be a deeper reason, but I
    don't know it. (To anyone more expert: if there is, I'd love to learn it).

    > I also find the continual need for objects to reference their own
    > variables by prefixing 'self' annoying. It seems that Python is the
    > reverse of my assuptions. whats the rationale for that?


    The self prefix is just a conventional way of indicating a reference
    to the current class instance. I hated it at first too. Python is my
    first language since some BASIC long ago and the selfs were one reason
    I steered clear of OOP at first. But, a few evenings of programming
    with classes (a recent thing for me) and the aversion went away. So:
    give it a bit of time; you might get so you aren't bothered by them.

    I should also note there was some residual confusion in what I wrote, too:

    >>Still another (but one not so good for clarity or beauty) would be to
    >>put a line like:
    >>temp = currentAbility # temp a name to reference global scope name
    >> # before assignment to follow.


    This won't work. Witness:

    >>> a = 42
    >>> def my_mistake():

    .... temp = a
    .... a = a * 2
    ....
    >>> my_mistake()

    Traceback (most recent call last):
    File "<interactive input>", line 1, in ?
    File "<interactive input>", line 2, in my_mistake
    UnboundLocalError: local variable 'a' referenced before assignment
    >>>


    Sorry 'bout that :-[

    Best,

    Brian vdB
    Brian van den Broek, Mar 13, 2005
    #5
    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. Jeff Epler
    Replies:
    0
    Views:
    497
    Jeff Epler
    Aug 20, 2004
  2. Jeff Epler
    Replies:
    0
    Views:
    444
    Jeff Epler
    Aug 23, 2004
  3. phil

    Tkinter weirdness item count

    phil, Apr 29, 2005, in forum: Python
    Replies:
    3
    Views:
    353
    pavel.kosina
    May 29, 2005
  4. phil

    Tkinter weirdness item count

    phil, May 1, 2005, in forum: Python
    Replies:
    0
    Views:
    305
  5. Pierre Dagenais
    Replies:
    0
    Views:
    298
    Pierre Dagenais
    Aug 3, 2008
Loading...

Share This Page