Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > how best to check a value? (if/else or try/except?)

Reply
Thread Tools

how best to check a value? (if/else or try/except?)

 
 
John Salerno
Guest
Posts: n/a
 
      07-27-2006
My code is below. The main focus would be on the OnStart method. I want
to make sure that a positive integer is entered in the input box. At
first I tried an if/else clause, then switched to try/except. Neither is
perfect yet, but I was wondering which I should try for in the first
place. I figure I need to check for an emptry string, non-numeric
strings (maybe these are the same check), 0 and negative numbers (which
might also fall into the category of 'anything but a number' because of
the negative sign).

Thanks.

-------------------------------

import wx


class MyTimer(wx.Frame):

def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, 'Timer',
style=wx.DEFAULT_FRAME_STYLE ^
wx.RESIZE_BORDER ^ wx.MAXIMIZE_BOX)
panel = wx.Panel(self)

mainSizer = wx.BoxSizer(wx.VERTICAL)
inputSizer = wx.BoxSizer(wx.HORIZONTAL)

self.progress = wx.Gauge(panel, wx.ID_ANY, 100, size=(300, 20))
self.status = wx.StaticText(panel, wx.ID_ANY, 'Enter a time.')
prompt = wx.StaticText(panel, wx.ID_ANY, 'Time to wait:')
self.input = wx.TextCtrl(panel, wx.ID_ANY, size=(20, 20))
self.start = wx.Button(panel, wx.ID_ANY, 'Start')
self.reset = wx.Button(panel, wx.ID_ANY, 'Reset')
self.reset.Disable()
self.timer = wx.Timer(self)

mainSizer.Add(self.progress, flag=wx.ALIGN_CENTER | wx.ALL ^
wx.BOTTOM,
border=10)
mainSizer.Add(self.status, flag=wx.ALIGN_CENTER | wx.ALL,
border=10)
mainSizer.Add(inputSizer, flag=wx.ALIGN_CENTER | wx.BOTTOM,
border=10)
inputSizer.Add(prompt, flag=wx.ALIGN_CENTER)
inputSizer.Add(self.input, flag=wx.ALIGN_CENTER | wx.LEFT |
wx.RIGHT,
border=5)
inputSizer.Add(self.start, flag=wx.ALIGN_CENTER)
inputSizer.Add(self.reset, flag=wx.ALIGN_CENTER)

self.Bind(wx.EVT_TEXT_ENTER, self.OnStart, self.input)
self.Bind(wx.EVT_BUTTON, self.OnStart, self.start)
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
self.Bind(wx.EVT_BUTTON, self.OnReset, self.reset)

panel.SetSizer(mainSizer)
mainSizer.Fit(self)

def OnStart(self, event):
try:
self.time = int(self.input.GetValue())
self.minutes_passed = 1
self.minutes_remaining = self.time - 1
self.start.Disable()
self.input.Disable()
self.reset.Enable()
self.status.SetLabel('%s minute(s) remaining.' % self.time)
self.timer.Start(1000)
except ValueError:
wx.MessageBox('Enter a valid time.', 'Invalid time entered',
wx.OK | wx.ICON_ERROR)
self.input.Clear()

def OnReset(self, event):
if self.timer.IsRunning():
self.timer.Stop()
self.input.Clear()
self.input.Enable()
self.start.Enable()
self.reset.Disable()
self.status.SetLabel('Enter a new time.')
self.progress.SetValue(0)
self.minutes_passed = 1

def OnTimer(self, event):
if self.minutes_remaining != 0:
self.progress.SetValue(self.minutes_passed * (100.0 /
self.time))
self.status.SetLabel('%s minute(s) remaining.' %
self.minutes_remaining)
self.minutes_passed += 1
self.minutes_remaining -= 1
else:
self.timer.Stop()
self.progress.SetValue(self.minutes_passed * (100.0 /
self.time))
self.status.SetLabel('%s minute(s) have elapsed.' % self.time)
wx.Sound.Play(wx.Sound(r'C:\Windows\Media\notify.w av'))


class MyApp(wx.App):

def OnInit(self):
frame = MyTimer()
self.SetTopWindow(frame)
frame.Show()
return True


