updating local()

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

    #1

    updating local()

    Hi,

    I heard time and again that you are not _supposed_ to update the
    locals dictionary.

    Can anyone tell me why, if the following code works, I should not do
    this?

    #
    # Extending Local namespace
    #

    def fun(a=1,b=2,**a rgs):

    print 'locals:',local s()
    locals().update (args)
    print locals()

    e = {'s':3,'e':4}
    fun(k=10,v=32,* *e)


    thanks,

    Flávio

  • Steve Holden

    #2
    Re: updating local()

    Flavio wrote:[color=blue]
    > Hi,
    >
    > I heard time and again that you are not _supposed_ to update the
    > locals dictionary.
    >
    > Can anyone tell me why, if the following code works, I should not do
    > this?
    >
    > #
    > # Extending Local namespace
    > #
    >
    > def fun(a=1,b=2,**a rgs):
    >
    > print 'locals:',local s()
    > locals().update (args)
    > print locals()
    >
    > e = {'s':3,'e':4}
    > fun(k=10,v=32,* *e)
    >[/color]
    Because it depends on the current implementation and isn't guaranteeed
    to work in the future.

    regards
    Steve
    --
    Steve Holden +44 150 684 7255 +1 800 494 3119
    Holden Web LLC www.holdenweb.com
    PyCon TX 2006 www.python.org/pycon/

    Comment

    • Sybren Stuvel

      #3
      Re: updating local()

      Flavio enlightened us with:[color=blue]
      > Can anyone tell me why, if the following code works, I should not do
      > this?
      >
      > def fun(a=1,b=2,**a rgs):
      >
      > print 'locals:',local s()
      > locals().update (args)
      > print locals()[/color]

      Because it's very, very, very insecure. What would happen if someone
      found a way to call that function? It could replace any name in the
      locals dictionary, including functions from __builtins__. In other
      words: probably the whole program could be taken over by other code by
      just one call to that function.

      Sybren
      --
      The problem with the world is stupidity. Not saying there should be a
      capital punishment for stupidity, but why don't we just take the
      safety labels off of everything and let the problem solve itself?
      Frank Zappa

      Comment

      • Duncan Booth

        #4
        Re: updating local()

        Flavio wrote:[color=blue]
        > Can anyone tell me why, if the following code works, I should not do
        > this?
        >
        > #
        > # Extending Local namespace
        > #
        >
        > def fun(a=1,b=2,**a rgs):
        >
        > print 'locals:',local s()
        > locals().update (args)
        > print locals()
        >
        > e = {'s':3,'e':4}
        > fun(k=10,v=32,* *e)
        >[/color]
        Because if all you want is to update a dictionary you might as well use
        another dictionary which isn't locals(). If what you want is to update the
        local variables, that won't work:
        [color=blue][color=green][color=darkred]
        >>> def fun(a=1,b=2,**a rgs):[/color][/color][/color]
        s = 1
        print 'locals:',local s()
        locals().update (args)
        print locals()
        print s, e

        [color=blue][color=green][color=darkred]
        >>> e = {'s':3,'e':4}
        >>> fun(k=10,v=32,* *e)[/color][/color][/color]
        locals: {'a': 1, 's': 1, 'args': {'s': 3, 'e': 4, 'k': 10, 'v': 32}, 'b':
        2}
        {'a': 1, 'b': 2, 'e': 4, 'k': 10, 'args': {'s': 3, 'e': 4, 'k': 10, 'v':
        32}, 's': 1, 'v': 32}
        1 {'s': 3, 'e': 4}[color=blue][color=green][color=darkred]
        >>>[/color][/color][/color]

        Note that k, v, and e are added to the locals dictionary, but real local
        variables such as 's' are not updated. Also you cannot access k, v, and e
        as local variables within the function, if you try you get the global
        variables (if they exist).

        Also, this behaviour is undefined. Different versions of Python will behave
        differently, and even minor code changes can change the behaviour. With
        this version, 's' still doesn't update, but we can now access the 'e' value
        as a variable:
        [color=blue][color=green][color=darkred]
        >>> def fun(a=1,b=2,**a rgs):[/color][/color][/color]
        s = 1
        print 'locals:',local s()
        locals().update (args)
        print locals()
        exec "print 'hi'"
        print s,e

        [color=blue][color=green][color=darkred]
        >>> fun(k=10,v=32,* *e)[/color][/color][/color]
        locals: {'a': 1, 's': 1, 'args': {'s': 3, 'e': 4, 'k': 10, 'v': 32}, 'b':
        2}
        {'a': 1, 'b': 2, 'e': 4, 'k': 10, 'args': {'s': 3, 'e': 4, 'k': 10, 'v':
        32}, 's': 1, 'v': 32}
        hi
        1 4[color=blue][color=green][color=darkred]
        >>>[/color][/color][/color]

        Short answer: don't even think of trying to update locals().

        Comment

        • Fredrik Lundh

          #5
          Re: updating local()

          "Flavio" <fccoelho@gmail .com> wrote:
          [color=blue]
          > Can anyone tell me why, if the following code works, I should not do
          > this?[/color]

          because it doesn't work:

          #
          # Extending Local namespace, now with Local namespace
          #

          def fun(a=1,b=2,**a rgs):
          k="K"
          v="V"
          print 'locals:',local s()
          locals().update (args)
          print locals()
          print k
          print v

          e = {'s':3,'e':4}
          fun(k=10,v=32,* *e)


          </F>



          Comment

          • jepler@unpythonic.net

            #6
            Re: updating local()

            I'm surprised you found any example of 'locals().updat e' that worked.
            Here's one that doesn't work:
            def f(y):
            locals().update ({'x': y})
            return x

            print f(3) # prints 3?

            Jeff

            -----BEGIN PGP SIGNATURE-----
            Version: GnuPG v1.4.1 (GNU/Linux)

            iD8DBQFDRBXeJd0 1MZaTXX0RAru9AK CLn7jtxwCFBIn6+ ztalyhoN1vT9wCf R6yZ
            1HxA4j8rhl/RlsF4mDmPlI8=
            =rjtz
            -----END PGP SIGNATURE-----

            Comment

            • Sybren Stuvel

              #7
              Re: updating local()

              Jp Calderone enlightened us with:[color=blue]
              > If I can call functions in your process space, I've already taken
              > over your whole program.[/color]

              That's true for standalone programs, but not for things like web
              applications, RPC calls etc.

              Sybren
              --
              The problem with the world is stupidity. Not saying there should be a
              capital punishment for stupidity, but why don't we just take the
              safety labels off of everything and let the problem solve itself?
              Frank Zappa

              Comment

              • Flavio

                #8
                Re: updating local()

                Ok,

                I got it!

                Its vey insecure, and it is not guaranteed to work. Fine.

                Now what would you do if you wanted to pass a lot of variables (like a
                thousand) to a function and did not wanted the declare them in the
                function header?

                Flávio

                Comment

                • Richard Brodie

                  #9
                  Re: updating local()


                  "Flavio" <fccoelho@gmail .com> wrote in message
                  news:1128603314 .197733.119160@ g47g2000cwa.goo glegroups.com.. .
                  [color=blue]
                  > Now what would you do if you wanted to pass a lot of variables (like a
                  > thousand) to a function and did not wanted the declare them in the
                  > function header?[/color]

                  I'd lie down until I felt better.


                  Comment

                  • Simon Brunning

                    #10
                    Re: updating local()

                    On 6 Oct 2005 05:55:14 -0700, Flavio <fccoelho@gmail .com> wrote:[color=blue]
                    > Now what would you do if you wanted to pass a lot of variables (like a
                    > thousand) to a function and did not wanted the declare them in the
                    > function header?[/color]

                    I'd think twice. If on reflection I decided I really wanted to do it,
                    I'd pass them all in a dictionary.

                    --
                    Cheers,
                    Simon B,
                    simon@brunningo nline.net,

                    Comment

                    • Diez B. Roggisch

                      #11
                      Re: updating local()

                      Flavio wrote:[color=blue]
                      > Ok,
                      >
                      > I got it!
                      >
                      > Its vey insecure, and it is not guaranteed to work. Fine.
                      >
                      > Now what would you do if you wanted to pass a lot of variables (like a
                      > thousand) to a function and did not wanted the declare them in the
                      > function header?[/color]

                      use a dict or list? This is almost certainly a design smell - and a
                      pretty strong one, too.. Nobody is using so many variables and actually
                      typing them - so there certainly is some naming scheme that could be
                      used to access the values from a dict.

                      Or, to put it differently: show us the code that uses thousands of
                      variables, and we show you how to improve that.

                      Diez

                      Comment

                      • Steve Holden

                        #12
                        Re: updating local()

                        Richard Brodie wrote:[color=blue]
                        > "Flavio" <fccoelho@gmail .com> wrote in message
                        > news:1128603314 .197733.119160@ g47g2000cwa.goo glegroups.com.. .
                        >
                        >[color=green]
                        >>Now what would you do if you wanted to pass a lot of variables (like a
                        >>thousand) to a function and did not wanted the declare them in the
                        >>function header?[/color]
                        >
                        >
                        > I'd lie down until I felt better.
                        >
                        >[/color]
                        Or alternatively put them in a 1,000-element list. Just as a matter of
                        interest, what on *earth* is the use case for a function with a thousand
                        arguments?

                        regards
                        Steve
                        --
                        Steve Holden +44 150 684 7255 +1 800 494 3119
                        Holden Web LLC www.holdenweb.com
                        PyCon TX 2006 www.python.org/pycon/

                        Comment

                        • Flavio

                          #13
                          Re: updating local()

                          I wish all my problems involved just a couple of variables, but
                          unfortunately the real interesting problems tend to be complex...

                          As a last resort this problem could be solved by something like this:

                          def fun(**kw):
                          a = 100
                          for k,v in kw.items():
                          exec('%s = %s'%(k,v))
                          print locals()

                          [color=blue][color=green][color=darkred]
                          >>> fun(**{'a':1,'b ':2})[/color][/color][/color]
                          {'a': 1, 'k': 'b', 'b': 2, 'kw': {'a': 1, 'b': 2}, 'v': 2}

                          But that would be utterly stupid! So much for not being able to write
                          to locals()....

                          any better Ideas?

                          Comment

                          • Flavio

                            #14
                            Re: updating local()

                            Ok, its not thousands, but more like dozens of variables...
                            I am reading a large form from the web which returns a lot of values.
                            (I am Using cherrypy)

                            I know I could pass these variables around as:

                            def some_function(* *variables):
                            ...

                            some_function(* *variables)

                            but its a pain in the neck to have to refer to them as
                            variables['whatever']...

                            dont you think?

                            Flavio

                            Comment

                            • Simon Brunning

                              #15
                              Re: updating local()

                              On 6 Oct 2005 07:04:08 -0700, Flavio <fccoelho@gmail .com> wrote:[color=blue]
                              > I know I could pass these variables around as:
                              >
                              > def some_function(* *variables):
                              > ...
                              >
                              > some_function(* *variables)
                              >
                              > but its a pain in the neck to have to refer to them as
                              > variables['whatever']...
                              >
                              > dont you think?[/color]

                              Err, no, not really. ;-)

                              If you'd prfefer to access them like this:

                              variables.whate ver

                              Check out the Bunch class here -
                              <http://aspn.activestat e.com/ASPN/Cookbook/Python/Recipe/52308>.

                              --
                              Cheers,
                              Simon B,
                              simon@brunningo nline.net,

                              Comment

                              Working...