Python Cookbook 2Nd Edition Jun 1002005 [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Python Cookbook 2Nd Edition Jun 1002005 [Electronic resources] - نسخه متنی

David Ascher, Alex Martelli, Anna Ravenscroft

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید







Recipe 4.12. Building a Dict from a List of Alternating Keys and Values


Credit: Richard Philips, Raymond Hettinger


Problem


You want to build a dict from a list of alternating keys and values.


Solution


The built-in type dict offers many ways to build
dictionaries, but not this one, so we need to code a function for the
purpose. One way is to use the built-in function
zip on extended slices:

def dictFromList(keysAndValues):
return dict(zip(keysAndValues[::2], keysAndValues[1::2]))

A more general approach, which works for any sequence or other
iterable argument and not just for lists, is to
"factor out" the task of getting a
sequence of pairs from a flat sequence into a separate generator.
This approach is not quite as concise as
dictFromList, but it's faster as
well as more general:

def pairwise(iterable):
itnext = iter(iterable).next
while True:
yield itnext( ), itnext( )
def dictFromSequence(seq):
return dict(pairwise(seq))

Defining pairwise also allows
updating an existing dictionary with any
sequence of alternating keys and valuesjust code, for example,
mydict.update(pairwise(seq)).


Discussion


Both of the "factory functions" in
this recipe use the same underlying way to construct a dictionary:
each calls dict with an argument that is a
sequence of (key, value) pairs. All the difference
is in how the functions build the sequence of pairs to pass to
dict.

dictFromList builds a list of such pairs by calling
built-in function zip with two extended-form
slices of the function's
keysAndValues argumentone that gathers all
items with even indices (meaning the items at index 0, 2, 4, . . .),
the other that gathers all items with odd indices (starting at 1 and
counting by 2 . . .). This approach is fine, but it works only when
the argument named keysAndValues is an instance of a
type or class that supports extended slicing, such as
list, tuple or
str. Also, this approach results in constructing
several temporary lists in memory: if keysAndValues
is a long sequence, all of this list construction activity can cost
some performance.

dictFromSequence, on the other hand, delegates the
task of building the sequence of pairs to the generator named
pairwise. In turn, pairwise is
coded to ensure that it can use any iterable at allnot just
lists (or other sequences, such as tuples or strings), but also, for
example, results of other generators, files, dictionaries, and so on.
Moreover, pairwise yields pairs one at a time. It
never constructs any long list in memory, an aspect that may improve
performance if the input sequence is very long.

The implementation of pairwise is interesting. As
its very first statement, pairwise binds local name
itnext to the bound-method next
of the iterator that it obtains by calling the built-in function
iter on the iterable argument.
This may seem a bit strange, but it's a good general
technique in Python: if you start with an object, and all you need to
do with that object is call one of its methods in a loop, you can
extract the bound-method, assign it to a local name, and afterwards
just call the local name as if it were a function.
pairwise would work just as well if the
next method was instead called in a way that may
look more normal to programmers who are used to other languages:

def pairwise_slow(iterable):
it = iter(iterable)
while True:
yield it.next( ), it.next( )

However, this pairwise_slow variant
isn't really any simpler than the
pairwise generator shown in the Solution
("more familiar to people who don't
know Python" is not a synonym
of "simpler"!), and it
is about 60% slower. Focusing on simplicity and
clarity is one thing, and a very good oneindeed, a core
principle of Python. Throwing performance to the winds,
without getting any real advantage to
compensate, is a completely different proposition and definitely not
a practice that can be recommended in any language. So, while it is
an excellent idea to focus on writing correct, clear, and simple
code, it's also very advisable to learn and use
Python's idioms that are most appropriate to your
needs.


See Also


Recipe 19.7 for more
general approaches to looping by sliding windows over an iterable.
See the Python Reference Manual for more on
extended slicing.


/ 394