Postpone evaluation of argument

Discussion in 'Python' started by Righard van Roy, Feb 10, 2012.

  1. Hello,

    I want to add an item to a list, except if the evaluation of that item
    results in an exception.
    I could do that like this:

    def r(x):
    if x > 3:
    raise(ValueError)

    try:
    list.append(r(1))
    except:
    pass
    try:
    list.append(r(5))
    except:
    pass

    This looks rather clumbsy though, and it does not work with i.e. list
    comprehensions.

    I was thinking of writing a decorator like this:

    def tryAppendDecorator(fn):
    def new(*args):
    try:
    fn(*args)
    except:
    pass
    return new

    @tryAppendDecorator
    def tryAppend(list, item):
    list.append(item)

    tryAppend(list, r(1))
    tryAppend(list, r(5))

    This does not work however because the 'item' argument gets evaluated
    before the decorator does it's magic.

    Is there a way to postpone the evaluation of 'item' till it gets used
    inside the decorator. Like it is possible to quote a form in Lisp.

    Thank you,
    Righard
     
    Righard van Roy, Feb 10, 2012
    #1
    1. Advertising

  2. Righard van Roy

    Paul Rubin Guest

    Righard van Roy <> writes:
    > I want to add an item to a list, except if the evaluation of that item
    > results in an exception.


    This may be overkill and probably slow, but perhaps most in the spirit
    that you're asking.

    from itertools import chain

    def r(x):
    if x > 3:
    raise(ValueError)
    return x

    def maybe(func):
    try:
    yield func()
    except:
    return

    def p(i): return maybe(lambda: r(i))

    your_list = list(chain(p(1), p(5)))
    print your_list
     
    Paul Rubin, Feb 10, 2012
    #2
    1. Advertising

  3. Righard van Roy writes:

    > Hello,
    >
    > I want to add an item to a list, except if the evaluation of that item
    > results in an exception.
    > I could do that like this:
    >
    > def r(x):
    > if x > 3:
    > raise(ValueError)
    >
    > try:
    > list.append(r(1))
    > except:
    > pass
    > try:
    > list.append(r(5))
    > except:
    > pass
    >
    > This looks rather clumbsy though, and it does not work with i.e. list
    > comprehensions.
    >
    > I was thinking of writing a decorator like this:
    >
    > def tryAppendDecorator(fn):
    > def new(*args):
    > try:
    > fn(*args)
    > except:
    > pass
    > return new
    >
    > @tryAppendDecorator
    > def tryAppend(list, item):
    > list.append(item)
    >
    > tryAppend(list, r(1))
    > tryAppend(list, r(5))
    >
    > This does not work however because the 'item' argument gets evaluated
    > before the decorator does it's magic.
    >
    > Is there a way to postpone the evaluation of 'item' till it gets used
    > inside the decorator. Like it is possible to quote a form in Lisp.


    That's not considered good practice in Lisp either. One would use a
    lambda expression to delay the computation, as others have suggested.

    You might be able to arrange your program so that tryAppend is called
    with the error-raising function and its arguments separately. I mean
    like this:

    def r(x):
    if x > 3:
    raise(ValueError)
    return x

    def tryAppendDecorator(fn):
    def new(xs, f, *args):
    try:
    fn(xs, f(*args))
    except:
    pass
    return new

    @tryAppendDecorator
    def tryAppend(items, item):
    items.append(item)

    sub3 = []
    tryAppend(sub3, r, 3)
    tryAppend(sub3, r, 1)
    tryAppend(sub3, r, 4)
    tryAppend(sub3, r, 1)
    tryAppend(sub3, r, 5)

    Maybe you should only ignore some specific type of exception, like
    ValueError if you are specifically using r as a filter whose task it
    is to raise a ValueError.
     
    Jussi Piitulainen, Feb 11, 2012
    #3
  4. 在 2012å¹´2月11日星期六UTC+8上åˆ7æ—¶57分56秒,Paul Rubin写é“:
    > Righard van Roy
    > writes:
    > > I want to add an item to a list, except if the evaluation of that item
    > > results in an exception.

    >
    > This may be overkill and probably slow, but perhaps most in the spirit
    > that you're asking.
    >
    > from itertools import chain
    >
    > def r(x):
    > if x > 3:
    > raise(ValueError)
    > return x
    >
    > def maybe(func):
    > try:
    > yield func()
    > except:
    > return
    >

    I am wondering at which level to yield in a nested decorated function
    is more controllable.

    It is definitely wrong to yield in manny levels decorated.


    > def p(i): return maybe(lambda: r(i))
    >
    > your_list = list(chain(p(1), p(5)))
    > print your_list
     
    88888 Dihedral, Feb 11, 2012
    #4
    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. Replies:
    0
    Views:
    359
  2. Ilias Lazaridis
    Replies:
    2
    Views:
    407
    Ilias Lazaridis
    Apr 24, 2005
  3. Frank Millman
    Replies:
    23
    Views:
    643
    Steven D'Aprano
    Jun 13, 2007
  4. Jesse
    Replies:
    4
    Views:
    1,524
    Jesse
    Dec 13, 2007
  5. Ilias Lazaridis
    Replies:
    74
    Views:
    798
    Ilias Lazaridis
    Apr 4, 2005
Loading...

Share This Page