Making things more functional in Python

G

gf gf

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_add({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
http://birthday.yahoo.com/netrospective/
 
M

Michael Hoffman

gf said:
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

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.
Yet, I'd hate to put an assignment into Python's FP list
> comprehensions.

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.)
Ideally, I'd like something like this:
vectors.dict_add({d:result}) for [sample.get_val(d)
for sample in samples for d in dset].

You can't use the name "vectors" without first initializing it
somehow!
 
S

Steve Holden

gf said:
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_add({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.
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
 
M

Michael Hoffman

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

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].
 
S

Steve Holden

Michael said:
Steve said:
return dict([(d, sample.getval(d)) for d in dset for sample in samples])


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].

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

regards
Steve
 
D

Dave Benjamin

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

You could use reduce:

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

Dave
 
D

Dave Benjamin

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

You could use reduce:

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

This could be further generalized:

def compute(xs, ys, f):
def add_entry(result, y):
result[y] = [f(x, y) for x in xs]
return result
return reduce(add_entry, 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top