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

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

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

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

David Ascher, Alex Martelli, Anna Ravenscroft

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

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

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







Recipe 6.4. Chaining Dictionary Lookups


Credit: Raymond Hettinger


Problem




You have several mappings (usually
dicts) and want to look things up in them in a
chained way (try the first one; if the key is not there, then try the
second one; and so on). Specifically, you want to make a single
mapping object that "virtually
merges" several others, by looking things up in them
in a specified priority order, so that you can conveniently pass that
one object around.


Solution


A mapping is a generalized, abstract version
of a dictionary: a mapping provides an interface
that's similar to a dictionary's,
but it may use very different implementations. All dictionaries are
mappings, but not vice versa. Here, you need to implement a mapping
which sequentially tries delegating lookups to other mappings. A
class is the right way to encapsulate this
functionality:

class Chainmap(object):
def _ _init_ _(self, *mappings):
# record the sequence of mappings into which we must look
self._mappings = mappings
def _ _getitem_ _(self, key):
# try looking up into each mapping in sequence
for mapping in self._mappings:
try:
return mapping[key]
except KeyError:
pass
# `key' not found in any mapping, so raise KeyError exception
raise KeyError, key
def get(self, key, default=None):
# return self[key] if present, otherwise `default'
try:
return self[key]
except KeyError:
return default
def _ _contains_ _(self, key):
# return True if `key' is present in self, otherwise False
try:
self[key]
return True
except KeyError:
return False

For example, you can now implement the same sequence of lookups that
Python normally uses for any name: look among locals, then (if not
found there) among globals, lastly (if not found yet) among
built-ins:

import _ _builtin_ _
pylookup = Chainmap(locals( ), globals( ), vars(_ _builtin_ _))


Discussion


Chainmap relies on minimal functionality from
the mappings it wraps: each of those underlying mappings must allow
indexing (i.e., supply a special method _ _getitem_
_
), and it must raise the standard exception
KeyError when indexed with a key that the mapping
does not know about. A Chainmap instance provides
the same behavior, plus the handy get method
covered in Recipe 4.9 and
special method _ _contains_ _ (which conveniently
lets you check whether some key k is
present in a Chainmap instance
c by just coding if k in
c
).

Besides the obvious and sensible limitation of being
"read-only", this
Chainmap class has othersessentially, it is
not a "full mapping" even within
the read-only design choice. You can make any partial mapping into a
"full mapping" by inheriting from
class DictMixin (in standard library module
UserDict) and supplying a few key methods
(DictMixin implements the others). Here is how you
could make a full (read-only) mapping from ChainMap
and
UserDict.DictMixin:

import UserDict
from sets import Set
class FullChainmap(Chainmap, UserDict.DictMixin):
def copy(self):
return self._ _class_ _(self._mappings)
def _ _iter_ _(self):
seen = Set( )
for mapping in self._mappings:
for key in mapping:
if key not in seen:
yield key
seen.add(key)
iterkeys = _ _iter_ _
def keys(self):
return list(self)

This class
FullChainmap adds one requirement to the mappings it
holds, besides the requirements posed by Chainmap:
the mappings must be iterable. Also note that the implementation in
Chainmap of methods get and
_ _contains_ _ is redundant (although innocuous)
once we subclass DictMixin, since
DictMixin also implements those two methods (as
well as many others) in terms of lower-level methods, just like
Chainmap does. See Recipe 5.14 for more details about
DictMixin.


See Also


Recipe 4.9; Recipe 5.14; the Library
Reference
and Python in a Nutshell
sections on mapping types.


/ 394