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

Discussion in 'Python' started by John Salerno, Jul 27, 2006.

  1. John Salerno

    John Salerno Guest

    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.wav'))


    class MyApp(wx.App):

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


    if __name__ == '__main__':
    app = MyApp(False)
    app.MainLoop()
    John Salerno, Jul 27, 2006
    #1
    1. Advertising

  2. 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.wav'))
    >
    >
    > class MyApp(wx.App):
    >
    > def OnInit(self):
    > frame = MyTimer()
    > self.SetTopWindow(frame)
    > frame.Show()
    > return True
    >
    >
    > if __name__ == '__main__':
    > app = MyApp(False)
    > app.MainLoop()
    Nick Vatamaniuc, Jul 27, 2006
    #2
    1. Advertising

  3. 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.
    John McMonagle, Jul 27, 2006
    #3
  4. John Salerno

    John Salerno Guest

    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!
    John Salerno, Jul 28, 2006
    #4
  5. John Salerno

    John Salerno Guest

    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.
    John Salerno, Jul 28, 2006
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Salerno
    Replies:
    20
    Views:
    843
    John Salerno
    Aug 11, 2006
  2. Ed Jensen

    try/except/else/finally problem

    Ed Jensen, Jun 28, 2007, in forum: Python
    Replies:
    5
    Views:
    445
    Ben Finney
    Jun 29, 2007
  3. Fabio Z Tessitore

    who is simpler? try/except/else or try/except

    Fabio Z Tessitore, Aug 12, 2007, in forum: Python
    Replies:
    5
    Views:
    367
  4. kj
    Replies:
    15
    Views:
    548
    Lawrence D'Oliveiro
    May 23, 2009
  5. David House

    try -> except -> else -> except?

    David House, Jul 6, 2009, in forum: Python
    Replies:
    2
    Views:
    332
    Bruno Desthuilliers
    Jul 6, 2009
Loading...

Share This Page