FAQ
Since George Sakkis proposed a new way of doing list comprehensions

http://groups-beta.google.com/group/comp.lang.python/browse_frm/thread/ac5023ad18b2835f/d3ff1b81fa70c8a7#d3ff1b81fa70c8a7

letting tuples-like objects (x,y,z=0) acting as functions on other
tuples I wonder why this would not be a good starting point of
rethinking anonymus functions?

In Georges proposition the action is

(x,y,z=0) -> (x,y,z)

i.e. mapping tuples on other tuples. This is equivalent to

lambda x,y,z=0:(x,y,z)

But regarding tuples as actions by means of an arrow "->" would
generalize this idea:

Mappings like that:

((x,y),z) -> x+y-z

((x,y=0),z) -> None

should be valid actions too.

What is the audience thinking about that?

Regards Kay

Search Discussions

  • Kay Schluehr at Mar 22, 2005 at 6:37 am
    Since George Sakkis proposed a new way of doing list comprehensions

    http://groups-beta.google.com/group/comp.lang.python/browse_frm/thread/ac5023ad18b2835f/d3ff1b81fa70c8a7#d3ff1b81fa70c8a7

    letting tuples-like objects (x,y,z=0) acting as functions on other
    tuples I wonder why this would not be a good starting point of
    rethinking anonymus functions?

    In Georges proposition the action is

    (x,y,z=0) -> (x,y,z)

    i.e. mapping tuples on other tuples. This is equivalent to

    lambda x,y,z=0:(x,y,z)

    But regarding tuples as actions by means of an arrow "->" would
    generalize this idea:

    Mappings like that:

    ((x,y),z) -> x+y-z

    ((x,y=0),z) -> None

    should be valid actions too.

    What is the audience thinking about that?

    Regards Kay
  • Bruno modulix at Mar 22, 2005 at 10:17 am

    Kay Schluehr wrote:
    Since George Sakkis proposed a new way of doing list comprehensions

    http://groups-beta.google.com/group/comp.lang.python/browse_frm/thread/ac5023ad18b2835f/d3ff1b81fa70c8a7#d3ff1b81fa70c8a7

    letting tuples-like objects (x,y,z=0) acting as functions on other
    tuples I wonder why this would not be a good starting point of
    rethinking anonymus functions?

    In Georges proposition the action is

    (x,y,z=0) -> (x,y,z)

    i.e. mapping tuples on other tuples. This is equivalent to

    lambda x,y,z=0:(x,y,z)

    But regarding tuples as actions by means of an arrow "->" would
    generalize this idea:

    Mappings like that:

    ((x,y),z) -> x+y-z

    ((x,y=0),z) -> None

    should be valid actions too.

    What is the audience thinking about that?
    IMHO, it's just lambda in disguise, and I'm not sure it's more readable
    than lambda. You'll have to provide more arguments (sorry for the pun
    !-) to gain my adhesion. (NB : I could use this syntax without problem,
    it's just that we already have a syntax for this).


    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in 'onurb at xiludom.gro'.split('@')])"
  • Bruno modulix at Mar 22, 2005 at 2:05 pm

    bruno modulix wrote:
    Kay Schluehr wrote:
    Since George Sakkis proposed a new way of doing list comprehensions

    http://groups-beta.google.com/group/comp.lang.python/browse_frm/thread/ac5023ad18b2835f/d3ff1b81fa70c8a7#d3ff1b81fa70c8a7


    letting tuples-like objects (x,y,z=0) acting as functions on other
    tuples I wonder why this would not be a good starting point of
    rethinking anonymus functions?

    In Georges proposition the action is

    (x,y,z=0) -> (x,y,z)

    i.e. mapping tuples on other tuples. This is equivalent to

    lambda x,y,z=0:(x,y,z)
    which is in fact not a valid solution in the context of Georges'
    problem... (or I failed to get it to work !-)

    But regarding tuples as actions by means of an arrow "->" would
    generalize this idea:

    Mappings like that:

    ((x,y),z) -> x+y-z

    ((x,y=0),z) -> None

    should be valid actions too.

    What is the audience thinking about that?

    IMHO, it's just lambda in disguise, and I'm not sure it's more readable
    than lambda. You'll have to provide more arguments (sorry for the pun
    !-) to gain my adhesion. (NB : I could use this syntax without problem,
    it's just that we already have a syntax for this).
    Changing my mind after a more torough re-reading of the original thread
    and few tests... The original problem is about tuple unpacking. The
    proposed solution solves this problem, *and* can (could ?) be a
    replacement for lambdas.

    hmmm... I like the idea of having a more flexible tuple unpacking with a
    function-call-like semantic, but I'm still not sure to like the idea of
    replacing lambda with the proposed syntax.

    needs-some-more-thinking-on-this-ly'yrs

    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in 'onurb at xiludom.gro'.split('@')])"
  • Ron at Mar 22, 2005 at 5:13 pm

    On Tue, 22 Mar 2005 15:05:55 +0100, bruno modulix wrote:
    bruno modulix wrote:
    Kay Schluehr wrote:
    Since George Sakkis proposed a new way of doing list comprehensions
    letting tuples-like objects (x,y,z=0) acting as functions on other
    tuples I wonder why this would not be a good starting point of
    rethinking anonymus functions?

    In Georges proposition the action is

    (x,y,z=0) -> (x,y,z)

    What about a safe exec as a replacement to lamba but witht he
    flexability of exec in a safe and limeted way?

    safe_exec ( (*inputs) , (expressionstring) , ( *outputs) )

    Functon to return a default value:
    def dfv( arg = value):
    return arg

    Safe exec command:
    x, y = 1, 2
    safeexec ( (x, y, dfv(z=0)), "# do nothing", ( x, y, z) )
    (1, 2, 0)

    What could we do, not do with this?



    * I actually started this reply here, so below is how I got to the
    above exression.


    I'm trying to put my finger on the basic inconsistency here. It has
    something to do with the z=0 as a way to defining a default .

    Then there's the lamba which I hear may be removed, but is difficult
    to understand for beginners, and isn't readable in that the name
    doesn't say what it does. An alternative name, and possibly a
    simpler syntax would be a plus.

    Another concept that this touches is the indirect execution of an
    expression. Exec and eval do that, but then you introduce security
    issues.

    I'm wondering if there's a fundamental concept under these issues such
    as a base function class or command that can evaluate the contents of
    a tuple in a secure way?

    value = fn(arg, returnvalue)
    x = 1
    fn( x, x*2)
    2

    Use lists or tuples for multiple arguments and return expressions:
    x, y, z = 1, 2, 3
    fn( (x,y,z=0), (x,y,z) )
    (1, 2, 3)

    But it's that "z=0" causes problems here. In a tuple it's equivalent
    to saying 1=2. or 'a'='b'

    So we need a way to say 'if name is undefined, bind it to object'.

    # function to give a default value
    def dfv( arg = value):
    return arg
    x, y = 1, 2
    fn( (x, y, dfv(x=0)), ( x, y, z ))
    (1, 2, 3)

    Now since this could execute in it's own private space, it might also
    offer a way to use exec or eval() indirectly in a very limited and
    safe way.
    estring = \
    """
    result = ''
    data = 'abcdefghigklmnop'
    for ch in data:
    if ch != filterc:
    result.join(ch)
    """
    fn( ( dfv(filterc='d'), evalstring), (exec estring) )
    So we need to use a three item tuple:

    safe_exec ( (*inputs) , (expressionstring) , ( *outputs) )
    def dfv( arg = value):
    return arg
    x, y = 1, 2
    safeexec( (x, y, dfv(z=0)), "# do nothing", ( x, y, z) )
    (1, 2, 0)

    Long way around to here, but is this something that has potential?
    It would have to be a built in to ensure it's safe to use. But with
    an exec string, it can possibly do a lot more than lamba, and it
    probably wouldn't be as fast. But the flexibility could be useful.

    Ron
  • Bruno Desthuilliers at Mar 22, 2005 at 8:43 pm
    Ron a ?crit :
    (snip)
    def dfv( arg = value):
    return arg
    def dfv( arg = value):
    ... return arg
    ...
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    NameError: name 'value' is not defined

    And sorry, but -1 for using exec here.
  • Ron at Mar 22, 2005 at 9:56 pm

    On Tue, 22 Mar 2005 21:43:48 +0100, Bruno Desthuilliers wrote:

    Ron a ?crit :
    (snip)
    def dfv( arg = value):
    return arg
    def dfv( arg = value):
    ... return arg
    ...
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    NameError: name 'value' is not defined

    And sorry, but -1 for using exec here.

    Yes, I cought that myself. So...

    try: z=z
    except: z=0

    or

    if 'z' not in locals():
    z = 0

    Ok, thinking in more incremental terms...

    Why should a function not create a local varable of an argument if the
    varable doesn't exist and a default value is given?

    So when:

    Def dfv( v=0):
    return v
    dfv()
    0 ;it creates the local copy in this case.
    a = 25
    dfv(a)
    25 ;It used the given value as expected.
    dfv(b)
    Traceback (most recent call last):
    File "<pyshell#4>", line 1, in -toplevel-
    dfv(b)
    NameError: name 'b' is not defined

    Why not let it set the local varable v to the default as it does when
    no varable is specified?

    A function without a default would still give an error as expected.


    :)
    Ok no exec, but what about the general syntax?

    value = keyword (inputargs, command, outputargs)

    I was thinking if it can be done with standard tuples, it has the
    potential to be passed around easily and work from lists and
    dictionaries.

    Ron
  • Ron at Mar 22, 2005 at 10:27 pm

    On Tue, 22 Mar 2005 21:56:57 GMT, Ron wrote:
    Why should a function not create a local varable of an argument if the
    varable doesn't exist and a default value is given?
    ok... thought it out better. :)

    Getting a default into a function isn't the problem. Returning the
    value to a varable that doesn't exist is.

    So then the question is ... is there a way for a function to create a
    varable in it's parents namespace that persists after the function is
    done?
  • George Sakkis at Mar 22, 2005 at 11:15 pm

    "Ron" wrote:
    On Tue, 22 Mar 2005 21:56:57 GMT, Ron wrote:

    Why should a function not create a local varable of an argument if the
    varable doesn't exist and a default value is given?
    ok... thought it out better. :)

    Getting a default into a function isn't the problem. Returning the
    value to a varable that doesn't exist is.

    So then the question is ... is there a way for a function to create a
    varable in it's parents namespace that persists after the function is
    done?
    Yeap.. a simple one-liner can do the trick:

    def makeVars(**nameVals):
    sys._getframe(1).f_locals.update(nameVals)

    try: b
    except NameError: print "Before makeVars: NameError"
    else: print "Before makeVars: Not NameError"
    makeVars(b=2)
    try: b
    except NameError: print "After makeVars: NameError"
    else: print "After makeVars: Not NameError"

    George
  • Ron at Mar 23, 2005 at 2:11 am

    On Tue, 22 Mar 2005 18:15:25 -0500, "George Sakkis" wrote:

    "Ron" wrote:
    On Tue, 22 Mar 2005 21:56:57 GMT, Ron wrote:

    Why should a function not create a local varable of an argument if the
    varable doesn't exist and a default value is given?
    Yeap.. a simple one-liner can do the trick:

    def makeVars(**nameVals):
    sys._getframe(1).f_locals.update(nameVals)

    try: b
    except NameError: print "Before makeVars: NameError"
    else: print "Before makeVars: Not NameError"
    makeVars(b=2)
    try: b
    except NameError: print "After makeVars: NameError"
    else: print "After makeVars: Not NameError"

    George
    Cool! Thanks George, so I can do this:

    # Set a varable to a default value if it doesn't exist.
    # Return the same value back if it does.
    # Use: varable = dfvalue( varable=object)
    def defvalue(**var):
    if var.keys()[0] not in sys._getframe(1).f_locals.keys():
    return var.values()[0]
    return sys._getframe(1).f_locals[var.keys()[0]]

    f = defvalue(f=0)
    print f # 0

    g = 19
    g = defvalue(g=0)
    print g # 19


    Would there be any problems with using this function?

    Not sure where I need it. Was thinking it could be used inside
    expressions somehow, and it was an iteresting problem. ;)

    Ron
  • Bruno modulix at Mar 23, 2005 at 9:50 am

    George Sakkis wrote:
    "Ron" wrote:
    On Tue, 22 Mar 2005 21:56:57 GMT, Ron wrote:

    Why should a function not create a local varable of an argument if the
    varable doesn't exist and a default value is given?
    ok... thought it out better. :)

    Getting a default into a function isn't the problem. Returning the
    value to a varable that doesn't exist is.

    So then the question is ... is there a way for a function to create a
    varable in it's parents namespace that persists after the function is
    done?

    Yeap.. a simple one-liner can do the trick:

    def makeVars(**nameVals):
    sys._getframe(1).f_locals.update(nameVals)

    try: b
    except NameError: print "Before makeVars: NameError"
    else: print "Before makeVars: Not NameError"
    makeVars(b=2)
    try: b
    except NameError: print "After makeVars: NameError"
    else: print "After makeVars: Not NameError"
    Interesting. I'll keep a copy of this one in my cookbook for further
    exploration. But I think I would use such a thing in production code.
    b = 25
    makeVars(b�)
    b
    88


    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in 'onurb at xiludom.gro'.split('@')])"
  • Duncan Booth at Mar 23, 2005 at 10:13 am

    George Sakkis wrote:

    So then the question is ... is there a way for a function to create a
    varable in it's parents namespace that persists after the function is
    done?
    Yeap.. a simple one-liner can do the trick:

    def makeVars(**nameVals):
    sys._getframe(1).f_locals.update(nameVals)

    try: b
    except NameError: print "Before makeVars: NameError"
    else: print "Before makeVars: Not NameError"
    makeVars(b=2)
    try: b
    except NameError: print "After makeVars: NameError"
    else: print "After makeVars: Not NameError"
    Do I really need to mention that the whole concept here is broken. This
    only works if you call it from global scope. If you call it from inside a
    function it [usually] won't work:
    def makeVars(**nameVals):
    sys._getframe(1).f_locals.update(nameVals)

    def test():
    try: b
    except NameError: print "Before makeVars: NameError"
    else: print "Before makeVars: Not NameError"
    makeVars(b=2)
    try: b
    except NameError: print "After makeVars: NameError"
    else: print "After makeVars: Not NameError"

    import sys
    test()
    Before makeVars: NameError
    After makeVars: NameError
    >>>
  • Kay Schluehr at Mar 23, 2005 at 11:43 am

    Duncan Booth wrote:

    Do I really need to mention that the whole concept here is broken. This
    only works if you call it from global scope. If you call it from inside a
    function it [usually] won't work:
    def makeVars(**nameVals):
    sys._getframe(1).f_locals.update(nameVals)

    def test():
    try: b
    except NameError: print "Before makeVars: NameError"
    else: print "Before makeVars: Not NameError"
    makeVars(b=2)
    try: b
    except NameError: print "After makeVars: NameError"
    else: print "After makeVars: Not NameError"

    import sys
    test()
    Before makeVars: NameError
    After makeVars: NameError
    Yes.

    To put it short:

    def makeVars(**nameVals):
    print "prev",sys._getframe(1).f_locals["z"]
    sys._getframe(1).f_locals.update(nameVals)
    print "post",sys._getframe(1).f_locals["z"]

    def test():
    z = 0
    makeVars(z=2)
    z = 0
    makeVars(z=3)
    prev 0
    post 3
    test()
    prev 0
    post 0


    The Python runtime uses the opcodes STORE_FAST and LOAD_FAST to
    store/access local variables of a function.

    Take a closer look at the code:

    case STORE_FAST:
    v = POP();
    SETLOCAL(oparg, v);
    goto fast_next_opcode;

    with

    register PyObject **fastlocals

    and macros

    #define GETLOCAL(i) (fastlocals[i])
    #define SETLOCAL(i, value) do { PyObject *tmp = GETLOCAL(i); \
    GETLOCAL(i) = value; \
    Py_XDECREF(tmp); } while (0)

    The local variables will be stored in the pointer array fastlocals not
    within a Python dict.

    If a variable is created as a global it will be stored using the
    STORE_NAME opcode instead:


    case STORE_NAME:
    w = GETITEM(names, oparg);
    v = POP();
    if ((x = f->f_locals) != NULL) {
    if (PyDict_CheckExact(x))
    err = PyDict_SetItem(x, w, v);
    else
    err = PyObject_SetItem(x, w, v);
    Py_DECREF(v);
    if (err == 0) continue;
    break;
    }


    which clearly accesses a Python dict for storage.


    Regards Kay
  • Ron at Mar 23, 2005 at 1:41 pm

    On 23 Mar 2005 10:13:16 GMT, Duncan Booth wrote:

    Do I really need to mention that the whole concept here is broken. This
    only works if you call it from global scope. If you call it from inside a
    function it [usually] won't work:

    That's only becuase it was asked to go up 1 frame, and not 2.


    def makeVars(**nameVals):
    sys._getframe(2).f_locals.update(nameVals) # <- get 2 frames up.


    def test():
    try: b
    except NameError: print "Before makeVars: NameError"
    else: print "Before makeVars: Not NameError"
    makeVars(b=2)
    try: b
    except NameError: print "After makeVars: NameError"
    else: print "After makeVars: Not NameError"


    import sys
    test()

    >>>
    Before makeVars: NameError
    After makeVars: Not NameError
    >>>
  • Kay Schluehr at Mar 23, 2005 at 2:31 pm

    Ron wrote:

    On 23 Mar 2005 10:13:16 GMT, Duncan Booth
    wrote:

    Do I really need to mention that the whole concept here is broken.
    This
    only works if you call it from global scope. If you call it from
    inside a
    function it [usually] won't work:

    That's only becuase it was asked to go up 1 frame, and not 2.

    def makeVars(**nameVals):
    sys._getframe(2).f_locals.update(nameVals) # <- get 2 frames up.

    def test():
    try: b
    except NameError: print "Before makeVars: NameError"
    else: print "Before makeVars: Not NameError"
    makeVars(b=2)
    try: b
    except NameError: print "After makeVars: NameError"
    else: print "After makeVars: Not NameError"


    import sys
    test()


    Before makeVars: NameError
    After makeVars: Not NameError
    That's true only because the globals are updated by {"b":2}
    two levels down.

    If You nest the test() function You reproduce the error again:

    def test():
    def inner(): try: b
    except NameError: print "Before makeVars: NameError"
    else: print "Before makeVars: Not NameError"
    makeVars(b=2)
    try: b
    except NameError: print "After makeVars: NameError"
    else: print "After makeVars: Not NameError"
    inner()


    Before makeVars: NameError
    After makeVars: NameError


    A working makeVars seems not to be different from

    def makeVars(**nameVals):
    globals().update(nameVals)


    Regards Kay
  • Duncan Booth at Mar 23, 2005 at 2:47 pm

    Kay Schluehr wrote:

    A working makeVars seems not to be different from

    def makeVars(**nameVals):
    globals().update(nameVals)
    Not quite. If Ron can come up with a working makeVars it would update the
    caller's globals whereas what you just posted updates makeVar's globals so
    there is a difference (when the makeVars and the calling function are in
    different modules), just not a very useful one.
  • Ron at Mar 23, 2005 at 10:41 pm

    On 23 Mar 2005 14:47:30 GMT, Duncan Booth wrote:

    Kay Schluehr wrote:
    A working makeVars seems not to be different from

    def makeVars(**nameVals):
    globals().update(nameVals)
    Not quite. If Ron can come up with a working makeVars it would update the
    caller's globals whereas what you just posted updates makeVar's globals so
    there is a difference (when the makeVars and the calling function are in
    different modules), just not a very useful one.
    How about this one? The only reliable way I found to do it is to
    pass locals() to the function.

    def defvalue(**args):
    args = args.items()
    a1 = args[0]
    a2 = args[1]
    if type(a1[1]) == type({}):
    vv, names = a2, a1[1]
    else:
    vv, names = a1, a2[1]
    if names.has_key(vv[0]):
    return names[vv[0]]
    return vv[1]

    f = defvalue(f=1, v=locals())
    print f # 0

    g = 19
    g = defvalue(g=2, v=locals())
    print g # 19

    z = 6
    def f1():
    #z = 4
    z = defvalue(z=3, v=locals())
    print z
    f1()
  • Duncan Booth at Mar 24, 2005 at 9:20 am

    Ron wrote:

    A working makeVars seems not to be different from

    def makeVars(**nameVals):
    globals().update(nameVals)
    Not quite. If Ron can come up with a working makeVars it would update
    the caller's globals whereas what you just posted updates makeVar's
    globals so there is a difference (when the makeVars and the calling
    function are in different modules), just not a very useful one.
    How about this one? The only reliable way I found to do it is to
    pass locals() to the function.
    Yes, but you are still missing the fundamental point. The locals()
    dictionary is not guaranteed to do anything useful if you update it. The
    current C implementation will reflect changes in the locals dictionary if
    you call locals() from global scope or in a few other circumstances, but
    this is simply an implementation detail.

    If you want to update global variables then use globals() or setattr on the
    module. Only use locals() to access local variables indirectly, never to
    try and set them.
  • Ron at Mar 24, 2005 at 5:38 pm

    On 24 Mar 2005 09:20:52 GMT, Duncan Booth wrote:

    Ron wrote:
    A working makeVars seems not to be different from

    def makeVars(**nameVals):
    globals().update(nameVals)
    Not quite. If Ron can come up with a working makeVars it would update
    the caller's globals whereas what you just posted updates makeVar's
    globals so there is a difference (when the makeVars and the calling
    function are in different modules), just not a very useful one.
    How about this one? The only reliable way I found to do it is to
    pass locals() to the function.
    Yes, but you are still missing the fundamental point. The locals()
    dictionary is not guaranteed to do anything useful if you update it. The
    current C implementation will reflect changes in the locals dictionary if
    you call locals() from global scope or in a few other circumstances, but
    this is simply an implementation detail.
    Nope, Didn't miss the point. The functions return a value, not create
    it from within.
    If you want to update global variables then use globals() or setattr on the
    module. Only use locals() to access local variables indirectly, never to
    try and set them.
    Good advise. :)

    One of pythons weak points is it is sometimes difficult to 'monitor
    and confirm' what is happening leading to confusing try/except
    constructions.

    Having the function is_defined() and if_not_defined() have the
    advantage that they can be use in expressions where try/except can't.
    And the source code could be more compact and more readable.

    The disadvantage is the functions are quite a bit slower than
    try/except, probably due to the function call over head.

    If they were built in, they may be as fast as the try/except and there
    wouldn't be issues with having to passing locals() or globals() name
    dictionaries.


    It's interesting that there is a whole is_"type"_() group of functions
    in the inspect module, but not a is_defined(). Maybe I just haven't
    found it yet.


    #############

    def if_not_defined(v, dv=None, lv=locals()):
    if lv.has_key(v):
    return lv[v]
    return dv

    def is_defined(v, lv=locals()):
    if lv.has_key(v):
    return True
    False

    # Shorten names and pass locals() with lambas for
    # convenience. (This needs to be in the function
    # where they are used or it will break.
    # Another use for lamba! ;)

    ifnd = lambda v, dv, lv=locals(): if_not_defined(v,dv,lv)
    isa = lambda v, lv=locals(): is_defined(v, lv)

    # Totally useless routine. ;)
    import random
    for n in range(10):

    # Delete a random x,y,z coordinate to
    # simulate an unreliable data source.
    d = random.choice([1,2,3])
    if d==1:
    if isa('x'): del x
    elif d==2:
    if isa('y'): del y
    else:
    if isa('z'): del z

    # Replace the missing variable with a random number.
    r = int(random.random()*100)
    x, y, z = ifnd('x',r), ifnd('y',r), ifnd('z',r)
    print x, y, z

    ###########
  • Duncan Booth at Mar 25, 2005 at 10:09 am

    Ron wrote:
    It's interesting that there is a whole is_"type"_() group of functions
    in the inspect module, but not a is_defined(). Maybe I just haven't
    found it yet.
    I've never found any need for an is_defined function. If in doubt I just
    make sure and initialise all variables to a suitable value before use.
    However, I'll assume you have a good use case.

    #############

    def if_not_defined(v, dv=None, lv=locals()):
    if lv.has_key(v):
    return lv[v]
    return dv
    I don't see the point of the default argument. locals() at the global level
    simply returns globals, so you might as well use that. A more useful
    default would be the caller's locals.
    def is_defined(v, lv=locals()):
    if lv.has_key(v):
    return True
    False
    Same comments, plus the whole 'if on a boolean to return a boolean' is a
    bit redundant.

    Try something on these lines:
    import inspect
    def is_defined(name, lv=None):
    if lv is None:
    lv = inspect.currentframe().f_back.f_locals
    return name in lv
    is_defined('abc')
    False
    abc = 3
    is_defined('abc')
    True
    def f(x):
    print is_defined('x')
    print is_defined('y')
    y = 0
    print is_defined('y')

    f(2)
    True
    False
    True
    # Shorten names and pass locals() with lambas for
    # convenience. (This needs to be in the function
    # where they are used or it will break.
    # Another use for lamba! ;)

    ifnd = lambda v, dv, lv=locals(): if_not_defined(v,dv,lv)
    isa = lambda v, lv=locals(): is_defined(v, lv)
    There is no need for lambda here, it adds nothing. Use a 'def'.
  • Ron_Adam at Mar 25, 2005 at 6:00 pm

    On 25 Mar 2005 10:09:50 GMT, Duncan Booth wrote:


    I've never found any need for an is_defined function. If in doubt I just
    make sure and initialise all variables to a suitable value before use.
    However, I'll assume you have a good use case.
    I admit that that is the better practice. George's example was the
    conversion of data from one form to another where the data is mixed
    with complete and incomplete items. And Kay is looking at tuple
    unpacking.

    It's hard to beat try/except for these situations though. :)

    I cleaned it up some more and figured out the proper use of
    _getframe(). So no lambdas, and no passing of locals needed., and it
    checks for globals and builtins before defining the default value so
    as not to over write a readable value.

    I'm not sure what the best behavior should be. Maybe a routine to
    tell where a name is, ie.. local, global, builtin, or a writable
    global? maybe isa() return the location or None.? I think that would
    be better.

    The best purpose for utilities like these is for debugging and getting
    feedback about the environment. So I'm thinking of putting them in a
    module for that purpose. I have a subroutine to list all the names
    attached to an object. I think I can add that a bit now too.


    #---Here's the code---------------------

    import sys

    def isa(v):
    """
    Check if a varable exists in the current
    (parent to this function), global, or
    builtin name spaces.

    use: bool = isa( str )
    returns True or False
    """
    plocals = sys._getframe(1).f_locals
    if plocals.has_key(v) or globals().has_key(v) or \
    __builtins__.locals().has_key(v):
    return True
    return False


    def ifno(v, obj=None):
    """
    Check if a varable does not exists, return a
    default value, otherwise return the varable obj.

    use: obj = ifno( str [,obj=None] )
    if str exist, returns str's object
    if str does not exist, returns specified object
    """
    plocals = sys._getframe(1).f_locals
    if plocals.has_key(v):
    return plocals[v]
    if globals().has_key(v):
    return globals()[v]
    if __builtins__.locals().has_key(v):
    return __builtins__.locals()[v]
    return obj


    def test():
    """
    Test isa() and ifno() functions:
    """

    # Totally useless routine. ;)
    import random
    for n in range(25):

    # Delete a random x,y,z coordinate to
    # simulate an unrealiabe data source.
    d = random.choice([1,2,3])
    if d==1:
    if isa('x'): del x
    elif d==2:
    if isa('y'): del y
    else:
    if isa('z'): del z

    # Replace the missing Varible with a random number.
    r = int(random.random()*100)
    x, y, z = ifno('x',r), ifno('y',r), ifno('z',r)
    print x, y, z


    if __name__ == '__main__':
    test()

    #-------------------------------------
  • George Sakkis at Mar 25, 2005 at 10:09 pm

    "Ron_Adam" wrote:

    On 25 Mar 2005 10:09:50 GMT, Duncan Booth
    wrote:

    I've never found any need for an is_defined function. If in doubt I just
    make sure and initialise all variables to a suitable value before use.
    However, I'll assume you have a good use case.
    I admit that that is the better practice. George's example was the
    conversion of data from one form to another where the data is mixed
    with complete and incomplete items. And Kay is looking at tuple
    unpacking.

    It's hard to beat try/except for these situations though. :)
    I posted a recipe in python cookbook
    (http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/392768) for the subproblem I was interested
    in initially (variable-length iterable unpacking), and I prefer it over explicit try/except (but of
    course I'm biased :-)). Kay is proposing something even more general and powerful, and it will be
    interesting to see if all this brainstorming can be brought forward more 'formally', e.g. at a PEP
    or pre-PEP level.

    Regards,
    George
  • Ron_Adam at Mar 26, 2005 at 3:39 am

    On Fri, 25 Mar 2005 17:09:38 -0500, "George Sakkis" wrote:

    I posted a recipe in python cookbook
    (http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/392768) for the subproblem I was interested
    in initially (variable-length iterable unpacking), and I prefer it over explicit try/except (but of
    course I'm biased :-)). Kay is proposing something even more general and powerful, and it will be
    interesting to see if all this brainstorming can be brought forward more 'formally', e.g. at a PEP
    or pre-PEP level.

    Regards,
    George
    Looks good George. :)

    I'm not sure what Kay is trying for, but it does look interesting. I'm
    all for new features as long as they are consistent and easy to use,
    and easy to remember as well. I keep finding ways to improve the
    little routines I'm playing with. ;) I'll probably post them in the
    cookbook also, and maybe put them together in a mod.

    A few more pieces and I should be able to build a name space explorer
    which I think will be good for debugging programs. I'm thinking you
    could put it in the program where you are having problems and it will
    open a tree type window where you can examine all the names and
    objects at that point. When done, close it and the programs
    continues. It will give you a little more info than sticking print
    statements hear and there.

    Ron
  • Ron at Mar 23, 2005 at 2:26 pm

    On 23 Mar 2005 10:13:16 GMT, Duncan Booth wrote:

    Do I really need to mention that the whole concept here is broken. This
    only works if you call it from global scope. If you call it from inside a
    function it [usually] won't work:
    Ok... you can get globals this way if you know how many frames up it
    is. Not terrable useful. :/


    def frame0():
    print 'frame0 (locals): ',sys._getframe(0).f_locals
    print '\nframe1 (parent): ',sys._getframe(1).f_locals
    print '\n(Global) : ',sys._getframe(2).f_locals

    def frame1():
    frame0()

    import sys
    frame1()


    >>>
    frame0 (locals): {}

    frame1 (parent): {}

    (Global) : {'__builtins__': <module '__builtin__' (built-in)>, 'sys':
    <module 'sys' (built-in)>, '__name__': '__main__', 'frame1': <function
    frame1 at 0x00B437B0>, 'frame0': <function frame0 at 0x00B43770>,
    '__doc__': None}
    >>>
  • Bruno modulix at Mar 23, 2005 at 9:44 am

    Ron wrote:
    On Tue, 22 Mar 2005 21:56:57 GMT, Ron wrote:

    Why should a function not create a local varable of an argument if the
    varable doesn't exist and a default value is given?

    ok... thought it out better. :)

    Getting a default into a function isn't the problem. Returning the
    value to a varable that doesn't exist is.

    So then the question is ... is there a way for a function to create a
    varable in it's parents namespace that persists after the function is
    done?
    yes, that'w called a global, and it's UGLY(tm)
    def yuck():
    ... global G
    ... G = 42
    ...
    G
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    NameError: name 'G' is not defined
    yuck()
    G
    42
    >>>

    Anyone doing such a thing in my team would be shoot down at once !-)

    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in 'onurb at xiludom.gro'.split('@')])"
  • Ron at Mar 22, 2005 at 1:39 pm

    On 21 Mar 2005 22:37:42 -0800, "Kay Schluehr" wrote:
    Mappings like that:

    ((x,y),z) -> x+y-z

    ((x,y=0),z) -> None

    should be valid actions too.

    What is the audience thinking about that?
    I think that there's too much implied, and that in the long run it,
    if we keep addding in special shortcuts, it will lead to very dificult
    to read code.
  • Bruno Desthuilliers at Mar 22, 2005 at 8:45 pm

    Ron a ?crit :
    On 21 Mar 2005 22:37:42 -0800, "Kay Schluehr" wrote:

    Mappings like that:

    ((x,y),z) -> x+y-z

    ((x,y=0),z) -> None

    should be valid actions too.

    What is the audience thinking about that?

    I think that there's too much implied, and that in the long run it,
    if we keep addding in special shortcuts, it will lead to very dificult
    to read code.
    Don't like Perl ?-)

    The problem here is that Kay's proposition mixes two points: flexible
    tuple unpacking and a new syntax for anonymous functions.
  • Ron at Mar 23, 2005 at 3:32 am

    On Tue, 22 Mar 2005 21:45:42 +0100, Bruno Desthuilliers wrote:

    Ron a ?crit :
    On 21 Mar 2005 22:37:42 -0800, "Kay Schluehr" <kay.schluehr at gmx.net>
    wrote:

    Mappings like that:

    ((x,y),z) -> x+y-z

    ((x,y=0),z) -> None

    should be valid actions too.

    What is the audience thinking about that?

    I think that there's too much implied, and that in the long run it,
    if we keep addding in special shortcuts, it will lead to very dificult
    to read code.
    Don't like Perl ?-)
    I tried it.. Wrote a html reformatter in it a long time ago. Wasn't
    tempted to do anything else with it. It was good for that, but I went
    a month later and had trouble figuring out how it worked. :)
    The problem here is that Kay's proposition mixes two points: flexible
    tuple unpacking and a new syntax for anonymous functions.
    Yes, two different problems. I don't think anything needs to be done
    to tuples myself. I tend to use lists more anyway.


    As far as anonymous functions go... What if there where a container
    type to hold unexecuted python code until it is asked to do it. And to
    be able to assign it a name, so it would have an object class and
    type. But be defined by like a tuple. No addition syntax to make
    things confusing.
    sum = (* a = b+c *)
    The (* and *) could be something more appropriate. As long as it's
    easy to identify and can't be confused with anything else.


    There would be an order of precedence to it also so you could do:
    my_button_action = (*a+=c (*if b:c=1 (*if not z: b=False*) *) *)
    It would execute from the inside (*_*) outward and use the local name
    space it's executed in, so no passing arguments or return values.

    Nesting and order of precedence has worked for a long time. to
    evaluate it you would need a keyword...
    newlamba my_button_action

    or this could be valid:
    newlamba (* a+=c (* if b:c=1 (* if not z:b=False *) *) *)
    or left to right order of execution:
    newlamba (* a = b+c+d, if a>limit:done=True *)
    If argument passing is really needed, I suppose there could be an
    export/inport method attached to it.
    newlamba (* sum = a+b *).import(a,b).export(sum)
    or
    newlamba (* sum = a+b *).in_out(a,b -> sum)
    newlamba my_button_action.in_out(a,b ->sum)

    A differnt name would be nice... code, docode, dothis, process... ?

    or if you require the in_out method to start it, you don't need the
    keyword.

    mybutton = (* sum = a+b *) # does not execute, but binds it to a
    b = mybutton.in_out(a,b -> sum) # This evaluates first, the sum is bound to b.
    b = (* sum = a+b *).in_out(a,b -> sum) # Is the same as above.

    Yes, there are probably loads of stuff wrong with this. ;-)

    Ron Adam

    (Looks like another Ron joined the group.)
  • Bruno modulix at Mar 23, 2005 at 9:57 am

    Ron wrote:
    On Tue, 22 Mar 2005 21:45:42 +0100, Bruno Desthuilliers
    wrote:

    Ron a ?crit :
    On 21 Mar 2005 22:37:42 -0800, "Kay Schluehr" <kay.schluehr at gmx.net>
    wrote:


    Mappings like that:

    ((x,y),z) -> x+y-z

    ((x,y=0),z) -> None

    should be valid actions too.

    What is the audience thinking about that?

    I think that there's too much implied, and that in the long run it,
    if we keep addding in special shortcuts, it will lead to very dificult
    to read code.
    Don't like Perl ?-)

    I tried it.. Wrote a html reformatter in it a long time ago. Wasn't
    tempted to do anything else with it. It was good for that, but I went
    a month later and had trouble figuring out how it worked. :)
    This was kind of rethorical question !-)
    The problem here is that Kay's proposition mixes two points: flexible
    tuple unpacking and a new syntax for anonymous functions.

    Yes, two different problems. I don't think anything needs to be done
    to tuples myself. I tend to use lists more anyway.
    They are two different beasts. Note that you don't have anything like
    list unpacking, now tuple unpacking is pretty common in Python (swap,
    multiple return values, formatted strings and outputs, ...).
    As far as anonymous functions go...
    (snip prospective code)

    Yes, there are probably loads of stuff wrong with this. ;-)
    Err... Isn't it a bit more complicated than our actual lambdas ?-)

    --
    bruno desthuilliers
    ruby -e "print 'onurb at xiludom.gro'.split('@').collect{|p|
    p.split('.').collect{|w| w.reverse}.join('.')}.join('@')"
  • George Sakkis at Mar 23, 2005 at 6:52 pm
    "bruno modulix" wrote: in message news:42413d90$0$1618$636a15ce at news.free.fr...
    Ron wrote:
    The problem here is that Kay's proposition mixes two points: flexible
    tuple unpacking and a new syntax for anonymous functions.

    Yes, two different problems. I don't think anything needs to be done
    to tuples myself. I tend to use lists more anyway.
    They are two different beasts. Note that you don't have anything like
    list unpacking, now tuple unpacking is pretty common in Python (swap,
    multiple return values, formatted strings and outputs, ...).
    All the following are possible:
    (x,y,z) = (1,2,3)
    (x,y,z) = [1,2,3]
    [x,y,z] = (1,2,3)
    [x,y,z] = [1,2,3]
    What exactly do you mean by "don't have anything like list unpacking" ?

    George
  • Bruno modulix at Mar 24, 2005 at 9:20 am

    George Sakkis wrote:
    "bruno modulix" wrote: in message news:42413d90$0$1618$636a15ce at news.free.fr...
    (snip)
    Note that you don't have anything like
    list unpacking, now tuple unpacking is pretty common in Python (swap,
    multiple return values, formatted strings and outputs, ...).

    All the following are possible:

    (x,y,z) = (1,2,3)
    (x,y,z) = [1,2,3]
    [x,y,z] = (1,2,3)
    [x,y,z] = [1,2,3]

    What exactly do you mean by "don't have anything like list unpacking" ?
    A stupidity :(

    --
    bruno desthuilliers
    ruby -e "print 'onurb at xiludom.gro'.split('@').collect{|p|
    p.split('.').collect{|w| w.reverse}.join('.')}.join('@')"
  • Diez B. Roggisch at Mar 22, 2005 at 1:48 pm

    letting tuples-like objects (x,y,z=0) acting as functions on other
    tuples I wonder why this would not be a good starting point of
    rethinking anonymus functions?

    In Georges proposition the action is

    (x,y,z=0) -> (x,y,z)

    i.e. mapping tuples on other tuples. This is equivalent to

    lambda x,y,z=0:(x,y,z)
    As you say for yourself, that's just lambda in disguise. So I guess the same
    arguments about the in- or exclusion of lambda apply here. I personally
    like lambda, but _can_ live without it.

    --
    Regards,

    Diez B. Roggisch
  • Bruno modulix at Mar 22, 2005 at 4:07 pm

    Diez B. Roggisch wrote:
    letting tuples-like objects (x,y,z=0) acting as functions on other
    tuples I wonder why this would not be a good starting point of
    rethinking anonymus functions?

    In Georges proposition the action is

    (x,y,z=0) -> (x,y,z)

    i.e. mapping tuples on other tuples. This is equivalent to

    lambda x,y,z=0:(x,y,z)

    As you say for yourself, that's just lambda in disguise.
    Not exactly in fact - unless I messed something. There are 2 problems
    here: a more flexible tuple unpacking, *and* a lambda in disguise.
    Actually, I'd go + 1 for the first, -1 for the second
    So I guess the same
    arguments about the in- or exclusion of lambda apply here.
    For the second part, yes. Not for the first one.
    I personally
    like lambda, but _can_ live without it.
    Yes, one can live without...
    <troll>
    ...and without list comprehensions, __call__ and other special methods,
    descriptors, metaclasses, first class functions, builtin datatypes like
    lists and dicts, exceptions, dynamic typing, garbage collection, etc
    too. Hurray, let's all happily program in assembly !-)
    </troll>

    --
    bruno desthuilliers
    ruby -e "print 'onurb at xiludom.gro'.split('@').collect{|p|
    p.split('.').collect{|w| w.reverse}.join('.')}.join('@')"
  • Diez B. Roggisch at Mar 22, 2005 at 4:42 pm

    Not exactly in fact - unless I messed something. There are 2 problems
    here: a more flexible tuple unpacking, *and* a lambda in disguise.
    Actually, I'd go + 1 for the first, -1 for the second
    The proposed syntax from Kay is lambda in disguise. To make it work like
    George want it is modifying the unpacking behaviour. Actually while Kay
    proposed his syntax as result of the discussion started by George it won't
    work for that case. The reason is simply that the lambda form returns a
    tuple, but does not make any revelations about the variable names that
    tuple shall be unpacked to.

    So they are in fact unrelated - at least if introduced as declared. An
    augmentation to fulfill George's wishes could look like this:

    [a,b,c for a,b,c: (x,y,z=0)-> x,y,z) in values]
    Yes, one can live without...
    <troll>
    ...and without list comprehensions, __call__ and other special methods,
    descriptors, metaclasses, first class functions, builtin datatypes like
    lists and dicts, exceptions, dynamic typing, garbage collection, etc
    too. Hurray, let's all happily program in assembly !-)
    </troll>
    You are right, but for lambda in its current limited form short, named
    functions are a good replacement. I don't want to get rid of lambda - but
    since listcomps got introduced, 95% of my usages of them disappeared.

    --
    Regards,

    Diez B. Roggisch
  • Bruno Desthuilliers at Mar 22, 2005 at 8:53 pm
    Diez B. Roggisch a ?crit :
    (snip)
    You are right, but for lambda in its current limited form short, named
    functions are a good replacement.
    -inf on this !-)
  • Antoon Pardon at Mar 23, 2005 at 8:31 am

    Op 2005-03-22, Diez B. Roggisch schreef <deetsNOSPAM at web.de>:
    Not exactly in fact - unless I messed something. There are 2 problems
    here: a more flexible tuple unpacking, *and* a lambda in disguise.
    Actually, I'd go + 1 for the first, -1 for the second
    The proposed syntax from Kay is lambda in disguise. To make it work like
    George want it is modifying the unpacking behaviour. Actually while Kay
    proposed his syntax as result of the discussion started by George it won't
    work for that case. The reason is simply that the lambda form returns a
    tuple, but does not make any revelations about the variable names that
    tuple shall be unpacked to.

    So they are in fact unrelated - at least if introduced as declared. An
    augmentation to fulfill George's wishes could look like this:

    [a,b,c for a,b,c: (x,y,z=0)-> x,y,z) in values]
    Yes, one can live without...
    <troll>
    ...and without list comprehensions, __call__ and other special methods,
    descriptors, metaclasses, first class functions, builtin datatypes like
    lists and dicts, exceptions, dynamic typing, garbage collection, etc
    too. Hurray, let's all happily program in assembly !-)
    </troll>
    You are right, but for lambda in its current limited form short, named
    functions are a good replacement. I don't want to get rid of lambda - but
    since listcomps got introduced, 95% of my usages of them disappeared.
    I don't understand why people always say short named functions are a
    good replacement. IMO list comprehensions and generator expressions
    use lambda's in disguise. When we write something like
    [x * x for x in some_iterator], nobody seems to have problems that
    we just write an expression here and nobody is argueing that we
    should define a short function. However when people need the
    same kind of semantics in their function, being an expression that
    is being reevaluated with different values, for which lambda is the
    natural candidate, suddenly we should use short named functions.

    Can someone who thinks this way, please explain why this is acceptable

    [ x * x for x in some_iterator ]

    But this is not

    map(lambda x: x * x, some_iteraror)

    and should be replaced with

    def sqr(x): return x * x
    map(sqr , some_iterator)

    --
    Antoon Pardon
  • Diez B. Roggisch at Mar 23, 2005 at 11:06 am

    Can someone who thinks this way, please explain why this is acceptable

    [ x * x for x in some_iterator ]

    But this is not

    map(lambda x: x * x, some_iteraror)

    and should be replaced with

    def sqr(x): return x * x
    map(sqr , some_iterator)
    It shouldn't, it should be replaced with the listcomp. And IMHO it results
    in better readable code.

    AFAIK the reason people say you should use named functions is _not_ because
    of these single expression replacements. The reason is that frequently
    people complain about lambda being so restrictive so that you can't write

    lambda x,y: if x > 100: x else: y

    and want to _extend_ lambda beyond its current capabilities and make it full
    featured but anonymous functions.

    And these requests are rebuked with the argument that having to give a more
    complex function a name instead of declaring it anonymously doesn't cost
    you much - especially since you can declare them inside other functions so
    the global namespace isn't cluttered.

    I have to admit that rereading my statement

    """
    You are right, but for lambda in its current limited form short, named
    functions are a good replacement
    """

    is not really what I wanted to say.

    I should have written:

    """
    for lambda in its current limited form, listcomprehensions often are a good
    replacement.
    """

    But as I've said various times before: I personally don't mind lambdas and
    for example the reduce function has been useful for me quite a few times,
    can't be replaced by listcomps, and frequently needs a callable consisting
    of only a single expression. So I'll continue to use lambdas there.

    --
    Regards,

    Diez B. Roggisch
  • Antoon Pardon at Mar 23, 2005 at 12:07 pm

    Op 2005-03-23, Diez B. Roggisch schreef <deetsNOSPAM at web.de>:
    Can someone who thinks this way, please explain why this is acceptable

    [ x * x for x in some_iterator ]

    But this is not

    map(lambda x: x * x, some_iteraror)

    and should be replaced with

    def sqr(x): return x * x
    map(sqr , some_iterator)
    It shouldn't, it should be replaced with the listcomp. And IMHO it results
    in better readable code.
    This misses the point. The fact that map and the listcomprehension do
    the same stuff is just a detail. It is about giving a function an
    expression as argument that is to be evaluated multiple times.
    AFAIK the reason people say you should use named functions is _not_ because
    of these single expression replacements. The reason is that frequently
    people complain about lambda being so restrictive so that you can't write

    lambda x,y: if x > 100: x else: y

    and want to _extend_ lambda beyond its current capabilities and make it full
    featured but anonymous functions.
    This is one kind of people. An other kind of people seems to want to
    get rid of lamda's altogether and asks whether it is so difficult
    to make a named function each time you would otherwise use a lambda.
    But as I've said various times before: I personally don't mind lambdas and
    for example the reduce function has been useful for me quite a few times,
    can't be replaced by listcomps, and frequently needs a callable consisting
    of only a single expression. So I'll continue to use lambdas there.
    Then my question was not meant for you.

    --
    Antoon Pardon
  • Julian Smith at Mar 23, 2005 at 6:16 pm

    On 23 Mar 2005 08:31:36 GMT Antoon Pardon wrote:

    Can someone who thinks this way, please explain why this is acceptable

    [ x * x for x in some_iterator ]

    But this is not

    map(lambda x: x * x, some_iteraror)

    and should be replaced with

    def sqr(x): return x * x
    map(sqr , some_iterator)
    I guess I have similar feelings.

    I've only been using python for a year or two, so I'm still a relative
    newcomer.

    Like a lot of people, I found Python to be magically simple and intuitive.

    But I've never really found list comprehensions particularly clear. I don't
    know whether it's my backgroud (mainly C/C++), or my brain or what, but they
    are probably the only thing in Python that hasn't seemed transparent and
    obvious to me (apart from shadowing of variables in nested functions).

    Of course, I'm sure I could get used to them, given time. But that rather
    defeats one of the main reasons for using python in the first place - the
    lack of a steep learning curve.

    In contrast, I find lambdas, even with their significant restrictions, to be
    much more obvious. In fact, the proposal (sorry, don't have a link to hand)
    about extending lambda to allow things like `myfn = def <indented block>' was
    something that I initially assumed would become part of the language in time.

    Is there some definitive information that explains why python is moving away
    from lambdas and towards things like list comprehensions?

    - Julian
  • Claudio Grondi at Mar 22, 2005 at 9:41 am
    For me, one of the reasons for using Python
    is the ease and the intuivity of reading its
    code.
    I have a problem with intuitively getting
    what is going on when using a pattern like
    (x,y,z=0) -> (x,y,z)
    where I expect at the first glance some
    C code with access to class members.
    At least I must start looking at the code
    more closely thinking why is someone
    using such a construct.

    Already
    lambda x,y,z=0:(x,y,z)
    is a problem for me.

    Why not:
    try:
    (x,y,z)
    except NameError:
    z=0
    (x,y,z)
    ?

    Watching the last piece of code
    can even directly be seen, that there
    is eventually a NameError
    problem with z to handle,
    so where is the gain of using
    lambda or the mapping?

    My current conclusion (I can't see any gain):

    No, thanks.

    Claudio


    "Kay Schluehr" <kay.schluehr at gmx.net> schrieb im Newsbeitrag
    news:1111473420.674542.209610 at z14g2000cwz.googlegroups.com...
    Since George Sakkis proposed a new way of doing list comprehensions

    http://groups-beta.google.com/group/comp.lang.python/browse_frm/thread/ac5023ad18b2835f/d3ff1b81fa70c8a7#d3ff1b81fa70c8a7
    letting tuples-like objects (x,y,z=0) acting as functions on other
    tuples I wonder why this would not be a good starting point of
    rethinking anonymus functions?

    In Georges proposition the action is

    (x,y,z=0) -> (x,y,z)

    i.e. mapping tuples on other tuples. This is equivalent to

    lambda x,y,z=0:(x,y,z)

    But regarding tuples as actions by means of an arrow "->" would
    generalize this idea:

    Mappings like that:

    ((x,y),z) -> x+y-z

    ((x,y=0),z) -> None

    should be valid actions too.

    What is the audience thinking about that?

    Regards Kay
  • Antoon Pardon at Mar 22, 2005 at 9:53 am

    Op 2005-03-22, Claudio Grondi schreef <claudio.grondi at freenet.de>:
    For me, one of the reasons for using Python
    is the ease and the intuivity of reading its
    code.
    I have a problem with intuitively getting
    what is going on when using a pattern like
    (x,y,z=0) -> (x,y,z)
    where I expect at the first glance some
    C code with access to class members.
    At least I must start looking at the code
    more closely thinking why is someone
    using such a construct.

    Already
    lambda x,y,z=0:(x,y,z)
    is a problem for me.

    Why not:
    try:
    (x,y,z)
    except NameError:
    z=0
    (x,y,z)
    ?
    Because they are not equivallent.
    Watching the last piece of code
    can even directly be seen, that there
    is eventually a NameError
    problem with z to handle,
    And suppose there is a NameError with x,
    your piece of code will then assign 0 to
    z. Do you think that is what the original
    code wanted?
    so where is the gain of using
    lambda or the mapping?
    Is is usable as an argument.

    --
    Antoon Pardon
  • Claudio Grondi at Mar 22, 2005 at 12:47 pm

    Already
    lambda x,y,z=0:(x,y,z)
    is a problem for me.

    Why not:
    try:
    (x,y,z)
    except NameError:
    z=0
    (x,y,z)
    ?
    Because they are not equivallent.
    Watching the last piece of code
    can even directly be seen, that there
    is eventually a NameError
    problem with z to handle,
    And suppose there is a NameError with x,
    your piece of code will then assign 0 to
    z. Do you think that is what the original
    code wanted?
    Ok, I see.
    But inspite of the fact, that I have
    overseen this while writing the
    code, this bad assignment won't
    much matter, because the script will fail
    anyway in (x,y,z), so there will be no
    effect on the subsequent code.

    If I had written:
    try:
    z
    except NameError:
    z=0
    #:try/except
    (x,y,z)
    I would be closer to the original
    idea behind
    lambda x,y,z=0:(x,y,z)
    right?
    [lambda] It is usable as an argument.
    I have to admit, that I still don't understand
    the concept behind lambda, because this
    construct in new to me. Maybe it is because
    I still haven't seen any example making it
    clear, why lambda is the only or at least
    the better way to go.

    Even if I am very interested in understanding
    and discussing lambda related matters here,
    I see, that with discussing it we are probably
    far away from the original intent of Kay who
    expects in this thread postings expressing
    an opinion about introduction of the
    (x,y,z=0) -> (x,y,z)
    construct in Python.

    Claudio
  • Bruno modulix at Mar 22, 2005 at 10:12 am

    Claudio Grondi wrote:
    For me, one of the reasons for using Python
    is the ease and the intuivity of reading its
    code.
    I guess this is true for many of us. Now 'ease and intuitivity' stronly
    depends on one's background...
    I have a problem with intuitively getting
    what is going on when using a pattern like
    (x,y,z=0) -> (x,y,z)
    where I expect at the first glance some
    C code with access to class members.
    <pedantic>
    There are nothing like a class or a class member in C.
    </pedantic>
    At least I must start looking at the code
    more closely thinking why is someone
    using such a construct.
    Already
    lambda x,y,z=0:(x,y,z)
    is a problem for me.
    Not for me. It's clearly a function that takes 2 mandatory and one
    optional argument (which default to 0), and returns a tuple of it's
    argument.

    it's named equivalent is:
    def make_three_tuple(x, y, z=0):
    return (x, y, z)
    Why not:
    try:
    (x,y,z)
    except NameError:
    z=0
    (x,y,z)
    ?
    Because it does not do the same thing ?-)

    Because, if it did, it would still require 5 times more lines of code to
    do the same thing (hence it's more error-prone by a factor a 5) ?

    Because it uses an exception, which is far less efficient than using a
    default argument ?

    Because the name error could be on x and/or y too, and the try:except
    clause would hide it ?

    I stop here, but I think I could think of more good (IMHO) reason to
    prefer the lambda form.
    Watching the last piece of code
    can even directly be seen, that there
    is eventually a NameError
    problem with z to handle,
    No. AFAICT, the name error could be with x and/or y and/or z.
    so where is the gain of using
    lambda or the mapping?
    See upper...

    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in 'onurb at xiludom.gro'.split('@')])"
  • Claudio Grondi at Mar 22, 2005 at 12:21 pm

    Why not:
    try:
    (x,y,z)
    except NameError:
    z=0
    (x,y,z)
    ?
    instead of
    lambda x,y,z=0:(x,y,z)
    Because it does not do the same thing ?-)
    Haven't got the idea why? (<pedantic?>)
    Because, if it did, it would still require 5 times more lines of code to
    do the same thing (hence it's more error-prone by a factor a 5) ?
    I don't like to mix the idea of compression
    with the idea of programming. The amount
    of code doesn't matter much to me,
    when readability suffers. This becomes
    obvious, when one skips any comments and
    name all variables with two letter codes
    in the script, making it much more
    compact.
    By the way, I could also write:

    try:(x,yz)
    except NameError:z=0;(x,y,z)

    reducing the number of lines to two,
    but I don't, because in my eyes
    I can read the code better if
    spread over five lines and because
    of this, the code becomes in my
    opinion even less error-prone.
    Actually I would write in my code:
    try:
    (x,y,z)
    except NameError:
    z=0
    (x,y,z)
    #:try/except
    inreasing the number of lines to
    six in order to see directly, where
    the end of try:/except construct is.
    Because it uses an exception, which is far less efficient than using a
    default argument ?
    Efficiency is not the key point for me.
    If I need efficiency I go to C(C++) anyway.
    From my past experience I know, that
    defaults lead very often to problems,
    because one tends to forget, that there
    is a default value and is confused by
    the outcome in which values not
    explicitly mentioned in the
    code occure, leading to deep
    confusion (especially if hidden in
    modules and libraries).
    So I try to avoid defaults where it
    is possible, using them if they don't
    harm the outcome i.e. are related to
    internal way of processing within
    a function or are really obvious
    and can be expected.

    If the exception is the problem, why not
    setting somewhere at the early beginning
    of the code
    z=0
    and then use
    (x,y,z)
    ?
    Does the lambda in this case just not
    try to get straight what was caused by
    the bad concept and therefore bad
    design of the script code flow?
    Because the name error could be on x and/or y too, and the try:except
    clause would hide it ?
    I can't see why try:except hides it?
    at least at the next line with
    (x,y,z)
    the problem with x or y will cause
    an error.
    Watching the last piece of code
    can even directly be seen, that there
    is eventually a NameError
    problem with z to handle,
    No. AFAICT, the name error could be with x and/or y and/or z.
    see upper.
    so where is the gain of using
    lambda or the mapping?
    Sorry, but I still can't see the advantage
    of lambda, at least not in this example.

    Claudio
  • Antoon Pardon at Mar 22, 2005 at 1:09 pm

    Op 2005-03-22, Claudio Grondi schreef <claudio.grondi at freenet.de>:
    reducing the number of lines to two,
    but I don't, because in my eyes
    I can read the code better if
    spread over five lines and because
    of this, the code becomes in my
    opinion even less error-prone.
    Actually I would write in my code:
    try:
    (x,y,z)
    except NameError:
    z=0
    (x,y,z)
    #:try/except
    inreasing the number of lines to
    six in order to see directly, where
    the end of try:/except construct is.
    Because it uses an exception, which is far less efficient than using a
    default argument ?
    Efficiency is not the key point for me.
    If I need efficiency I go to C(C++) anyway.
    From my past experience I know, that
    defaults lead very often to problems,
    because one tends to forget, that there
    is a default value and is confused by
    the outcome in which values not
    explicitly mentioned in the
    code occure, leading to deep
    confusion (especially if hidden in
    modules and libraries).
    So I try to avoid defaults where it
    is possible, using them if they don't
    harm the outcome i.e. are related to
    internal way of processing within
    a function or are really obvious
    and can be expected.

    If the exception is the problem, why not
    setting somewhere at the early beginning
    of the code
    z=0
    and then use
    (x,y,z)
    ?
    Because that wouldn't work with the kind
    of code that was being discussed being:

    for x,y,z in some_iterator:

    If some_iterator produces at some time
    a tuple with only two elements this
    will raise an exception no matter
    whether you assigned z already or not.

    Does the lambda in this case just not
    try to get straight what was caused by
    the bad concept and therefore bad
    design of the script code flow?
    Why should we assume the concept or design
    was bad? Suppose we have an algoritme
    that works with 3d points. Now we find
    out the algorithm works equally fine
    with 2d points if we assume this 2d
    points lie in the z plane. Wouldn't
    giving z the value 0 in the case of
    only two elements perfectly allow us
    to use this 3d algorthm with 2d points?

    Just because you can't imagine were this
    would be helpfull doesn't make it a
    bad concept or design.
    so where is the gain of using
    lambda or the mapping?
    Sorry, but I still can't see the advantage
    of lambda, at least not in this example.
    The lambda would allow us to insert the
    functionallity locally without the need
    to an function that is define somewhere
    else.

    --
    Antoon Pardon
  • Claudio Grondi at Mar 22, 2005 at 3:59 pm

    for x,y,z in some_iterator:

    If some_iterator produces at some time
    a tuple with only two elements this
    will raise an exception no matter
    whether you assigned z already or not.
    So if I now understand it right, the core
    of the whole proposal is to find a way to
    make unpacking of tuples work also in case
    the tuples have not the appropriate
    number of elements, right?

    So to achieve the same effect I need
    currently (not tested):

    for x,y,z in [getMyTargetTupleFrom(currentTuple) for currentTuple in
    tupleList]

    where getMyTargetTupleFrom(currentTuple) is:

    def getMyTargetTupleFrom(currentTuple):
    if len(currentTuple) >= 3:
    return (currentTuple[0], currentTuple[1], currentTuple[2])
    if len(currentTuple) == 2:
    return (currentTuple[0], currentTuple[1], 0)

    right?

    Is it really worth it?
    Isn't it much easier to convert the list of tuples
    explicit to appropriate format, first?

    It seems, that my attitude to the proposal
    is originated from bad experience with
    default values.

    To get it tracked down to the point:

    In my opinion default values are evil and it
    is enough trouble that function defintions
    allow them.
    I have seen already postings
    of confused newbies expecting the
    default values beeing set during
    function execution not during
    definition and I have also faced
    this problem starting on Python
    myself .

    Claudio
  • Bruno modulix at Mar 22, 2005 at 4:02 pm

    Claudio Grondi wrote:
    for x,y,z in some_iterator:

    If some_iterator produces at some time
    a tuple with only two elements this
    will raise an exception no matter
    whether you assigned z already or not.

    So if I now understand it right, the core
    of the whole proposal is to find a way to
    make unpacking of tuples work also in case
    the tuples have not the appropriate
    number of elements, right?
    That's the original problem at least. Kay seems to be wanting to extend
    a possible solution to this problem to a lambda replacement, which is
    IMHO another point.
    So to achieve the same effect I need
    currently (not tested):

    for x,y,z in [getMyTargetTupleFrom(currentTuple) for currentTuple in
    tupleList]

    where getMyTargetTupleFrom(currentTuple) is:

    def getMyTargetTupleFrom(currentTuple):
    if len(currentTuple) >= 3:
    return (currentTuple[0], currentTuple[1], currentTuple[2])
    if len(currentTuple) == 2:
    return (currentTuple[0], currentTuple[1], 0)

    right? Yes
    Is it really worth it?
    I think so. The problem of "unpacking tuple of the wrong size" is a
    common one (at least for me), and having to write a special function to
    handle the case, or use try:except blocks, dont make for more readable
    code IMHO. The possibility to clearly and cleanly handle the case *when
    it's an expected case* and *as close as possible* to where it happens
    would (always IMHO) improve readability.

    What do you find most readable: your version, with an ad-hoc function
    defined somewhere else, far away in the code, or a simpler:
    for (x,y,z=0) in tupleList:
    do_whatever_with_it()
    Isn't it much easier to convert the list of tuples
    explicit to appropriate format, first?
    This *is* an explicit conversion. Much more explicit than a function
    buried xxx lines of code away IMHO. (and BTW, It also avoid to have to
    build two lists.)
    It seems, that my attitude to the proposal
    is originated from bad experience with
    default values.

    To get it tracked down to the point:

    In my opinion default values are evil and it
    is enough trouble that function defintions
    allow them.
    Python would barely be usable without.
    I have seen already postings
    of confused newbies expecting the
    default values beeing set during
    function execution not during
    definition and I have also faced
    this problem starting on Python
    myself .
    There are a lot of features in any language that are at first sight
    confusing, specially when these features look like features existing in
    another language but fail to behave like in the other language.

    <half-troll>
    Removing anything that could confuse anyone having only experience with
    language X or Y leads to Java - an average language designed for average
    programmers, where the lack of expressive power leads to overly
    complicated code to get simple things done.
    </half-troll>

    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in 'onurb at xiludom.gro'.split('@')])"
  • Claudio Grondi at Mar 22, 2005 at 6:34 pm

    What do you find most readable: your version, with an ad-hoc function
    defined somewhere else, far away in the code, or a simpler:
    for (x,y,z=0) in tupleList:
    do_whatever_with_it()
    I came up with the "ad-hoc function"
    to give a kind of replacement
    for the used syntax, in order
    not to ask why not immediately:
    for tuple in tupleList:
    do_whatever_with_it()
    ?

    Sure I like the syntax as long as
    I think in terms of unpacking
    tuples, but at the first glance
    I thought that the intention
    was to get only x, y from the tuple
    setting all z in the yielded tuples
    to zero (as suggested in this
    thread by giving the example of
    going from 3D down to 2D where
    with all z=0 the algorithm will
    remain the same).
    What about
    "for (x,y,if z not in tupleList: z=0 else: z=1) in tupleList"
    ?

    What if the tupleList is empty?
    Should existing z be set to zero
    or not after the line with the
    for loop was executed?

    Should
    for (,y) in tupleList:
    do_whatever_with_it()
    give only the y and
    for (,,z) in tupleList:
    only the z values?

    If it should become possible to
    use the "for (x,y,z=0) in tupleList"
    syntax, I would sure like also to have:
    "for (,,z) in tupleList"

    "for (x,y,if z not in tupleList: z=0 else: z=1) in tupleList"
    "for (x,y,if z not in tupleList: z=0 else: z=2*x*z) in tupleList"
    and sure also:
    "for (x,y,z=0, *r) in tupleList"
    etc.

    My only objections are:

    Is it worth the effort?
    Would it not be confusing?

    Maybe starting with e.g. a
    xlistcomprehension
    module where
    xlistcomprehension.execute(
    "[for (x,y,if z not in tupleList: z=0 else: z=1) in tupleList]"
    )
    or just xl(...) to keep it short
    provides the desired functionality
    is a good idea?
    Then it can be seen if this module
    becomes widely used and therefore
    worth to be integrated?

    I think it would be nice to have, but I
    can't imagine it to be really very helpful.

    It is sure a long way before the concept
    of it becomes so mature, that all who
    see it say:
    Wow, why was it not from the very
    beginning there?

    Claudio
  • Bruno modulix at Mar 22, 2005 at 5:56 pm

    Claudio Grondi wrote:
    What do you find most readable: your version, with an ad-hoc function
    defined somewhere else, far away in the code, or a simpler:
    for (x,y,z=0) in tupleList:
    do_whatever_with_it()

    I came up with the "ad-hoc function"
    to give a kind of replacement
    for the used syntax, in order
    not to ask why not immediately:
    for tuple in tupleList:
    do_whatever_with_it()
    ?
    What if do_whatever_with_it() waits for a triplet, we have a list of
    mixed pairs and triplets, and augmenting pairs with a 0 would do for us?

    As I said, there's always a way to do it as long as the language is
    turing complete. The problem is with is of use and readiblity -
    expressive power - which, I agree, is at least somewhat subjective !-)
    Sure I like the syntax as long as
    I think in terms of unpacking
    tuples, but at the first glance
    I thought that the intention
    was to get only x, y from the tuple
    setting all z in the yielded tuples
    to zero (as suggested in this
    thread by giving the example of
    going from 3D down to 2D where
    with all z=0 the algorithm will
    remain the same).
    What about
    "for (x,y,if z not in tupleList: z=0 else: z=1) in tupleList"
    ?
    Should be:
    for x, y, if [???]:z=0 else:z=1 in tupleList:
    # etc

    This Would do for me. But since we're not going to have a ternary
    woperator (or everything's-an-expression for that matter)...
    What if the tupleList is empty?
    No iteration.
    Should existing z be set to zero
    or not after the line with the
    for loop was executed?
    should follow the same rule as for other vars.
    Should
    for (,y) in tupleList:
    do_whatever_with_it()
    give only the y and
    for (,,z) in tupleList:
    only the z values?
    Don't know. Didn't think of it.

    If it should become possible to
    use the "for (x,y,z=0) in tupleList"
    syntax, I would sure like also to have:
    "for (,,z) in tupleList"
    Sounds coherent... but then you already have:
    for dont_care, ignore, y in tupleList:
    # etc
    "for (x,y,if z not in tupleList: z=0 else: z=1) in tupleList"
    "for (x,y,if z not in tupleList: z=0 else: z=2*x*z) in tupleList"
    and sure also:
    "for (x,y,z=0, *r) in tupleList"
    etc.

    My only objections are:

    Is it worth the effort?
    Would it not be confusing?

    Maybe starting with e.g. a
    xlistcomprehension
    module where
    xlistcomprehension.execute(
    "[for (x,y,if z not in tupleList: z=0 else: z=1) in tupleList]"
    )
    or just xl(...) to keep it short
    provides the desired functionality
    is a good idea?
    Then it can be seen if this module
    becomes widely used and therefore
    worth to be integrated?
    I don't think this would be possible. What is proposed requires
    modification to the language itself AFAICT.
    I think it would be nice to have, but I
    can't imagine it to be really very helpful.
    I once had the same feeling about first class functions, higher-order
    functions, lambdas, list comprehension, __call__ special method,
    descriptors, metaclasses, and a whole lot of other constructs for that
    matter. Now I woul be very unhappy not to have them !-)

    Regards,
    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in 'onurb at xiludom.gro'.split('@')])"
  • Elbertlev at Mar 23, 2005 at 4:25 am
    Please do not change the syntax. Better focus on the library.

    1. There are already 3 constructs right now for this problem.
    2. List comprehensions are used mostly in examples. At least I came to
    such conclusion reading the standard library modules.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedMar 22, '05 at 6:37a
activeMar 26, '05 at 3:39a
posts50
users11
websitepython.org

People

Translate

site design / logo © 2022 Grokbase