Making things more functional in Python

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

    #1

    Making things more functional in Python

    Is there a better, more FP style, more Pythonic way to
    write this:

    def compute_vectors (samples, dset):
    vectors = {}
    for d in dset:
    vectors[d] = [sample.get_val( d) for sample in
    samples]
    return vectors

    Namely, I'd like to get rid of the initilization
    (vectors = {}) and also the loop Yet, I'd hate to put
    an assignment into Python's FP list comprehensions.

    Ideally, I'd like something like this:
    vectors.dict_ad d({d:result}) for [sample.get_val( d)
    for sample in samples for d in dset].

    Is there anything like that? Am I missing the
    picture?

    Thanks.

    PS If possible, please cc me on all responses, thanks.




    _______________ _______________ ____
    Celebrate Yahoo!'s 10th Birthday!
    Yahoo! Netrospective: 100 Moments of the Web

  • Michael Hoffman

    #2
    Re: Making things more functional in Python

    gf gf wrote:[color=blue]
    > Is there a better, more FP style, more Pythonic way to
    > write this:
    >
    > def compute_vectors (samples, dset):
    > vectors = {}
    > for d in dset:
    > vectors[d] = [sample.get_val( d) for sample in
    > samples]
    > return vectors
    >
    > Namely, I'd like to get rid of the initilization
    > (vectors = {}) and also the loop[/color]

    Generate the whole dictionary on the fly with a Python 2.4 generator
    expression:

    dict((d, [sample.get_val( d) for sample in samples]) for d in dset)

    Whether this is "better" or not I think mainly hinges on which
    one you ahve an easier time understanding later. Personally I would
    prefer this version, but it's easy to get carried away trying to
    functionalize things to the point that a procedural version is much
    easier to understand.
    [color=blue]
    > Yet, I'd hate to put an assignment into Python's FP list
    > comprehensions.[/color]

    Indeed it's not possible to have an assignment in a list comprehension.
    (Unless it's a side-effect due to a function called by the list
    comprehension.)
    [color=blue]
    > Ideally, I'd like something like this:
    > vectors.dict_ad d({d:result}) for [sample.get_val( d)
    > for sample in samples for d in dset].[/color]

    You can't use the name "vectors" without first initializing it
    somehow!
    --
    Michael Hoffman

    Comment

    • Steve Holden

      #3
      Re: Making things more functional in Python

      gf gf wrote:[color=blue]
      > Is there a better, more FP style, more Pythonic way to
      > write this:
      >
      > def compute_vectors (samples, dset):
      > vectors = {}
      > for d in dset:
      > vectors[d] = [sample.get_val( d) for sample in
      > samples]
      > return vectors
      >
      > Namely, I'd like to get rid of the initilization
      > (vectors = {}) and also the loop Yet, I'd hate to put
      > an assignment into Python's FP list comprehensions.
      >
      > Ideally, I'd like something like this:
      > vectors.dict_ad d({d:result}) for [sample.get_val( d)
      > for sample in samples for d in dset].
      >
      > Is there anything like that? Am I missing the
      > picture?
      >
      > Thanks.
      >
      > PS If possible, please cc me on all responses, thanks.
      >[/color]
      The logical thing to use would be

      return dict([(d, sample.getval(d )) for d in dset for sample in samples])

      which (I think) should work from 2.2 onwards.

      regards
      Steve
      --
      Meet the Python developers and your c.l.py favorites March 23-25
      Come to PyCon DC 2005 http://www.pycon.org/
      Steve Holden http://www.holdenweb.com/

      Comment

      • Michael Hoffman

        #4
        Re: Making things more functional in Python

        Steve Holden wrote:
        [color=blue]
        > return dict([(d, sample.getval(d )) for d in dset for sample in samples])[/color]

        That won't do what the original code does. This sets dict[d] to
        samples[-1].getval(d) instead of [sample.getval(d ) for sample in samples].
        --
        Michael Hoffman

        Comment

        • Steve Holden

          #5
          Re: Making things more functional in Python

          Michael Hoffman wrote:[color=blue]
          > Steve Holden wrote:
          >[color=green]
          >> return dict([(d, sample.getval(d )) for d in dset for sample in samples])[/color]
          >
          >
          > That won't do what the original code does. This sets dict[d] to
          > samples[-1].getval(d) instead of [sample.getval(d ) for sample in samples].[/color]

          My bad, I didn;t look closely enbough to see the need for the nested
          comprehensions.

          regards
          Steve
          --
          Meet the Python developers and your c.l.py favorites March 23-25
          Come to PyCon DC 2005 http://www.pycon.org/
          Steve Holden http://www.holdenweb.com/

          Comment

          • Dave Benjamin

            #6
            Re: Making things more functional in Python

            On Fri, 2005-03-04 at 08:36 -0800, gf gf wrote:[color=blue]
            > Is there a better, more FP style, more Pythonic way to
            > write this:
            >
            > def compute_vectors (samples, dset):
            > vectors = {}
            > for d in dset:
            > vectors[d] = [sample.get_val( d) for sample in
            > samples]
            > return vectors[/color]

            You could use reduce:

            def compute_vectors (samples, dset):
            def add_entry(vecto rs, d):
            vectors[d] = [sample.get_val( d) for sample in samples]
            return vectors
            return reduce(add_entr y, dset, {})

            Dave


            Comment

            • Dave Benjamin

              #7
              Re: Making things more functional in Python

              On Sat, 2005-03-05 at 00:00 -0700, Dave Benjamin wrote:[color=blue]
              > On Fri, 2005-03-04 at 08:36 -0800, gf gf wrote:[color=green]
              > > Is there a better, more FP style, more Pythonic way to
              > > write this:
              > >
              > > def compute_vectors (samples, dset):
              > > vectors = {}
              > > for d in dset:
              > > vectors[d] = [sample.get_val( d) for sample in
              > > samples]
              > > return vectors[/color]
              >
              > You could use reduce:
              >
              > def compute_vectors (samples, dset):
              > def add_entry(vecto rs, d):
              > vectors[d] = [sample.get_val( d) for sample in samples]
              > return vectors
              > return reduce(add_entr y, dset, {})[/color]

              This could be further generalized:

              def compute(xs, ys, f):
              def add_entry(resul t, y):
              result[y] = [f(x, y) for x in xs]
              return result
              return reduce(add_entr y, ys, {})

              Now, compute_vectors is just:

              compute(samples , dset, lambda x, y: x.get_val(y))

              You could even abstract the method call:

              def method(name):
              def _method(obj, *args, **kwds):
              return getattr(obj, name)(*args, **kwds)
              return _method

              compute(samples , dset, method('get_val '))

              Dave


              Comment

              Working...