By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,213 Members | 1,117 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,213 IT Pros & Developers. It's quick & easy.

Correct use of try,except and raise?

P: n/a
Is this correct use of exceptions? to raise an indexerror and add my
own string insetad of just letting it raise a IndexError by itself and
"blaming" it on list.pop?

class Stack(object):
def __init__(self, *items):
self.stack = list(items)

def push(self, item):
self.stack.append(item)

def pop(self):
try:
return self.stack.pop()
except:
raise IndexError, "pop from empty stack"

class Queue(object):
def __init__(self, *items):
self.queue = list(items)

def append(self, item):
self.queue.append(item)

def pop(self):
try:
return self.queue.pop(0)
except:
raise IndexError, "pop from empty queue"
Jul 12 '08 #1
Share this Question
Share on Google+
9 Replies


P: n/a
In article
<3b**********************************@p25g2000hsf. googlegroups.com>,
ssecorp <ci**********@gmail.comwrote:
Is this correct use of exceptions? to raise an indexerror and add my
own string insetad of just letting it raise a IndexError by itself and
"blaming" it on list.pop?

class Stack(object):
def __init__(self, *items):
self.stack = list(items)

def push(self, item):
self.stack.append(item)

def pop(self):
try:
return self.stack.pop()
except:
raise IndexError, "pop from empty stack"

class Queue(object):
def __init__(self, *items):
self.queue = list(items)

def append(self, item):
self.queue.append(item)

def pop(self):
try:
return self.queue.pop(0)
except:
raise IndexError, "pop from empty queue"
I think you would do better defining a new exception, PopError, or
something like that. Then you can write code which specifically catches
that and do something with it.

It's also not a good idea to catch all exceptions. Catch the most specific
thing you can. Consider something like:

try:
kew.pop(0)
except:
raise IndexError, "pop from empty kew"

When I run it, it prints, "IndexError: pop from empty kew". The problem
is, the *real* error is "NameError: name 'kew' is not defined". By
catching all exceptions, I've masked a programming error by turning the
NameError into an IndexError.
Jul 13 '08 #2

P: n/a
On Jul 13, 2:32*am, Roy Smith <r...@panix.comwrote:
In article
<3b78898b-6131-4137-9c1d-64deaf460...@p25g2000hsf.googlegroups.com>,

*ssecorp <circularf...@gmail.comwrote:
Is this correct use of exceptions? to raise an indexerror and add my
own string insetad of just letting it raise a IndexError by itself and
"blaming" it on list.pop?
class Stack(object):
* * def __init__(self, *items):
* * * * self.stack = list(items)
* * def push(self, item):
* * * * self.stack.append(item)
* * def pop(self):
* * * * try:
* * * * * * return self.stack.pop()
* * * * except:
* * * * * * raise IndexError, "pop from empty stack"
class Queue(object):
* * def __init__(self, *items):
* * * * self.queue = list(items)
* * def append(self, item):
* * * * self.queue.append(item)
* * def pop(self):
* * * * try:
* * * * * * return self.queue.pop(0)
* * * * except:
* * * * * * raise IndexError, "pop from empty queue"

I think you would do better defining a new exception, PopError, or
something like that. *Then you can write code which specifically catches
that and do something with it.

It's also not a good idea to catch all exceptions. *Catch the most specific
thing you can. *Consider something like:

try:
* * kew.pop(0)
except:
* *raise IndexError, "pop from empty kew"

When I run it, it prints, "IndexError: pop from empty kew". *The problem
is, the *real* error is "NameError: name 'kew' is not defined". *By
catching all exceptions, I've masked a programming error by turning the
NameError into an IndexError.


i dont get what you mean, if i dont do anything python will raise an
indexerror so it is an indexerror.
Jul 13 '08 #3

P: n/a
ssecorp <ci**********@gmail.comwrote:
i dont get what you mean, if i dont do anything python will raise an
indexerror so it is an indexerror.
You wrote:
* * def pop(self):
* * * * try:
* * * * * * return self.queue.pop(0)
* * * * except:
* * * * * * raise IndexError, "pop from empty queue"
You are assuming that the only possible exception that can be thrown by
"return self.queue.pop(0)" is IndexError. Maybe, maybe not. I gave you
one example of how something else could be thrown -- a typo in your code
leading to a NameError. Maybe even something more exotic like MemoryError?

The defensive thing to do is catch exactly the exception you expect to
happen. In this case, that means IndexError.
Jul 13 '08 #4

P: n/a
ssecorp <ci**********@gmail.comwrites:
Is this correct use of exceptions? to raise an indexerror and add my
own string insetad of just letting it raise a IndexError by itself
and "blaming" it on list.pop?

class Stack(object):
def __init__(self, *items):
self.stack = list(items)
If you are passing a sequence conceptually, then it's more Pythonic to
pass it as a sequence explicitly::

