Correct use of try,except and raise?

S

ssecorp

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"
 
R

Roy Smith

ssecorp said:
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.
 
S

ssecorp

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.
 
R

Roy Smith

ssecorp said:
i dont get what you mean, if i dont do anything python will raise an
indexerror so it is an indexerror.

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.
 
B

Bart Kastermans

Roy Smith said:
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.
 
R

Roy Smith

Ben Finney said:
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.
 
R

Roy Smith

Ben Finney said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,000
Messages
2,570,252
Members
46,848
Latest member
CristineKo

Latest Threads

Top