if __name__ == '__main__':
app = MyApp(False)
app.MainLoop()
 
Reply With Quote
 
 
 
 
Nick Vatamaniuc
Guest
Posts: n/a
 
      07-27-2006
John,

The way I do it is, is I ask myself 'is there a more common (basic)
base between the code paths or do they both have about a 50/50 chance
on average?' or 'will one code path be taken during an error and the
other one during the normal processing?'. If there is a clear single
common/usual/basic case or I try to detect an error I use 'try/except',
if it could go either way on average I use 'if'.

In general in Python we follow the 'it is better to ask forgiveness
than to ask permission'. In other words if you don't know if a piece
of data you have is a function and is callable you just call it and if
it raises an exception then you'll know it's not. This is the opposite
of C where you have to spend a good deal of time validating your input
arguments before you can safely continue.

That said, Python is also a practical language and quite often if you
do just one check then an 'if' may take 2 lines (if no need for else)
while a try/except will take 4 lines. So just apply common sense. For
example, I want to find out if I can call f then do some stuff if that
is the case:
try:
f(arg)
#...do stuff because f is callable...
except TypeError:
pass
# ... if f is not callable, then I don't care...

But of course it is much shorter to do:
if callable(f):
#...do stuff because f is callable...

Hope this helps,
Nick Vatamaniuc





John Salerno wrote:
> My code is below. The main focus would be on the OnStart method. I want
> to make sure that a positive integer is entered in the input box. At
> first I tried an if/else clause, then switched to try/except. Neither is
> perfect yet, but I was wondering which I should try for in the first
> place. I figure I need to check for an emptry string, non-numeric
> strings (maybe these are the same check), 0 and negative numbers (which
> might also fall into the category of 'anything but a number' because of
> the negative sign).
>
> Thanks.
>
> -------------------------------
>
> import wx
>
>
> class MyTimer(wx.Frame):
>
> def __init__(self):
> wx.Frame.__init__(self, None, wx.ID_ANY, 'Timer',
> style=wx.DEFAULT_FRAME_STYLE ^
> wx.RESIZE_BORDER ^ wx.MAXIMIZE_BOX)
> panel = wx.Panel(self)
>
> mainSizer = wx.BoxSizer(wx.VERTICAL)
> inputSizer = wx.BoxSizer(wx.HORIZONTAL)
>
> self.progress = wx.Gauge(panel, wx.ID_ANY, 100, size=(300, 20))
> self.status = wx.StaticText(panel, wx.ID_ANY, 'Enter a time.')
> prompt = wx.StaticText(panel, wx.ID_ANY, 'Time to wait:')
> self.input = wx.TextCtrl(panel, wx.ID_ANY, size=(20, 20))
> self.start = wx.Button(panel, wx.ID_ANY, 'Start')
> self.reset = wx.Button(panel, wx.ID_ANY, 'Reset')
> self.reset.Disable()
> self.timer = wx.Timer(self)
>
> mainSizer.Add(self.progress, flag=wx.ALIGN_CENTER | wx.ALL ^
> wx.BOTTOM,
> border=10)
> mainSizer.Add(self.status, flag=wx.ALIGN_CENTER | wx.ALL,
> border=10)
> mainSizer.Add(inputSizer, flag=wx.ALIGN_CENTER | wx.BOTTOM,
> border=10)
> inputSizer.Add(prompt, flag=wx.ALIGN_CENTER)
> inputSizer.Add(self.input, flag=wx.ALIGN_CENTER | wx.LEFT |
> wx.RIGHT,
> border=5)
> inputSizer.Add(self.start, flag=wx.ALIGN_CENTER)
> inputSizer.Add(self.reset, flag=wx.ALIGN_CENTER)
>
> self.Bind(wx.EVT_TEXT_ENTER, self.OnStart, self.input)
> self.Bind(wx.EVT_BUTTON, self.OnStart, self.start)
> self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
> self.Bind(wx.EVT_BUTTON, self.OnReset, self.reset)
>
> panel.SetSizer(mainSizer)
> mainSizer.Fit(self)
>
> def OnStart(self, event):
> try:
> self.time = int(self.input.GetValue())
> self.minutes_passed = 1
> self.minutes_remaining = self.time - 1
> self.start.Disable()
> self.input.Disable()
> self.reset.Enable()
> self.status.SetLabel('%s minute(s) remaining.' % self.time)
> self.timer.Start(1000)
> except ValueError:
> wx.MessageBox('Enter a valid time.', 'Invalid time entered',
> wx.OK | wx.ICON_ERROR)
> self.input.Clear()
>
> def OnReset(self, event):
> if self.timer.IsRunning():
> self.timer.Stop()
> self.input.Clear()
> self.input.Enable()
> self.start.Enable()
> self.reset.Disable()
> self.status.SetLabel('Enter a new time.')
> self.progress.SetValue(0)
> self.minutes_passed = 1
>
> def OnTimer(self, event):
> if self.minutes_remaining != 0:
> self.progress.SetValue(self.minutes_passed * (100.0 /
> self.time))
> self.status.SetLabel('%s minute(s) remaining.' %
> self.minutes_remaining)
> self.minutes_passed += 1
> self.minutes_remaining -= 1
> else:
> self.timer.Stop()
> self.progress.SetValue(self.minutes_passed * (100.0 /
> self.time))
> self.status.SetLabel('%s minute(s) have elapsed.' % self.time)
> wx.Sound.Play(wx.Sound(r'C:\Windows\Media\notify.w av'))
>
>
> class MyApp(wx.App):
>
> def OnInit(self):
> frame = MyTimer()
> self.SetTopWindow(frame)
> frame.Show()
> return True
>
>
> if __name__ == '__main__':
> app = MyApp(False)
> app.MainLoop()


 
Reply With Quote
 
 
 
 
John McMonagle
Guest
Posts: n/a
 
      07-27-2006
