exceptions

Alex Martelli aleaxit at yahoo.com
Fri Oct 6 03:56:02 EDT 2000


"Aleksei Guzev" <aleksei.guzev at bigfoot.com> wrote in message
news:mailman.970805891.5240.python-list at python.org...
> what one should d when he wants smth like this:

That depends on one's exact definition of "something like".


> def f(d,s,e):
>     for i in range(s,e):
>         print d[i]
>
> D={1:'blah1', 2:'blah2', 3:'blah3', 7:'blah7', 10:'blah10'}
>
> try: f(D, 1, 30)
> except KeyError(key):
>     D[key]='blah%d'%key
>     RESUME
>
> It's a simple example. Assume f(d,s,e) is defined by another programmer
deep
> in a module.

OK, so you want to supply to f an object d for which the semantics of
    d[i]
are:
    -- if i is a key in dictionary D, then return D[i]
    -- else force 'blah%d' % i into D[i] then return it

There are several approaches you could take to building such an object to
be passed to f.  I would slightly favour a wrapperclass approach; in
Python 2.0, the natural solution would be:

class blahwrap:
    def __init__(self, dict):
        self.dict = dict
    def __getitem__(self, key):
        return self.dict.setdefault(key, 'blah%d' % key)

D={1:'bloh1', 2:'bloh2', 3:'bloh3', 7:'bloh7', 10:'bloh10'}

f(blahwrap(D), 1, 12)


with output:
bloh1
bloh2
bloh3
blah4
blah5
blah6
bloh7
blah8
blah9
bloh10
blah11

(I've modified D so the original and concocted-on-the-fly entries
can more easily be distinguished).

Of course, wholly equivalent solutions are available in earlier
Python versions as well, you just need to substitute a couple more
lines in place of the newly-introduced setdefault method of the
dictionary object (try/except KeyError, or if self.dict.has_key,
etc etc).


> It seems to be not a good idea to provide f with a procedural object as an
> argument for every exception... Because those programmer SHOULD NOT know
> anything of the dictionary I provide. If one defines an object then he
> should handle everything concerned with it. This shortens the code and
> increases speed.

Of course!  That's why you must "define an object" (specifically, an
instance of the class that wraps the dictionary, and tweaks its exact
semantics to what you desire) rather than just pass a raw object whose
semantics are defined elsewhere (in a dictionary's case, deep in the
Python internals) and try to patch it up with procedural code at the
calling-spot, _outside_ the object you're passing.

Define the object you need, implement the exact semantics you need
_right where it belongs, in its methods_, pass the object you defined,
rather than a raw object defined elsewhere, and you'll have a well
architected, object-oriented, Pythonic solution to your problem.
(Without, of course, any need for restartable-exceptions and such).


The pattern of "wrap an object up in another to implement somewhat
different [syntactically or semantically] interfaces" is known, quite
reasonably, as "The Adapter Pattern" in the "Gang-of-Four" terminology.
(Some also call it, more explicitly, the Wrapper pattern).

If I had to nominate ONE GoF Pattern as the single most important
one for everyday Python programming, it would no doubt be Adapter
(aka Wrapper).

I'm starting to think we need an accessible repertory of Design
Patterns expressed in/for Python, as all of the examples I can
easily find on the Web are oriented to statically typed languages
(Java, C++, ...) where the trade-offs are somewhat different.


Alex






More information about the Python-list mailing list