ordered keywords?

Discussion in 'Python' started by Ron Adam, Oct 17, 2005.

  1. Ron Adam

    Ron Adam Guest

    Is there a way to preserve or capture the order which keywords are given?

    >>> def foo(**kwds):

    .... print kwds
    ....
    >>> foo(one=1, two=2, three=3)

    {'three': 3, 'two': 2, 'one': 1}


    I would love to reverse the *args, and **kwds as well so I can use kwds
    to set defaults and initiate values and args to set the order of
    expressions.


    def foo(**__dict__, *args):
    print args

    print foo(x=10, y=20, x, y, x+y)
    [10, 20, 30]


    Ok, I know there is a lot of problems with that. The reason I would
    like it is because I think there might be a use case for it where a
    function iterates over *args in order, but uses kwds to set values.

    def drawshapes(**inits, *args):
    for obj in args:
    obj.draw()

    drawshapes( triangle=3, square=4, color=red,
    polygon(triangle, color),
    polygon(square, color) )

    This comes close to the same pattern used in SVG and other formats where
    you have definitions before expressions. If I use keywords only, It
    won't keep the order, and if I use args before keywords, I have to
    pre-assign temporary 'None' values to the arguments in the parent or
    global scope.

    Any ideas?

    Cheers,
    Ron
    Ron Adam, Oct 17, 2005
    #1
    1. Advertising

  2. Ron Adam wrote:
    >
    > Is there a way to preserve or capture the order which keywords are given?
    >
    > >>> def foo(**kwds):

    > ... print kwds
    > ...
    > >>> foo(one=1, two=2, three=3)

    > {'three': 3, 'two': 2, 'one': 1}
    >
    >
    > I would love to reverse the *args, and **kwds as well so I can use kwds
    > to set defaults and initiate values and args to set the order of
    > expressions.
    >
    >
    > def foo(**__dict__, *args):
    > print args
    >
    > print foo(x=10, y=20, x, y, x+y)
    > [10, 20, 30]


    This is not simply about reversing the order of kwargs and args - this
    would require that keyword args would create bindings to variable names
    in the scope of the caller. Which is an enterily different beast. And a
    major semantic change in python, so it's not possible or at least not
    happening before Python 3K.

    Regards,

    Diez
    Diez B. Roggisch, Oct 17, 2005
    #2
    1. Advertising

  3. Ron Adam

    Ron Adam Guest

    Diez B. Roggisch wrote:
    > Ron Adam wrote:
    >
    >>
    >> Is there a way to preserve or capture the order which keywords are given?
    >>
    >> >>> def foo(**kwds):

    >> ... print kwds
    >> ...
    >> >>> foo(one=1, two=2, three=3)

    >> {'three': 3, 'two': 2, 'one': 1}
    >>
    >>
    >> I would love to reverse the *args, and **kwds as well so I can use
    >> kwds to set defaults and initiate values and args to set the order of
    >> expressions.
    >>
    >>
    >> def foo(**__dict__, *args):
    >> print args
    >>
    >> print foo(x=10, y=20, x, y, x+y)
    >> [10, 20, 30]

    >
    >
    > This is not simply about reversing the order of kwargs and args - this
    > would require that keyword args would create bindings to variable names
    > in the scope of the caller. Which is an enterily different beast. And a
    > major semantic change in python, so it's not possible or at least not
    > happening before Python 3K.
    >
    > Regards,
    >
    > Diez


    Yes, I kind of thought it would be pretty major. What I'm asking is how
    to get anything close to this behavior in the current Python 2.4 now
    either with functions or with class's. Or a way to generalize it in a
    nested data structure. But that runs into similar problems of self
    reference.

    I think the idea of putting the initialization first fits a lot of data
    patterns. But I really don't know how the best way to implement that
    would be.

    I was hoping it just might be possible (for P3k?) to have an argument
    list look to itself before looking to the caller, and then to globals
    after that. And not create additional binding in the caller name space.
    I think that would mean pre-creating the callee name space so it can
    be accessed by later terms in the argument list before control and the
    name space is handed over to the function. I think this would be
    earlier evaluation instead of the late evaluation some want.


    <clipped examples of possible stuff and jump to the interesting part>


    def lamb(args):
    for v in args: print v

    def feedlamb():
    print locals()
    lamb( (lambda x=10, y=20: (x,y,x+y))() )
    print locals()

    feedlamb()

    {}
    10
    20
    30
    {}


    AND... (!?)


    def lamb(args):
    for v in args: print v

    def feedlamb():
    print locals()
    y = 20
    lamb( (lambda x=10: (x,y,x+y))() )
    print locals()

    feedlamb()

    {}
    10
    20
    30
    {'y': 20}


    Cool, this is the exact behavior I was thinking of, but without the
    lambda if possible, and without all the extra parentheses. Anyway to
    clean this up?

    Maybe it wouldn't be as big a change as it seems? ;-)

    Cheers,
    Ron
    Ron Adam, Oct 17, 2005
    #3
  4. Ron Adam

    Ron Adam Guest

    Ron Adam wrote:

    >
    > def lamb(args):
    > for v in args: print v
    >
    > def feedlamb():
    > print locals()
    > y = 20
    > lamb( (lambda x=10: (x,y,x+y))() )
    > print locals()
    >
    > feedlamb()
    >
    > {}
    > 10
    > 20
    > 30
    > {'y': 20}
    >
    >
    > Cool, this is the exact behavior I was thinking of, but without the
    > lambda if possible, and without all the extra parentheses. Anyway to
    > clean this up?
    >
    > Maybe it wouldn't be as big a change as it seems? ;-)
    >
    > Cheers,
    > Ron



    Ok, this has a problem, there's no way to pass the values as keywords
    also. The lambda's a bit too isolated. So the following doesn't work as
    expected.

    lamb( (lambda x=10: (x,y,x+y,{'x':x}))() )


    Regards,
    Ron
    Ron Adam, Oct 18, 2005
    #4
  5. Ron Adam

    Kent Johnson Guest

    Ron Adam wrote:
    > drawshapes( triangle=3, square=4, color=red,
    > polygon(triangle, color),
    > polygon(square, color) )
    >
    > This comes close to the same pattern used in SVG and other formats where
    > you have definitions before expressions.


    Why is this better than the obvious
    triangle=3
    square=4
    color=red
    drawshapes(polygon(triangle, color),
    polygon(square, color) )

    or even
    drawshapes(polygon(3, red),
    polygon(4, red) )

    which is concise and readable IMO...?

    Kent
    Kent Johnson, Oct 18, 2005
    #5
  6. Ron Adam

    Ron Adam Guest

    Kent Johnson wrote:
    > Ron Adam wrote:
    >
    >> drawshapes( triangle=3, square=4, color=red,
    >> polygon(triangle, color),
    >> polygon(square, color) )
    >>
    >> This comes close to the same pattern used in SVG and other formats
    >> where you have definitions before expressions.

    >
    >
    > Why is this better than the obvious
    > triangle=3
    > square=4
    > color=red
    > drawshapes(polygon(triangle, color),
    > polygon(square, color) )
    >
    > or even
    > drawshapes(polygon(3, red),
    > polygon(4, red) )
    >
    > which is concise and readable IMO...?
    >
    > Kent


    That example was over simplified quite a bit. :)

    The reason I'm trying to get named attributes is so I can change colors
    or the text items later without having to recreate the object. The
    objects I'm using are capable inheriting from other predefined objects
    so you only have to add or modify it a tiny bit.

    For example the following creates shapes that build on each other and
    they all have a .draw() method to draw on a Tk canvas. In addition they
    can be scaled, stretched and rotated. Well, the ones based on polygons
    and lines can be rotated and stretched. I'm still working on how to do
    that with arcs and text items.



    ## These are the most basic shape elements which use the
    ## Tkinter canvas items specified by the 'obj' attribute.

    # base shapes.
    text = Shape( obj='text', text='', fill='black', size=1,
    font='', style='', pos=(0,0), points=(0,0) )

    line = Shape( obj='line', arrow='none', fill='black', smooth='false',
    pos=(0,0), width=.1, points=(-.5,0,.5,0), size=1,
    rotate=0, center=(0,0) )

    polygon = Shape( obj='polygon', fill='grey', outline='', size=1,
    smooth='false', pos=(0,0), width=0, points=(0,0),
    rotate=0, center=(0,0), ratio=(1,1) )

    arc = Shape( obj='arc', fill='grey', outline='', pos=(0,0), width=0,
    size=1, style='arc', start='0', extent='90',
    points=(-.5,-.5,.5,.5) )



    ## This next group inherits from the shapes above and only
    ## needs to change what's different.

    # shape variations
    chord = arc(style='chord')
    pie = arc(style='pieslice')
    rectangle = polygon(points=[-.5,-.5,.5,-.5,.5,.5,-.5,.5])
    triangle = polygon(points=getpolygon(3))
    square = polygon(points=getpolygon(4))
    octagon = polygon(points=getpolygon(8))
    circle = polygon(smooth='true', points=getpolygon(16))

    # The oval is stretched circle, which is a smoothed polygon.
    # this can be rotated, the Tkinter oval can't.
    oval = circle(ratio=(1,.7))


    ## Grouping combines the shapes together. Again only what is
    ## different needs to be changed, such as color or size and
    ## relative position. Any previously defined
    ## shapes can be combined to create complex new ones.

    # CAUTION ICON
    caution = Group(
    triangle(pos=(6,5), size=75),
    triangle(fill='yellow', size=75),
    txt = text( text='!', font='times', style='bold',
    pos=(0,-3), size=30,) )

    # ERROR ICON
    error = Group(
    octagon(pos=(6,5), size=55),
    octagon(fill='red', size=55),
    circle(fill='white', size=37),
    circle(fill='red', size=25),
    line(fill='white', width=.2, rotate=45, size=28) )


    ## For this next group it would be nice if the bubbletip
    ## shape could be in the argument list, but it would need
    ## to be after the other refernces to it, and they
    ## would not find it. I did it this way to try out
    ## the idea of reusing objects, it would be no trouble
    ## just to duplicate the bubbletip in this case.

    # QUESTION & INFO ICONS
    bubbletip = polygon(points=[-5,10, 20,10, 30,30])
    question = Group(
    bubbletip(pos=(6,5)),
    oval(pos=(6,5), size=60),
    bubbletip(fill='lightblue'),
    oval(fill='lightblue', size=60),
    txt = text( text='?', font='times', style='bold',
    size=25 ) )


    ## Here I just need to change the text element to 'i' to get
    ## the Info icon. Since it has a name we can do that.

    info = question() # get a copy of question
    info.txt.text = 'i' # change the '?' mark to 'i'


    These can all be in a file ready to import and then you can use them
    anywhere in Tkinter that accepts a normal canvas commands.

    caution.draw(c, pos=(70,50), scale=.5) # small caution icon
    error.draw(c, pos=(150,48), scale=3) # triple sized error icon


    Now this all works wonderfully, but I can only have one named attribute
    because I can't depend on the order a dictionary has. So I'm going to
    probaby need to have a layer attribute. Thus the need for either
    ordered keyword arguments, or a way to specify keywords as a variable
    for the arguments list.

    Eventually I will be able to mix groups and shapes together in other
    groups by using them exactly like any other shape. So I can take a
    image of a guy, add a hat, tilt the hat, and few other props, put some
    text on it, and I have a nice illustration with very little effort.

    There are still a lot of small details that still need to be worked out
    before it's suitable for real use. It works now, but too much will
    change as I add too it at this stage. ;-)

    Cheers,
    Ron
    Ron Adam, Oct 18, 2005
    #6
    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. Newbie
    Replies:
    1
    Views:
    517
    Andrew Thompson
    Apr 7, 2004
  2. Arvind Ganesan

    ordered list (OL) tag with tables

    Arvind Ganesan, Sep 6, 2003, in forum: HTML
    Replies:
    10
    Views:
    10,499
    Nico Schuyt
    Sep 6, 2003
  3. Jim Royal
    Replies:
    3
    Views:
    352
    Jim Royal
    Sep 16, 2003
  4. Luigi Donatello Asero

    Numbers in ordered lists

    Luigi Donatello Asero, May 5, 2004, in forum: HTML
    Replies:
    13
    Views:
    776
    Andrew Urquhart
    May 7, 2004
  5. DL

    Ordered list inside ordered list

    DL, Nov 9, 2009, in forum: Javascript
    Replies:
    6
    Views:
    323
    Dr J R Stockton
    Nov 21, 2009
Loading...

Share This Page