On Thu, 2006-07-27 at 20:44 +0000, John Salerno wrote:
> My code is below. The main focus would be on the OnStart method. I want
> to make sure that a positive integer is entered in the input box. At
> first I tried an if/else clause, then switched to try/except. Neither is
> perfect yet, but I was wondering which I should try for in the first
> place. I figure I need to check for an emptry string, non-numeric
> strings (maybe these are the same check), 0 and negative numbers (which
> might also fall into the category of 'anything but a number' because of
> the negative sign).
>


Have a look at using a wx.Validator in your wx.TextCtrl.


Syntax for wx.TextCtrl:

wx.TextCtrl(parent, id, value="", pos=wx.DefaultPosition,
size=wx.DefaultSize, style=0, validator=wx.DefaultValidator,
name=wx.TextCtrlNameStr)

This will enable you to automagically check the TextCtrl if it's empty,
has wrong data type, does not meet a prescribed condition (eg: no
negative numbers) and do something if it does not pass validation (eg:
colour the background of the TextCtrl red, initiate a system beep, etc).

Regards,

John



--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

 
Reply With Quote
 
John Salerno
Guest
Posts: n/a
 
      07-28-2006
John McMonagle wrote:

> Have a look at using a wx.Validator in your wx.TextCtrl.


Ah, good thinking! I wasn't even considering another option like that,
which probably makes more sense anyway!
 
Reply With Quote
 
John Salerno
Guest
Posts: n/a
 
      07-28-2006
Nick Vatamaniuc wrote:
> John,
>
> The way I do it is, is I ask myself 'is there a more common (basic)
> base between the code paths or do they both have about a 50/50 chance
> on average?' or 'will one code path be taken during an error and the
> other one during the normal processing?'. If there is a clear single
> common/usual/basic case or I try to detect an error I use 'try/except',
> if it could go either way on average I use 'if'.


Thanks, that's something good to think about. This issue came up once
before and I remember someone saying something like "you're using a
try/except statement, but i wouldn't really consider that situation
'exceptional'", so thinking of it in your terms might help a lot.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
how to selecet check box in the data grid ?? only one check box mit ASP .Net 1 01-25-2006 06:47 PM
how to check all check boxes in repeater control kris ASP .Net 0 09-22-2005 06:29 PM
how to check all check boxes in repeater control kris ASP .Net 0 09-22-2005 06:29 PM
.Net Pro include Visual Source Safe or other Code Check in Check out software? Davisro ASP .Net 1 06-14-2004 03:23 PM



Advertisments