def __init__(self, items):
""" Call with e.g. Stack(["foo", "bar"]) """
self.stack = list(items)
def pop(self):
try:
return self.stack.pop()
except:
raise IndexError, "pop from empty stack"
Don't use this form of 'raise', it's deprecated. Instead, create the
exception instance with the arguments::

raise IndexError("pop from empty stack")

Don't use a bare 'except'; you will thereby catch *all* exceptions in
the 'try' block, masking errors you did not expect to handle, making
debugging unnecessarily difficult. Instead, always be explicit about
*which* exceptions you're handling here.

Don't catch the exception only to raise a new one; the context of the
original exception is lost. If all you want to do is have a different
message, modify the existing exception instance's args and re-raise
it.

try:
return self.stack.pop()
except IndexError, exc:
exc.args = ["pop from empty stack"]
raise

--
\ “Experience is that marvelous thing that enables you to |
`\ recognize a mistake when you make it again.” —Franklin P. Jones |
_o__) |
Ben Finney
Jul 13 '08 #5

P: n/a
Roy Smith <ro*@panix.comwrites:
ssecorp <ci**********@gmail.comwrote:
>i dont get what you mean, if i dont do anything python will raise an
indexerror so it is an indexerror.

You wrote:
* * def pop(self):
* * * * try:
* * * * * * return self.queue.pop(0)
* * * * except:
* * * * * * raise IndexError, "pop from empty queue"

You are assuming that the only possible exception that can be thrown by
"return self.queue.pop(0)" is IndexError. Maybe, maybe not. I gave you
one example of how something else could be thrown -- a typo in your code
leading to a NameError. Maybe even something more exotic like MemoryError?

The defensive thing to do is catch exactly the exception you expect to
happen. In this case, that means IndexError.
And you do that by

except IndexError:
raise TheErrorYouNowWantToRaise

And
except IndexError, e:

if you want access to the exception as well.
Jul 13 '08 #6

P: n/a
Bart Kastermans <ka******@bart-kastermanss-macbook.localwrites:
Roy Smith <ro*@panix.comwrites:
The defensive thing to do is catch exactly the exception you
expect to happen. In this case, that means IndexError.

And you do that by

except IndexError:
raise TheErrorYouNowWantToRaise
You only do that if you want to throw away important information, such
as the traceback associated with the original exception. Not very
friendly to debugging.
And
except IndexError, e:

if you want access to the exception as well.
Usually best if it can be achieved. Not least because the bare 'raise'
statement will re-raise the original exception, complete with all its
context.

--
\ “If we don't believe in freedom of expression for people we |
`\ despise, we don't believe in it at all.” —Noam Chomsky, |
_o__) 1992-11-25 |
Ben Finney
Jul 13 '08 #7

P: n/a
Ben Finney <bi****************@benfinney.id.auwrote:
If you are passing a sequence conceptually, then it's more Pythonic to
pass it as a sequence explicitly::

def __init__(self, items):
""" Call with e.g. Stack(["foo", "bar"]) """
self.stack = list(items)
I don't get this. You're forcing a copy to be made of the list. This
changes the semantics of the original class, because the operations no
longer change the original list. That may or may not be what you want.
It's a design decision, not a "doing it this way is more pythonic" kind of
thing.
Jul 13 '08 #8

P: n/a
Roy Smith <ro*@panix.comwrites:
Ben Finney <bi****************@benfinney.id.auwrote:
If you are passing a sequence conceptually, then it's more Pythonic to
pass it as a sequence explicitly::

def __init__(self, items):
""" Call with e.g. Stack(["foo", "bar"]) """
self.stack = list(items)

I don't get this. You're forcing a copy to be made of the list.
The 'items' object might not be a list; it might be some other
sequence. The rest of the class (as shown by the original poster)
requires it to be a list.
This changes the semantics of the original class, because the
operations no longer change the original list.
Which "original class" are you referring to? The one posted by the
original poster of this thread had no "original list"; it gathered the
positional arguments (using '*items') into an 'items' parameter, which
*doesn't exist* until the function body executes.

There *is* no "original list" in that implementation posed by the
original poster; it's constructed at call time from the positional
parameters to the function.

If anything, my implementation above *preserves* that semantic, by
making a new list from the passed-in sequence.

--
\ “Consider the daffodil. And while you're doing that, I'll be |
`\ over here, looking through your stuff.” —Jack Handey |
_o__) |
Ben Finney
Jul 13 '08 #9

P: n/a
In article <87************@benfinney.id.au>,
Ben Finney <bi****************@benfinney.id.auwrote:
Which "original class" are you referring to? The one posted by the
original poster of this thread had no "original list"; it gathered the
positional arguments (using '*items') into an 'items' parameter, which
*doesn't exist* until the function body executes.
Ah, I didn't notice that.
Jul 13 '08 #10

This discussion thread is closed

Replies have been disabled for this discussion.