Problem with global variables

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Ed Jensen

    #1

    Problem with global variables

    I'm having a vexing problem with global variables in Python. Please
    consider the following Python code:

    #! /usr/bin/env python

    def tiny():
    bar = []
    for tmp in foo:
    bar.append(tmp)
    foo = bar

    if __name__ == "__main__":
    foo = ['hello', 'world']
    tiny()

    When I try to run this, I get:

    Traceback (most recent call last):
    File "./xtalk.py", line 11, in ?
    tiny()
    File "./xtalk.py", line 5, in tiny
    for tmp in foo:
    UnboundLocalErr or: local variable 'foo' referenced before assignment

    For some reason, Python can't see the global variable "foo" in the
    function tiny(). Why is that?

    If I change the code to this:

    #! /usr/bin/env python

    def tiny():
    for tmp in foo:
    print tmp

    if __name__ == "__main__":
    foo = ['hello', 'world']
    tiny()

    I get this:

    hello
    world

    All of a sudden, tiny() can see the global variable "foo". Very
    confusing! Why is it that tiny() sometimes can, and sometimes can't,
    see the global variable "foo"?

    If anyone can enlighten me about what's going on with Python and
    global variables, I would appreciate it!
  • hg

    #2
    Re: Problem with global variables

    Ed Jensen wrote:
    #! /usr/bin/env python
    >
    def tiny():
    bar = []
    for tmp in foo:
    bar.append(tmp)
    foo = bar
    >
    if __name__ == "__main__":
    foo = ['hello', 'world']
    tiny()

    Like this ?

    #! /usr/bin/env python

    def tiny():
        bar = []
    gobal foo
        for tmp in foo:
            bar.append(tmp)
        foo = bar

    if __name__ == "__main__":
        foo = ['hello', 'world']
        tiny()


    hg

    Comment

    • Laurent Pointal

      #3
      Re: Problem with global variables

      Ed Jensen a écrit :
      I'm having a vexing problem with global variables in Python. Please
      consider the following Python code:
      >
      #! /usr/bin/env python
      >
      def tiny():
      bar = []
      for tmp in foo:
      bar.append(tmp)
      foo = bar
      >
      if __name__ == "__main__":
      foo = ['hello', 'world']
      tiny()
      >
      When I try to run this, I get:
      >
      Traceback (most recent call last):
      File "./xtalk.py", line 11, in ?
      tiny()
      File "./xtalk.py", line 5, in tiny
      for tmp in foo:
      UnboundLocalErr or: local variable 'foo' referenced before assignment
      >
      For some reason, Python can't see the global variable "foo" in the
      function tiny(). Why is that?
      >
      If I change the code to this:
      >
      #! /usr/bin/env python
      >
      def tiny():
      for tmp in foo:
      print tmp
      >
      if __name__ == "__main__":
      foo = ['hello', 'world']
      tiny()
      >
      I get this:
      >
      hello
      world
      >
      All of a sudden, tiny() can see the global variable "foo". Very
      confusing! Why is it that tiny() sometimes can, and sometimes can't,
      see the global variable "foo"?
      >
      If anyone can enlighten me about what's going on with Python and
      global variables, I would appreciate it!
      To complete hg reply, Python compile your tiny function which contains a
      foo assignment. As foo is not defined "global", it is considered to be
      local. So the error when you tries to iterate throught foo before
      assigning it. And so the solution to add "global foo" before using it.

      A+

      Laurent.

      Comment

      • Bjoern Schliessmann

        #4
        Re: Problem with global variables

        Laurent Pointal wrote:
        And so the solution to add "global foo" before using it.
        Didn't you read his final question?

        | All of a sudden, tiny() can see the global variable "foo". Very
        | confusing! Why is it that tiny() sometimes can, and sometimes
        | can't, see the global variable "foo"?

        I have no explanation for this, but I'm interested in one, too.

        Regards,


        Björn

        --
        BOFH excuse #422:

        Someone else stole your IP address, call the Internet detectives!

        Comment

        • Steve Holden

          #5
          Re: Problem with global variables

          Bjoern Schliessmann wrote:
          Laurent Pointal wrote:
          >
          >And so the solution to add "global foo" before using it.
          >
          Didn't you read his final question?
          >
          | All of a sudden, tiny() can see the global variable "foo". Very
          | confusing! Why is it that tiny() sometimes can, and sometimes
          | can't, see the global variable "foo"?
          >
          I have no explanation for this, but I'm interested in one, too.
          >
          It doesn't happen "all of a sudden", it happens when the assignment to
          foo is removed from the function definition. The interpreter therefore
          no longer regards foo as a local variable.

          regards
          Steve
          --
          Steve Holden +44 150 684 7255 +1 800 494 3119
          Holden Web LLC/Ltd http://www.holdenweb.com
          Skype: holdenweb http://del.icio.us/steve.holden
          Recent Ramblings http://holdenweb.blogspot.com

          Comment

          • Roel Schroeven

            #6
            Re: Problem with global variables

            Bjoern Schliessmann schreef:
            Laurent Pointal wrote:
            >
            >And so the solution to add "global foo" before using it.
            >
            Didn't you read his final question?
            >
            | All of a sudden, tiny() can see the global variable "foo". Very
            | confusing! Why is it that tiny() sometimes can, and sometimes
            | can't, see the global variable "foo"?
            >
            I have no explanation for this, but I'm interested in one, too.
            Within functions Python can read from global variables, even without a
            'global' statement. Complications only arise when you try to write to
            it: in that case Python assumes it is a local variable instead of a global.

            It surprised me a bit when I first found out about this: I would have
            thought that Python would threat it as a local throughout the function
            until the function assigns something to it. That's not what happens: if
            the function assigns to it, *all* mentions of the variable are
            considered local.

            --
            If I have been able to see further, it was only because I stood
            on the shoulders of giants. -- Isaac Newton

            Roel Schroeven

            Comment

            • irstas@gmail.com

              #7
              Re: Problem with global variables

              On Apr 2, 5:29 pm, Bjoern Schliessmann <usenet-
              mail-0306.20.chr0n.. .@spamgourmet.c omwrote:
              Laurent Pointal wrote:
              And so the solution to add "global foo" before using it.
              >
              Didn't you read his final question?
              >
              | All of a sudden, tiny() can see the global variable "foo". Very
              | confusing! Why is it that tiny() sometimes can, and sometimes
              | can't, see the global variable "foo"?
              >
              I have no explanation for this, but I'm interested in one, too.
              >
              Regards,
              >
              Björn
              Laurent Pointal did explain this. "foo" is considered to be a local
              variable (scope limited to the function) if it's being assigned to in
              a function and there's no "global foo" statement. So even the "foo"
              before the actual assignment will refer to the local variable. But the
              local variable hasn't been assigned yet at that point and an exception
              is thrown. Yes, one could have a perfectly working function, then add
              an innocent-looking assignment statement at the very end of the
              function, and suddenly you'd get an exception thrown at the beginning
              of the function where that variable is used - Far away from the place
              where the modification was made.

              Why does it work like this? Couldn't it be somehow more uniform or
              less surprising?

              Well, if one had to define "global foo" even when one were to just
              read the variable foo, that'd be a pain in the ass. You'd have to use
              "global math" to use math module in a function and "global
              anotherFunction " to call anotherFunction , and so on. There's plenty of
              stuff in the global scope that you don't normally assign to.

              Another option would be to scrap "global" keyword and let "foo = bar"
              do an assignment to the global variable if a global variable named
              "foo" exists, but create (or assign) to a function local variable if
              it doesn't exist. That'd work but programming would be horrible. Now
              you'd have to know all the symbols that exist at the global scope,
              because if you accidentally accessed a global variable instead of
              local, your function would probably have undesirable side-effects.

              Now, name clashes could be solved with a naming convention (which
              could be enforced at the language level). It could be possible that
              all accesses to global scope would have to be prefixed by some symbol
              like $. E.g. "$foo = 4; foo = 6" where former assigns to global foo,
              latter to local foo. That's one option that might work and be somewhat
              readable.. But not a good tradeoff IMO, considering how rarely global
              assignment is needed and how often global variables are read.

              A remaining option is to use different operator for assignment and
              initialization. So you'd have to do e.g. "a := 4; a = 7". I'm not sure
              Pythonistas would prefer this either, although many other languages
              choose this route (through lets or declarations typically).

              Comment

              • Ed Jensen

                #8
                Re: Problem with global variables

                Ed Jensen <ejensen@visi.c omwrote:
                I'm having a vexing problem with global variables in Python.
                <SNIP>

                Thanks to everyone who replied. The peculiar way Python handles
                global variables in functions now makes sense to me.

                Comment

                • Laurent Pointal

                  #9
                  Re: Problem with global variables

                  Bjoern Schliessmann wrote:
                  Laurent Pointal wrote:
                  >
                  >And so the solution to add "global foo" before using it.
                  >
                  Didn't you read his final question?
                  Yes, and i replies: "which contains a foo assignment. As foo is not
                  defined "global", it is considered to be local. "

                  Maybe my explanation was not clear enough with variable foo to be considered
                  local because there is an *assignment* to foo.

                  A+

                  Laurent.


                  Comment

                  • Bjoern Schliessmann

                    #10
                    Re: Problem with global variables

                    Laurent Pointal wrote:
                    Yes, and i replies: "which contains a foo assignment. As foo is
                    not defined "global", it is considered to be local. "
                    >
                    Maybe my explanation was not clear enough with variable foo to be
                    considered local because there is an *assignment* to foo.
                    Yep, thanks for the clarification. After four replies and despite
                    weird conjugations, I've definitely got it now ... ;)

                    Regards,


                    Björn

                    --
                    BOFH excuse #113:

                    Root nameservers are out of sync

                    Comment

                    Working...