[DB-SIG] Optional DB API Extensions

Magnus Lyckå magnus@thinkware.se
Wed, 24 Oct 2001 15:41:57 +0200


At 13:35 2001-10-24 +0200, M.-A. Lemburg wrote:
> > After all these years I still make mistakes with string.find()...
> > I'm not suggesting that string.find should raise an exception
> > or return None if nothing is found. After all, not finding a
> > character in a string is something normal, hardly exceptional,
> > and both 0 and None are "false", so returning None would be
> > an invitation to bugs. But I still think the "-1" is a wart.
>
>Not really: -1 is not in the set of valid values since the
>return value is meant to be an index into a sequence (of
>characters) and indexes start at 0.

I know, it's just that after all these years it STILL feels
more natural to write

if s.find(x):
    bla bla

than

if s.find(x) != -1:
    bla bla

just as I do with re match objects and a lot of other objects
like strings, dicts and many home made class instances.

I understand why it works like it does, and I don't suggest any
change there (wrong forum anyway), but I feel more comfortable
with the way re match objects work, returning None if there is
nothing to find.

Most of the time, python works just as my intuition suggests,
almost like spoken language, much closer to the way I think than
other programming languages, and "if s.find(x) != -1:" is a
deviation, even it I usually spot it before I finish the next
line of code...

I think it's good if we can avoid these invitations to making
mistakes. Exceptions are very explicit...

> > Is it a terrible thing to raise an exception here? After all,
> > if I request a value from a module that doesn't know how to
> > supply that, I think that is a candidate for an exception. Or
> > did I misunderstand something?
>
>It's mainly a performance question: raising exceptions is very
>expensive and should only be done for unexpected behaviour.
>OTOH, checking for negative results when querying e.g. .rowcount of
>.rownumber is fast.

Or "is None"... On the other hand, there is a risk that people will
use "if rowid:" instead of "if rowid is not None:" and get in
trouble if the code is 0!

If I cared for performance I'd code in C! ;-)

I understand your point, but it doesn't really add up to me
anyway. If you know beforehand that this particular DB API
doesn't support rowids, there is no point in querying for
it. If you write "generic code" and don't know beforehand what
DB it is, you might expect an integer and recieve an Oracle
tuple or whatever it might be... It's not as in the string.find
or re.match example, that sometimes you get a result back,
and sometimes you won't. In the case here, the result will be
the same with every run, regardless of data, as long as you
have imported the same DB API. For me, it is unexpected
behaviour to ask a module to deliver a service that it is not
ever capable of providing. It has some kind of brute-force
taste to it.

But I'm sure both Marc-Andre and Federico work much more
with these modules than I ever will, so I won't push this
issue further.

Just as a little annoying suggestion: If you do want your
generic high performance code inside this big loop, you
could instead of

---
while biiiig loooop:
    ret = might.work()
    if ret == -1:
       ret = SomeOtherWayOfFindingOut()
    use(ret)
---

do it like this
---
itWorks = 1
while biiiig loooop:
   if itWorks:
     try:
       ret = might.work()
     except NotImplemented:
       itWorks = 0
       ret = SomeOtherWayOfFindingOut()
   else:
     ret = SomeOtherWayOfFindingOut()
   use(ret)
---

You will only get one exception. You don't call might.work()
more than one time if it fails. You also get as many ifs in
both cases. This should be as fast if might.works() is in
order, and faster if it isn't.


/Magnus


--
Magnus Lyckå, Thinkware AB
Älvans väg 99, SE-907 50 UMEÅ
tel 070-582 80 65, fax: 070-612 80 65
http://www.thinkware.se/  mailto:magnus@thinkware.se