Lambda alternative?

Discussion in 'Python' started by mousemeat@gmail.com, Apr 15, 2009.

  1. Guest

    Hello all,

    I really like the lambda function for a particular task i have: I am
    writing some simulation software, working with many different
    materials. Each material with many different properties, some are
    temperature dependent, others aren't, some are defined by a function,
    some are a lookup table, some are constant. Here is a simplified
    version:

    class material(object):
    def __init__(self,density):
    self.density=density

    airdensity=lambda T:100000/(287*T)
    air=material(airdensity)

    steeldensity=lambda T:interp(T,[0,1000],[7856,7813])
    steel=material(steeldensity)

    rockdensity=lambda T:5000
    rock=material(rockdensity)

    I really like doing things this way, because i can then define other
    properties within the class and i can always use the syntax:
    specificgravity_at_273K=stone.specificgravity(273), whether
    specificgravity is a function or a parameter. (not sure thats the
    right nomenclature, but i think you'll know what i mean.)

    But, lambda functions can't be pickled. I would like to pickle my
    objects, and i would really like to use parallel python (which
    requires pickling).

    The best way i can see to do that is to make a new class which
    inheirits the 'material' class for each physical material i want to
    model, but surely i should be creating instances rather than classes.

    Is this going to present some new problems that anyone can forsee? Can
    anyone think of a better way to do this? I keep reading that lambda
    functions aren't particularly pythonic and that there are always
    alternatives, but they seem very elegant to me.

    Thanks for your time,

    Warren
    , Apr 15, 2009
    #1
    1. Advertising

  2. Paul Rubin Guest

    writes:
    > But, lambda functions can't be pickled. I would like to pickle my
    > objects, and i would really like to use parallel python (which
    > requires pickling).


    Maybe you could use marshal instead of pickle. Make sure to read the
    documentation carefully--there are some pitfalls that can bite you.
    Paul Rubin, Apr 15, 2009
    #2
    1. Advertising

  3. Paul Rubin Guest

    Duncan Booth <> writes:
    > What exactly is your objection to using a named function here?...
    > Surely that would solve your pickle problem *and* give you more meaningful
    > tracebacks in your exceptions?


    I don't think it would help the pickle problem.
    Paul Rubin, Apr 15, 2009
    #3
  4. >>>>> (m) wrote:

    >m> Hello all,
    >m> I really like the lambda function for a particular task i have: I am
    >m> writing some simulation software, working with many different
    >m> materials. Each material with many different properties, some are
    >m> temperature dependent, others aren't, some are defined by a function,
    >m> some are a lookup table, some are constant. Here is a simplified
    >m> version:


    >m> class material(object):
    >m> def __init__(self,density):
    >m> self.density=density


    >m> airdensity=lambda T:100000/(287*T)
    >m> air=material(airdensity)


    >m> steeldensity=lambda T:interp(T,[0,1000],[7856,7813])
    >m> steel=material(steeldensity)


    >m> rockdensity=lambda T:5000
    >m> rock=material(rockdensity)


    The following isn't much different (only 6 chars more per def):

    def airdensity(T): return 100000/(287*T)
    air=material(airdensity)

    def steeldensity(T): return interp(T,[0,1000],[7856,7813])
    steel=material(steeldensity)

    def rockdensity(T): return 5000
    rock=material(rockdensity)

    --
    Piet van Oostrum <>
    URL: http://pietvanoostrum.com [PGP 8DAE142BE17999C4]
    Private email:
    Piet van Oostrum, Apr 15, 2009
    #4
  5. mousemeat Guest

    On 15 Apr, 16:27, Piet van Oostrum <> wrote:
    > >>>>> (m) wrote:

    > >m> Hello all,
    > >m> I really like the lambda function for a particular task i have: I am
    > >m> writing some simulation software, working with many different
    > >m> materials. Each material with many different properties, some are
    > >m> temperature dependent, others aren't, some are defined by a function,
    > >m> some are a lookup table, some are constant. Here is a simplified
    > >m> version:
    > >m> class material(object):
    > >m>     def __init__(self,density):
    > >m>         self.density=density
    > >m> airdensity=lambda T:100000/(287*T)
    > >m> air=material(airdensity)
    > >m> steeldensity=lambda T:interp(T,[0,1000],[7856,7813])
    > >m> steel=material(steeldensity)
    > >m> rockdensity=lambda T:5000
    > >m> rock=material(rockdensity)

    >
    > The following isn't much different (only 6 chars more per def):
    >
    > def airdensity(T): return 100000/(287*T)
    > air=material(airdensity)
    >
    > def steeldensity(T): return interp(T,[0,1000],[7856,7813])
    > steel=material(steeldensity)
    >
    > def rockdensity(T): return 5000
    > rock=material(rockdensity)
    >
    > --
    > Piet van Oostrum <>
    > URL:http://pietvanoostrum.com[PGP 8DAE142BE17999C4]
    > Private email: - Hide quoted text -
    >
    > - Show quoted text -


    Will i then be able to pickle 'rock', and any object that may contain
    'rock' as one of it's fields? I'm not sure that i will, but i'll give
    it a shot.
    mousemeat, Apr 15, 2009
    #5
  6. Paul Rubin Guest

    Duncan Booth <> writes:
    > dumped = dumps(air)
    > t = loads(dumped)
    > print t # works fine



    Hmm, well, that doesn't really pickle the function; it pickles a class
    instance that records where the class definition was and (on
    unpickling) imports that module. Maybe that is sufficient for this
    purpose.
    Paul Rubin, Apr 15, 2009
    #6
  7. mousemeat Guest

    On 16 Apr, 09:39, Duncan Booth <> wrote:
    > Paul Rubin <http://> wrote:
    > > Duncan Booth <> writes:
    > >> dumped = dumps(air)
    > >> t = loads(dumped)
    > >> print t # works fine

    >
    > > Hmm, well, that doesn't really pickle the function; it pickles a class
    > > instance that records where the class definition was and (on
    > > unpickling) imports that module.  Maybe that is sufficient for this
    > > purpose.

    >
    > It pickles a class instance which contains a reference to a function and
    > on unpickling it recreates the class instance with a new reference to
    > the function of the same name.
    >
    > That's how pickling works: it records where the class or function is
    > defined and creates a new reference to the class or function of the same
    > name when you unpickle. The classes and functions have to be defined at
    > module scope otherwise it won't be able to reference them. You don't
    > ever actually get either a class or function in the pickle so if you
    > want you can update the code and the unpickled object gets the new one.
    >
    > >>> import pickle
    > >>> class C(object):

    >
    >         def __init__(self, fn):
    >                 self.fn = fn
    >         def callfn(self):
    >                 self.fn()
    >
    > >>> def foo():

    >
    >         print "Hello I'm foo"
    >
    > >>> inst = C(foo)
    > >>> inst.callfn()

    > Hello I'm foo
    > >>> p = pickle.dumps(inst)
    > >>> def foo():

    >
    >         print "I'm a new foo"
    >
    > >>> inst2 = pickle.loads(p)
    > >>> inst2.callfn()

    > I'm a new foo
    > >>> inst.callfn()

    >
    > Hello I'm foo
    >
    > --
    > Duncan Boothhttp://kupuguy.blogspot.com



    Thank you for everyone's explanations, help and interest on this one.
    I have reworked my code as described and promised myself not to use
    lambdas ever again (i still think they are an elegant idea, but if
    they are incompatible with frequently used modules, then the
    inelegance of reality quickly overshadows the elegance of the theory).

    I think my problem now is that parallel python will want to unpickle
    my objects but can't find the modules. I've asked the pp forum for
    insight, but i think i'm going to have to plug away with this one.

    Thanks again,

    Warren
    mousemeat, Apr 16, 2009
    #7
  8. mousemeat <> writes:

    > Thank you for everyone's explanations, help and interest on this
    > one. I have reworked my code as described and promised myself not
    > to use lambdas ever again (i still think they are an elegant idea,
    > but if they are incompatible with frequently used modules, then the
    > inelegance of reality quickly overshadows the elegance of the
    > theory).


    I think you're going too far concluding that lambdas are unusable.
    lambdas are a problem only when they are stored as data attributes
    that need to be pickled, but that's far from being the only use case.
    You can still use them for what they're meant to be used: tiny anonymous
    function-expressions, typically passed as parameters to functions that
    expect a callback.

    Avoiding lambdas because they're unpicklable is like avoiding bound
    methods because they're just as unpicklable.
    Hrvoje Niksic, Apr 16, 2009
    #8
  9. mousemeat Guest

    On 16 Apr, 10:21, Hrvoje Niksic <> wrote:
    > mousemeat <> writes:
    > > Thank you for everyone's explanations, help and interest on this
    > > one.  I have reworked my code as described and promised myself not
    > > to use lambdas ever again (i still think they are an elegant idea,
    > > but if they are incompatible with frequently used modules, then the
    > > inelegance of reality quickly overshadows the elegance of the
    > > theory).

    >
    > I think you're going too far concluding that lambdas are unusable.
    > lambdas are a problem only when they are stored as data attributes
    > that need to be pickled, but that's far from being the only use case.
    > You can still use them for what they're meant to be used: tiny anonymous
    > function-expressions, typically passed as parameters to functions that
    > expect a callback.
    >
    > Avoiding lambdas because they're unpicklable is like avoiding bound
    > methods because they're just as unpicklable.


    Correct me if i am wrong, but i can pickle an object that contains a
    bound method (it's own bound method). I cannot pickle an object that
    contains a lambda function. Doesn't that make lambda's less
    pickleable? (I don't mean to be argumentative, i'm trying to
    understand python's syntax a little better.)
    mousemeat, Apr 16, 2009
    #9
  10. Aaron Brady Guest

    On Apr 16, 5:25 am, mousemeat <> wrote:
    > On 16 Apr, 10:21, Hrvoje Niksic <> wrote:
    >
    >
    >
    > > mousemeat <> writes:
    > > > Thank you for everyone's explanations, help and interest on this
    > > > one.  I have reworked my code as described and promised myself not
    > > > to use lambdas ever again (i still think they are an elegant idea,
    > > > but if they are incompatible with frequently used modules, then the
    > > > inelegance of reality quickly overshadows the elegance of the
    > > > theory).

    >
    > > I think you're going too far concluding that lambdas are unusable.
    > > lambdas are a problem only when they are stored as data attributes
    > > that need to be pickled, but that's far from being the only use case.
    > > You can still use them for what they're meant to be used: tiny anonymous
    > > function-expressions, typically passed as parameters to functions that
    > > expect a callback.

    >
    > > Avoiding lambdas because they're unpicklable is like avoiding bound
    > > methods because they're just as unpicklable.

    >
    > Correct me if i am wrong, but i can pickle an object that contains a
    > bound method (it's own bound method).  I cannot pickle an object that
    > contains a lambda function.  Doesn't that make lambda's less
    > pickleable?  (I don't mean to be argumentative, i'm trying to
    > understand python's syntax a little better.)


    When you pickle an instance, you get its data and the name of its
    class. If you don't have the class later, you can't unpickle it.

    Pickle is intended for persistence, and the only real kinds of
    persistent code are a self-contained library file, and the source,
    especially given access to function-external variables, i.e.
    closures. Pickling a function is like taking an excerpt from a binary
    executable. It can only be used in highly limited contexts, and as
    such not good for a standard module.

    It is most likely you want to transmit the source-- either the entire
    module, which you can then import dynamically, or an excerpt from it,
    which is known to have no closures, etc., and carefully call 'eval' on
    it.

    I disagree that Andres Tremols & Peter Cogolo's 'Recipe 7.6. Pickling
    Code Objects' is applicable. It's highly specialized, delicate, and
    brittle.
    Aaron Brady, Apr 16, 2009
    #10
  11. mousemeat <> writes:

    > Correct me if i am wrong, but i can pickle an object that contains a
    > bound method (it's own bound method).


    No, you can't:

    >>> import cPickle as p
    >>> p.dumps([])

    '(l.'
    >>> p.dumps([].append)

    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: expected string or Unicode object, NoneType found

    > (I don't mean to be argumentative, i'm trying to understand python's
    > syntax a little better.)


    Note that this has nothing to do with syntax, but with the
    (intentional) limitations of the "pickle" module.
    Hrvoje Niksic, Apr 16, 2009
    #11
  12. On Thu, 2009-04-16 at 13:33 +0200, Hrvoje Niksic wrote:
    > mousemeat <> writes:
    >
    > > Correct me if i am wrong, but i can pickle an object that contains a
    > > bound method (it's own bound method).

    >
    > No, you can't:
    >
    > >>> import cPickle as p
    > >>> p.dumps([])

    > '(l.'
    > >>> p.dumps([].append)

    > Traceback (most recent call last):
    > File "<stdin>", line 1, in <module>
    > TypeError: expected string or Unicode object, NoneType found


    Yes he can. mousemeat stated that he could pickle an object that
    *contains* a bound method, not that he could pickle the method itself.

    That said, you can make an instance method out of a lambda, just as well
    as any named function, and you can pickle that object, too:

    Python 2.5.2 (r252:60911, Oct 5 2008, 19:29:17)
    [GCC 4.3.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import cPickle as p
    >>> class Foo(object):

    .... a = lambda self, x: x+1
    >>> foo.a(1)

    2
    >>> type(foo.a)

    <type 'instancemethod'>
    >>> p.dumps(foo)

    'ccopy_reg\n_reconstructor\np1\n(c__main__\nFoo\np2\nc__builtin__
    \nobject\np3\nNtRp4\n.'

    Cheers,
    Cliff
    J. Cliff Dyer, Apr 17, 2009
    #12
  13. Aaron Brady Guest

    On Apr 17, 1:43 pm, "J. Cliff Dyer" <> wrote:
    > On Thu, 2009-04-16 at 13:33 +0200, Hrvoje Niksic wrote:
    > > mousemeat <> writes:

    >
    > > > Correct me if i am wrong, but i can pickle an object that contains a
    > > > bound method (it's own bound method).

    >
    > > No, you can't:

    >
    > > >>> import cPickle as p
    > > >>> p.dumps([])

    > > '(l.'
    > > >>> p.dumps([].append)

    > > Traceback (most recent call last):
    > >   File "<stdin>", line 1, in <module>
    > > TypeError: expected string or Unicode object, NoneType found

    >
    > Yes he can.  mousemeat stated that he could pickle an object that
    > *contains* a bound method, not that he could pickle the method itself.
    >
    > That said, you can make an instance method out of a lambda, just as well
    > as any named function, and you can pickle that object, too:

    snip

    'Contains' here is ambiguous. If the object contains a bound method,
    that is, if a bound method is in its dictionary, you can't.

    >>> import pickle as p
    >>> class A: pass

    ....
    >>> a= A()
    >>> class A:

    .... def f( self ): print( 'f' )
    ....
    >>> a= A()
    >>> class B: pass

    ....
    >>> b= B()
    >>> b.f= a.f
    >>> b.f()

    f
    >>> p.dumps( b )

    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "C:\Programs\Python30\lib\pickle.py", line 1329, in dumps
    Pickler(f, protocol).dump(obj)
    _pickle.PicklingError: Can't pickle <class 'method'>: attribute
    lookup
    builtins.method failed

    In this example, 'b' contains a bound method, 'a.f'. However, for
    other definitions of 'contains', such as if 'b' is an instance of a
    class that contains methods, you can. But in that case, the method is
    not in 'b.__dict__'.

    >>> b.__dict__

    {'f': <bound method A.f of <__main__.A object at 0x00B54B90>>}
    Aaron Brady, Apr 17, 2009
    #13
  14. Duncan Booth <> writes:

    >>>>> import cPickle as p
    >>>>> p.dumps([])

    >> '(l.'
    >>>>> p.dumps([].append)

    >> Traceback (most recent call last):
    >> File "<stdin>", line 1, in <module>
    >> TypeError: expected string or Unicode object, NoneType found

    >
    > Not the best of examples: [].append is a built-in method rather than a
    > bound method.


    Sorry about the confusion. By bound method I meant the callable
    obtained by binding a method (built-in or written in python) to a
    concrete instance, as opposed to an unbound method, such as
    list.append. The reprs are different for built-in methods and for
    python methods, but I consider that difference an artifact of the
    CPython implementation, not a distinction mandated by the language.
    Hrvoje Niksic, Apr 17, 2009
    #14
    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. Xah Lee

    A Lambda Logo Tour

    Xah Lee, Apr 5, 2006, in forum: Java
    Replies:
    5
    Views:
    505
    Alex Hunsley
    Apr 7, 2006
  2. Roman Suzi
    Replies:
    13
    Views:
    593
    Bengt Richter
    Jan 7, 2005
  3. Pablo
    Replies:
    6
    Views:
    343
    Maric Michaud
    May 26, 2006
  4. Steve Dogers

    lambda vs non-lambda proc

    Steve Dogers, Mar 30, 2009, in forum: Ruby
    Replies:
    1
    Views:
    157
    Sean O'Halpin
    Mar 30, 2009
  5. Haochen Xie
    Replies:
    4
    Views:
    234
    Haochen Xie
    Mar 17, 2013
Loading...

Share This Page