**kwds behavior?

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

    **kwds behavior?

    Why does the following attempts to pass in keywords arguments not
    work. It would be alot cooler if there was a way to not have to have
    the function defined with the variable name. It really seems to me
    that the 3rd function should work. Does anyone know how to accomplish
    something like this.
    def testKeywords1 (**kwds):
    print x

    def testKeywords2 (**kwds):
    locals().update (kwds)
    print x

    def testKeywords3 (**kwds):
    locals().update (kwds)
    def testNested():
    print x
    testNested()

    dict = {}
    dict['x'] = 5
    # doesn't work
    testKeywords1(* *dict)
    # doesn't work
    testKeywords2(* *dict)
    # doesn't work
    testKeywords3(* *dict)
  • John Roth

    #2
    Re: **kwds behavior?


    The description of the locals() function is:

    Update and return a dictionary representing the current local symbol table.
    Warning: The contents of this dictionary should not be modified; changes may
    not affect the values of local variables used by the interpreter.

    Note that this implies that the dictionary is essentially
    read only. What you're trying to do shouldn't work.

    John Roth

    "Paradox" <JoeyTaj@netzer o.com> wrote in message
    news:924a9f9c.0 309020652.212c5 4eb@posting.goo gle.com...[color=blue]
    > Why does the following attempts to pass in keywords arguments not
    > work. It would be alot cooler if there was a way to not have to have
    > the function defined with the variable name. It really seems to me
    > that the 3rd function should work. Does anyone know how to accomplish
    > something like this.
    > def testKeywords1 (**kwds):
    > print x
    >
    > def testKeywords2 (**kwds):
    > locals().update (kwds)
    > print x
    >
    > def testKeywords3 (**kwds):
    > locals().update (kwds)
    > def testNested():
    > print x
    > testNested()
    >
    > dict = {}
    > dict['x'] = 5
    > # doesn't work
    > testKeywords1(* *dict)
    > # doesn't work
    > testKeywords2(* *dict)
    > # doesn't work
    > testKeywords3(* *dict)[/color]


    Comment

    • Jeff Epler

      #3
      Re: **kwds behavior?

      Changes to locals() do not necessarily affect anything.
      locals()
      Update and return a dictionary representing the current local
      symbol table. *Warning*: The contents of this dictionary should
      not be modified; changes may not affect the values of local
      variables used by the interpreter.
      -- http://python.org/doc/current/lib/bu...cs.html#l2h-47

      You should probably try a different approach to whatever the underlying
      task is.

      Jeff

      Comment

      • Terry Reedy

        #4
        Re: **kwds behavior?


        "Paradox" <JoeyTaj@netzer o.com> wrote in message
        news:924a9f9c.0 309020652.212c5 4eb@posting.goo gle.com...[color=blue]
        > Why does the following attempts to pass in keywords arguments not
        > work.[/color]

        What do you mean 'not work'. What was your output and what did you
        expect?
        [color=blue]
        >It would be alot cooler if there was a way to not have to have
        > the function defined with the variable name.[/color]

        I don't understand your meaning here.

        It really seems to me[color=blue]
        > that the 3rd function should work. Does anyone know how to[/color]
        accomplish[color=blue]
        > something like this.[/color]

        Again, what is 'this'?
        [color=blue]
        > def testKeywords1 (**kwds):
        > print x[/color]

        If you want posted code to be read with indents by everybody, use
        space instead of tab to indent. It's your choice to limit readership
        or not.
        [color=blue]
        >
        > def testKeywords2 (**kwds):
        > locals().update (kwds)[/color]

        Above line has same effect as 'pass' for reason John Roth quoted.
        [color=blue]
        > print x
        >
        > def testKeywords3 (**kwds):
        > locals().update (kwds)
        > def testNested():
        > print x
        > testNested()
        >
        > dict = {}
        > dict['x'] = 5
        > # doesn't work[/color]

        I usually expect 'doesn't work' to apply to the line above that I just
        read -- just as this response applies to the line quoted above. I
        suspect you meant 'below doesn't work', whatever 'doesn't work means.
        The alternative way to reverse the 'pointer' is to leave a space above
        and none below.
        [color=blue]
        > testKeywords1(* *dict)
        > # doesn't work
        > testKeywords2(* *dict)
        > # doesn't work
        > testKeywords3(* *dict)[/color]

        If you don't get your question answered with above, try again with
        different words.

        Terry J. Reedy


        Comment

        • Terry Reedy

          #5
          Re: **kwds behavior?


          "Sean Ross" <sross@connectm ail.carleton.ca > wrote in message
          news:2S25b.841$ I_2.211334@news 20.bellglobal.c om...[color=blue]
          > better if attempting to write to an non-writable dict raised an[/color]
          exception,[color=blue]
          > but that is not the current behaviour.[/color]

          The dict returned by locals(), even within a function, *is* writable
          [color=blue][color=green][color=darkred]
          >>> def f():[/color][/color][/color]
          .... l = locals()
          .... l[5] = 6
          .... print l
          ....[color=blue][color=green][color=darkred]
          >>> f()[/color][/color][/color]
          {5: 6}

          However, it is only a dict copy of the local namespace, (which in
          CPython happens to not be a dict of any sort).
          [color=blue]
          > So, your call to update has no effect
          > on the local namespace and, thus, 'x' is not yet defined locally.[/color]

          So d=locals() can be used for what it is -- a dict initialized from
          the local namespace at a particular time, but which is thereafter
          independent from the local namespace.

          Terry J. Reedy


          Comment

          • Hans Nowak

            #6
            Re: **kwds behavior?

            Paradox wrote:[color=blue]
            > Why does the following attempts to pass in keywords arguments not
            > work. It would be alot cooler if there was a way to not have to have
            > the function defined with the variable name. It really seems to me
            > that the 3rd function should work. Does anyone know how to accomplish
            > something like this.[/color]

            "this" apparently means, that you want to create local variables (within in the
            function) with the same names as the keyword arguments.
            [color=blue]
            > def testKeywords1 (**kwds):
            > print x
            >
            > def testKeywords2 (**kwds):
            > locals().update (kwds)
            > print x
            >
            > def testKeywords3 (**kwds):
            > locals().update (kwds)
            > def testNested():
            > print x
            > testNested()[/color]

            As people already pointed out, modifying locals() like this doesn't work.
            There is a solution, but before using it you should stop and ask yourself why
            you want this. Is there a reason why leaving the values in the dict isn't
            sufficient? (Or putting them in a special class, like one poster suggested.)
            Creating variables on-the-fly is usually a bad idea.

            Now, on to the yucky solution:
            [color=blue][color=green][color=darkred]
            >>> def g(**kwargs):[/color][/color][/color]
            for key, value in kwargs.items():
            exec "%s = %s" % (key, repr(value))
            # test test...
            print x
            [color=blue][color=green][color=darkred]
            >>> d = {}
            >>> d['x'] = 5
            >>> g(**d)[/color][/color][/color]
            5

            HTH,

            --
            Hans (hans@zephyrfal con.org)
            Memimpin Angin Perubahan Teknologi




            Comment

            • Terry Reedy

              #7
              Re: **kwds behavior?


              "Hans Nowak" <hans@zephyrfal con.org> wrote in message
              news:mailman.10 62522376.29013. python-list@python.org ...[color=blue]
              > Now, on to the yucky solution:
              >[color=green][color=darkred]
              > >>> def g(**kwargs):[/color][/color]
              > for key, value in kwargs.items():
              > exec "%s = %s" % (key, repr(value))
              > # test test...[/color]

              This is cute but limited. It only works when values ==
              eval(repr(value )), which is to say, numbers, strings, and,
              recursively, tuples, lists, and dicts and some user-class instances.
              Others will raise syntax error.

              Terry J. Reedy


              Comment

              • Jeff Epler

                #8
                Re: **kwds behavior?

                On Tue, Sep 02, 2003 at 01:10:41PM -0400, Hans Nowak wrote:[color=blue]
                > Now, on to the yucky solution:
                >[color=green][color=darkred]
                > >>> def g(**kwargs):[/color][/color]
                > for key, value in kwargs.items():
                > exec "%s = %s" % (key, repr(value))
                > # test test...
                > print x[/color]
                [...]
                Now, you don't need to do that. This one works:
                def testKeywords5(* *kwds):
                exec ""
                locals().update (kwds)
                print x
                [color=blue][color=green][color=darkred]
                >>> testKeywords5(x =5)[/color][/color][/color]
                5

                even this variant should work (without actually executing any "exec"
                statements):
                def testKeywords6(* *kwds):
                locals().update (kwds)
                print x
                return
                exec ""

                .... but I don't think you can/should depend that either variation works.
                The key is that when the compiler sees 'bare exec' it disables an
                optimization used to turn local name accesses into fast C-array-based
                indexing operations...

                I stand by my words that you (the OP) should back up a step and choose a
                solution that doesn't have this yucky requirement of locals that aren't
                known at bytecompile time.

                Jeff

                Comment

                • Bengt Richter

                  #9
                  Re: **kwds behavior?

                  On 2 Sep 2003 07:52:22 -0700, JoeyTaj@netzero .com (Paradox) wrote:
                  [color=blue]
                  >Why does the following attempts to pass in keywords arguments not
                  >work. It would be alot cooler if there was a way to not have to have
                  >the function defined with the variable name. It really seems to me
                  >that the 3rd function should work. Does anyone know how to accomplish
                  >something like this.
                  >def testKeywords1 (**kwds):
                  > print x
                  >
                  >def testKeywords2 (**kwds):
                  > locals().update (kwds)
                  > print x
                  >
                  >def testKeywords3 (**kwds):
                  > locals().update (kwds)
                  > def testNested():
                  > print x
                  > testNested()
                  >
                  >dict = {}
                  >dict['x'] = 5
                  ># doesn't work
                  >testKeywords1( **dict)
                  ># doesn't work
                  >testKeywords2( **dict)
                  ># doesn't work
                  >testKeywords3( **dict)[/color]

                  A couple of other things that might relate to what you want:
                  [color=blue][color=green][color=darkred]
                  >>> def testkw(**kw):[/color][/color][/color]
                  ... exec 'print x' in kw
                  ...[color=blue][color=green][color=darkred]
                  >>> testkw(x='did it work?')[/color][/color][/color]
                  did it work?

                  Guess so, but[color=blue][color=green][color=darkred]
                  >>> testkw(y='did it work?')[/color][/color][/color]
                  Traceback (most recent call last):
                  File "<stdin>", line 1, in ?
                  File "<stdin>", line 2, in testkw
                  File "<string>", line 1, in ?
                  NameError: name 'x' is not defined

                  Note that that's a NameError, not a KeyError, as in:[color=blue][color=green][color=darkred]
                  >>> def testkw1(**kw):[/color][/color][/color]
                  ... print '%(x)s' % kw
                  ...[color=blue][color=green][color=darkred]
                  >>> testkw1(x='did it work?')[/color][/color][/color]
                  did it work?

                  Ok, but[color=blue][color=green][color=darkred]
                  >>> testkw1(y='did it work?')[/color][/color][/color]
                  Traceback (most recent call last):
                  File "<stdin>", line 1, in ?
                  File "<stdin>", line 2, in testkw1
                  KeyError: 'x'

                  Yet another way ...
                  [color=blue][color=green][color=darkred]
                  >>> def testkw2(**kw):[/color][/color][/color]
                  ... ns = type('',(),kw)( )
                  ... print ns.x
                  ...[color=blue][color=green][color=darkred]
                  >>> testkw2(x='did it work?')[/color][/color][/color]
                  did it work?
                  [color=blue][color=green][color=darkred]
                  >>> testkw2(y='did it work?')[/color][/color][/color]
                  Traceback (most recent call last):
                  File "<stdin>", line 1, in ?
                  File "<stdin>", line 3, in testkw2
                  AttributeError: '' object has no attribute 'x'

                  Or silliness,
                  [color=blue][color=green][color=darkred]
                  >>> def testkw3(**kw):[/color][/color][/color]
                  ... exec """
                  ... def foo():
                  ... print x
                  ... """ in kw
                  ... kw['foo']()
                  ...[color=blue][color=green][color=darkred]
                  >>> testkw3(x='did it work?')[/color][/color][/color]
                  did it work?
                  [color=blue][color=green][color=darkred]
                  >>> testkw3(y='did it work?')[/color][/color][/color]
                  Traceback (most recent call last):
                  File "<stdin>", line 1, in ?
                  File "<stdin>", line 6, in testkw3
                  File "<string>", line 3, in foo
                  NameError: global name 'x' is not defined

                  So what are you actually trying to do?

                  Regards,
                  Bengt Richter

                  Comment

                  • Paradox

                    #10
                    Re: **kwds behavior?

                    Thanks for the replies. basically what I was trying to accomplish was
                    to be able to load a script text file with python syntax into a class
                    and have it be able to cleanly reference the properties and methods.

                    I have currently accomplished it with something like this

                    code = compile(scriptT ext, '<string>','exe c')
                    exec code in self.__dict__

                    Comment

                    Working...