[Tutor] General Information Request
Danny Yoo
dyoo at hkn.eecs.berkeley.edu
Tue Sep 6 22:57:01 CEST 2005
On Tue, 6 Sep 2005, Lane, Frank L wrote:
> I found a really neat technique on the web using a built in called
> "apply", with it you can do struct.pack() using an array for the values.
> I can't find the technique in the release documentation and what's there
> says apply is deprecated, use the new function (**args, *kwargs) or
> something like that.
Hi Frank,
Python allows us to write functions that take a variable number of
arguments. (For the moment, let's ignore the kwargs stuff.)
For example:
######
>>> def wave_at_all(*people):
... for p in people:
... print "waving at", p
...
>>>
>>> wave_at_all()
>>>
>>> wave_at_all("euclid")
waving at euclid
>>>
>>> wave_at_all("frank", "lloyd", "wright")
waving at frank
waving at lloyd
waving at wright
######
When we have these functions that can take variable number of arguments,
it's often nice to be able to feed a list directly into them, without
having to destructure them.
That's where apply comes in:
######
>>> apply(wave_at_all, ["jane", "doe"])
waving at jane
waving at doe
######
Without apply, this example might have been written as:
######
some_list = ['jane', 'doe']
first_name, second_name = some_list
wave_at_all(first_name, second_name)
######
But the problem with this, though, is that this approach doesn't scale: it
doesn't work for lists of arbitrary length, because in the general case,
we won't know in advance how many elements we need to "destructure" or
yank out of a list.
So one reason why apply() exists is to allow us to use
variable-length-argument-eating functions with lists. (That was a
mouthful. *grin*) It's not the only reason, but it's a big one.
Notationally, apply() seemed a little weird to many Python programmers, so
the Python implementors added an alternative syntax in Python 2.0:
apply(some_function, list_of_arguments)
==>
some_function(*list_of_arguments)
(See: http://www.amk.ca/python/2.0/index.html#SECTION0001010000000000000000)
Does this make sense so far? Please feel free to ask questions about
this.
> I also saw a technique for building a dictionary out of two arrays,
> which I also can't read:
>
> dict([(['one', 'two'][i-2], i) for i in (2,3)])
>
> Is this just something that I have to get accustomed to or are there
> pointers that help us read python-speak better?
I can't read this either. Truthfully, this looks horrible. *grin*
What's happening is that there's a list comprehension nested in there, and
the expression as a whole feels very convoluted to me. Here, let's break
it down a bit.
mapping = dict([(['one', 'two'][i-2], i) for i in (2,3)])
==>
keys_and_values = [(['one', 'two'][i-2], i)
for i in (2, 3)]
mapping = dict(keys_and_values)
This also looks fairly ugly. (It also worries me because it looks like
there's an off-by-one bug: why is 'one' being mapped to 2?)
We can remove the use of the list comprehension altogether:
keys_and_values = [(['one', 'two'][i-2], i)
for i in (2, 3)]
mapping = dict(keys_and_values)
==>
keys = ['one', 'two']
values = [2, 3]
mapping = dict(zip(keys, values))
Best of wishes to you!
More information about the Tutor
mailing list