FAQ
I'm using a menu for my command line app using this method.

choice = "foobar"
while choice != "q":
if choice == "c":
temp = input("Celsius temperature:")
print "Fahrenheit:",celsius_to_fahrenheit(temp)
elif choice == "f":
temp = input("Fahrenheit temperature:")
print "Celsius:",fahrenheit_to_celsius(temp)
elif choice != "q":
print_options()
choice = raw_input("option:")

Just wondering if there is another or more efficient way I should be doing it?

Thanks
-- Braden Faulkner

Search Discussions

  • Rantingrick at Nov 4, 2010 at 2:03 am

    On Nov 3, 8:19?pm, braden faulkner wrote:

    Just wondering if there is another or more efficient way I should be doing it?

    I would move the input inside the respective methods or functions,
    short of that, what is more efficient than a conditional... nothing,
    and it reads very intuitively. Sure you could throw all the funcs into
    a dict and it may clean up a long winded conditional, however then you
    have to make a trade. So Zero Sum at that point.
  • Ben Finney at Nov 4, 2010 at 2:03 am

    braden faulkner <brf256 at gmail.com> writes:

    I'm using a menu for my command line app using this method.

    choice = "foobar"
    The default choice for a ?nothing here yet? value is the built-in
    ?None?.

    Sometimes that's not the right choice; but if you have no particular
    reaason in a specific program to avoid ?None? for that purpose, use it.
    while choice != "q":
    if choice == "c":
    temp = input("Celsius temperature:")
    print "Fahrenheit:",celsius_to_fahrenheit(temp)
    elif choice == "f":
    temp = input("Fahrenheit temperature:")
    print "Celsius:",fahrenheit_to_celsius(temp)
    elif choice != "q":
    print_options()
    choice = raw_input("option:")
    Python lacks a ?case? statement. But it does have functions as
    first-class objects; you can treat functions as data.

    So your approach above, with a chain of if-elif-elif clauses, is best
    replaced by a dispatch dictionary into functions specific to each
    command.

    Here's my attempt at making it more Pythonic and maintainable::


    #! /usr/bin/python
    # -*- coding: utf-8 -*-

    import sys
    import textwrap

    def print_commands():
    commands_display = ", ".join(commands.keys())
    sys.stdout.write(textwrap.dedent("""\
    Valid commands are: %(commands_display)s.
    """) % vars())

    def quit():
    raise SystemExit()

    def celsius_to_fahrenheit(in_value):
    return ((in_value * (9.0/5) + 32.0))

    def fahrenheit_to_celsius(in_value):
    return ((in_value - 32.0) * (5.0/9))

    def prompt_and_convert_temperature(labels, conversion_func):
    (from_label, to_label) = labels
    input = float(raw_input("%(from_label)s: " % vars()))
    result = conversion_func(input)
    sys.stdout.write("%(to_label)s temperature: %(result)0.2f\n" % vars())

    commands = {
    'q': (lambda: quit()),
    'c': (lambda: prompt_and_convert_temperature(
    ["Celsius", "Fahrenheit"], celsius_to_fahrenheit)),
    'f': (lambda: prompt_and_convert_temperature(
    ["Fahrenheit", "Celsius"], fahrenheit_to_celsius)),
    }


    if __name__ == '__main__':
    choice = None
    while choice is None:
    choice = raw_input("Command: ")
    if choice in commands:
    commands[choice]()
    else:
    choice = None
    print_commands()

    --
    \ ?I am as agnostic about God as I am about fairies and the |
    `\ Flying Spaghetti Monster.? ?Richard Dawkins, 2006-10-13 |
    _o__) |
    Ben Finney
  • Ben Finney at Nov 4, 2010 at 3:06 am

    Ben Finney <ben+python at benfinney.id.au> writes:

    Here's my attempt at making it more Pythonic and maintainable:: [?]
    def celsius_to_fahrenheit(in_value):
    return ((in_value * (9.0/5) + 32.0))
    Hmm. I went a bit overboard with the parens. This is what I'd prefer::

    def celsius_to_fahrenheit(in_value):
    return (in_value * (9.0/5) + 32.0)

    --
    \ ?There's a certain part of the contented majority who love |
    `\ anybody who is worth a billion dollars.? ?John Kenneth |
    _o__) Galbraith, 1992-05-23 |
    Ben Finney
  • Arnaud Delobelle at Nov 4, 2010 at 7:15 am
    Ben Finney <ben+python at benfinney.id.au> writes:
    [...]
    commands = {
    'q': (lambda: quit()),
    'c': (lambda: prompt_and_convert_temperature(
    ["Celsius", "Fahrenheit"], celsius_to_fahrenheit)),
    'f': (lambda: prompt_and_convert_temperature(
    ["Fahrenheit", "Celsius"], fahrenheit_to_celsius)),
    None: print_commands,
    }


    if __name__ == '__main__':
    choice = None
    while choice is None:
    choice = raw_input("Command: ")
    commands.get(choice)()


    --
    Arnaud
  • Ben Finney at Nov 4, 2010 at 11:33 am

    Arnaud Delobelle <arnodel at gmail.com> writes:

    Ben Finney <ben+python at benfinney.id.au> writes:
    [...]
    commands = {
    'q': (lambda: quit()),
    'c': (lambda: prompt_and_convert_temperature(
    ["Celsius", "Fahrenheit"], celsius_to_fahrenheit)),
    'f': (lambda: prompt_and_convert_temperature(
    ["Fahrenheit", "Celsius"], fahrenheit_to_celsius)),
    None: print_commands,
    This would be counter to the problem as stated by the OP. The program
    originally described loops *only* if no other command is specified;
    yours doesn't distinguish.

    --
    \ ?It is far better to grasp the universe as it really is than to |
    `\ persist in delusion, however satisfying and reassuring.? ?Carl |
    _o__) Sagan |
    Ben Finney
  • MRAB at Nov 4, 2010 at 2:13 am

    On 04/11/2010 01:19, braden faulkner wrote:
    I'm using a menu for my command line app using this method.

    choice = "foobar"
    while choice != "q":
    if choice == "c":
    temp = input("Celsius temperature:")
    print "Fahrenheit:",celsius_to_fahrenheit(temp)
    elif choice == "f":
    temp = input("Fahrenheit temperature:")
    print "Celsius:",fahrenheit_to_celsius(temp)
    elif choice != "q":
    print_options()
    choice = raw_input("option:")

    Just wondering if there is another or more efficient way I should be doing it?
    Here's an alternative:

    def option_c():
    temp = input("Celsius temperature:")
    print "Fahrenheit:", celsius_to_fahrenheit(temp)

    def option_f():
    temp = input("Fahrenheit temperature:")
    print "Celsius:", fahrenheit_to_celsius(temp)

    options = {"c": option_c, "f": option_f}
    while True:
    choice = raw_input("option:")
    if choice == "q":
    break
    options.get(choice, print_options)()
  • Tim Harig at Nov 4, 2010 at 2:19 am

    On 2010-11-04, braden faulkner wrote:
    I'm using a menu for my command line app using this method.

    choice = "foobar"
    while choice != "q":
    if choice == "c":
    temp = input("Celsius temperature:")
    print "Fahrenheit:",celsius_to_fahrenheit(temp)
    elif choice == "f":
    temp = input("Fahrenheit temperature:")
    print "Celsius:",fahrenheit_to_celsius(temp)
    elif choice != "q":
    print_options()
    choice = raw_input("option:")

    Just wondering if there is another or more efficient way I should be doing it?
    You are looking for a dictionary with function references maybe?

    menu_options = {
    'c':io_celsius_to_fahrenheit,
    'f':io_fahrenheit_to_celsisus,
    'q':print_options
    }

    The io versions of the functions would wrap the conversion functions to get
    the input and print the output.

    choice = "foobar"
    while choice != 'q':
    try:
    menu_options[choice]()
    except KeyError:
    # else code here
    choice = raw_input("option:")
  • Brf256 at Nov 4, 2010 at 2:25 am
    Thanks for the help! Ill incorporate this into my menu.

    Thanks again,
    Braden Faulkner

    Sent wirelessly from my BlackBerry device on the Bell network.
    Envoy? sans fil par mon terminal mobile BlackBerry sur le r?seau de Bell.
  • Carl Banks at Nov 4, 2010 at 3:02 am

    On Nov 3, 6:19?pm, braden faulkner wrote:
    I'm using a menu for my command line app using this method.

    choice = "foobar"
    while choice != "q":
    ? ? if choice == "c":
    ? ? ? ? temp = input("Celsius temperature:")
    ? ? ? ? print "Fahrenheit:",celsius_to_fahrenheit(temp)
    ? ? elif choice == "f":
    ? ? ? ? temp = input("Fahrenheit temperature:")
    ? ? ? ? print "Celsius:",fahrenheit_to_celsius(temp)
    ? ? elif choice != "q":
    ? ? ? ? print_options()
    ? ? choice = raw_input("option:")

    Just wondering if there is another or more efficient way I should be doing it?
    You're not even close to the point where you have to start worrying
    about efficiency.

    If you're at a point where efficiency matters, then by that point you
    should have long ago refactored it into a function-call dispatch
    (which is what others have posted) for the sake of organizing code.

    For this program, what you have it fine.


    Carl Banks
  • Michele Simionato at Nov 4, 2010 at 10:40 am

    On Nov 4, 2:19?am, braden faulkner wrote:
    I'm using a menu for my command line app using this method.

    choice = "foobar"
    while choice != "q":
    ? ? if choice == "c":
    ? ? ? ? temp = input("Celsius temperature:")
    ? ? ? ? print "Fahrenheit:",celsius_to_fahrenheit(temp)
    ? ? elif choice == "f":
    ? ? ? ? temp = input("Fahrenheit temperature:")
    ? ? ? ? print "Celsius:",fahrenheit_to_celsius(temp)
    ? ? elif choice != "q":
    ? ? ? ? print_options()
    ? ? choice = raw_input("option:")

    Just wondering if there is another or more efficient way I should be doing it?

    Thanks
    -- Braden Faulkner
    Here is a solution using plac (http://pypi.python.org/pypi/plac):

    $ echo c2f.py

    import plac

    class Converter(object):
    commands = ['celsius_to_fahrenheit', 'fahrenheit_to_celsius']

    @plac.annotations(t='convert Celsius to Fahrenheit')
    def celsius_to_fahrenheit(self, t):
    return round(32 + float(t) * 9/5)

    @plac.annotations(t='convert Fahrenheit to Celsius')
    def fahrenheit_to_celsius(self, t):
    return round((float(t) - 32) * 5 / 9.0)

    if __name__ == '__main__':
    import plac; plac.Interpreter.call(Converter)


    Here is an example of non-interactive usage:

    $ python c2f.py fahrenheit_to_celsius 212
    100.0
    $ python c2f.py celsius_to_fahrenheit 100
    212.0

    Here is an example of interactive usage:$ python c2f.py -i

    i> celsius_to_fahrenheit 100
    212.0
    i> celsius_to_fahrenheit 0
    32.0
    i> fahrenheit_to_celsius 32
    0.0
    i> fahrenheit_to_celsius 212
    100.0
  • Ben Finney at Nov 4, 2010 at 11:35 am

    brf256 at gmail.com writes:

    Thanks again,
    Braden Faulkner

    Sent wirelessly from my BlackBerry device on the Bell network.
    Envoy? sans fil par mon terminal mobile BlackBerry sur le r?seau de Bell.
    Please show your thanks by *not* spamming the forum with each message;
    compose your messages from a mail client that doesn't feel the need to
    blather about itself in the message body.

    --
    \ ?For fast acting relief, try slowing down.? ?Jane Wagner, via |
    `\ Lily Tomlin |
    _o__) |
    Ben Finney
  • Ned Deily at Nov 4, 2010 at 7:12 pm
    In article <87wrotfhj2.fsf at benfinney.id.au>,
    Ben Finney wrote:
    brf256 at gmail.com writes:
    Thanks again,
    Braden Faulkner

    Sent wirelessly from my BlackBerry device on the Bell network.
    Envoy? sans fil par mon terminal mobile BlackBerry sur le r?seau de Bell.
    Please show your thanks by *not* spamming the forum with each message;
    compose your messages from a mail client that doesn't feel the need to
    blather about itself in the message body.

    --
    \ ?For fast acting relief, try slowing down.? ?Jane Wagner, via |
    `\ Lily Tomlin |
    _o__) |
    Ben Finney
    If I were a rude person, I might observe that "spamming" is relative:
    some who obsess about "spam" might consider 2 lines less of an evil than
    5 lines.

    But I'm not, so I won't.

    --
    Ned Deily,
    nad at acm.org
  • Grant Edwards at Nov 4, 2010 at 7:46 pm

    On 2010-11-04, Ned Deily wrote:
    Ben Finney wrote:
    brf256 at gmail.com writes:
    Thanks again,
    Braden Faulkner

    Sent wirelessly from my BlackBerry device on the Bell network.
    Envoy?? sans fil par mon terminal mobile BlackBerry sur le r??seau de Bell.
    Please show your thanks by *not* spamming the forum with each message;
    compose your messages from a mail client that doesn't feel the need to
    blather about itself in the message body.

    --
    \ ???For fast acting relief, try slowing down.??? ???Jane Wagner, via |
    `\ Lily Tomlin |
    _o__) |
    Ben Finney
    If I were a rude person, I might observe that "spamming" is relative:
    some who obsess about "spam" might consider 2 lines less of an evil than
    5 lines.

    But I'm not, so I won't.
    I must admit that I sympathise with Ben: I find those "sent from my
    iphone/blackberry" lines exruciatingly annoying, and I'm not really
    sure why.

    They waste less space than my (or Ben's) sig, and actually do convey
    some sort of (pointless) information -- unlike randomly chosen
    Zippy-the-pinhead quotes.

    Still, I find them very smug, self-satisfied and irritating. Sort of
    like those doors from the Serious Cybernetics Corporation.

    I don't know whether it's that somebody is bragging about having a
    blackberry/iphone (whoop-de-friggin-do!), or that having one is
    somehow a valid excuse for poorly-written postings. I'm not
    specifically accusing Braden Faulkner of posting badly written
    articles, but it does seem to be a trend among people who use iphones
    and blackberrys to post.

    --
    Grant Edwards grant.b.edwards Yow! I didn't order any
    at WOO-WOO ... Maybe a YUBBA
    gmail.com ... But no WOO-WOO!


    Posted from my Linux computer using mutt!
  • D'Arcy J.M. Cain at Nov 4, 2010 at 8:11 pm

    On Thu, 4 Nov 2010 19:46:28 +0000 (UTC) Grant Edwards wrote:
    I don't know whether it's that somebody is bragging about having a
    blackberry/iphone (whoop-de-friggin-do!), or that having one is
    somehow a valid excuse for poorly-written postings. I'm not
    It's really just a matter of not knowing or caring how to change the
    default. Mine says "Sent from my brain".

    --
    D'Arcy J.M. Cain <darcy at druid.net> | Democracy is three wolves
    http://www.druid.net/darcy/ | and a sheep voting on
    +1 416 425 1212 (DoD#0082) (eNTP) | what's for dinner.
  • Braden faulkner at Nov 4, 2010 at 9:30 pm
    Sorry, I wasn't aware it was doing that but... I've removed it :-)

    Sorry about that,
    Braden Faulkner
  • Ben Finney at Nov 4, 2010 at 11:52 pm

    braden faulkner <brf256 at gmail.com> writes:

    Sorry, I wasn't aware it was doing that but... I've removed it :-)
    Thank you, it's good to keep a polite discourse going :-)

    --
    \ ?I don't accept the currently fashionable assertion that any |
    `\ view is automatically as worthy of respect as any equal and |
    _o__) opposite view.? ?Douglas Adams |
    Ben Finney
  • Peter Otten at Nov 4, 2010 at 11:49 am

    braden faulkner wrote:

    I'm using a menu for my command line app using this method.

    choice = "foobar"
    while choice != "q":
    if choice == "c":
    temp = input("Celsius temperature:")
    print "Fahrenheit:",celsius_to_fahrenheit(temp)
    elif choice == "f":
    temp = input("Fahrenheit temperature:")
    print "Celsius:",fahrenheit_to_celsius(temp)
    elif choice != "q":
    print_options()
    choice = raw_input("option:")

    Just wondering if there is another or more efficient way I should be doing
    it?
    The user interface will be slightly different, but the cmd module is great
    to build simple interactive command line apps quickly:

    # -*- coding: utf-8 -*-
    from __future__ import division
    import cmd

    class Cmd(cmd.Cmd):
    prompt = "Enter a command (? for help) --> "
    def do_celsius_to_fahrenheit(self, value):
    """Convert Celsius to Fahrenheit"""
    celsius = float(value)
    print u"%f ?F" % (celsius * 9/5 + 32)
    def do_fahrenheit_to_celsius(self, value):
    fahrenheit = float(value)
    print u"%f ?C" % ((fahrenheit - 32) * 5/9)
    def do_quit(self, value):
    return True
    do_EOF = do_quit

    Cmd().cmdloop()

    A sample session:

    $ python convert_temperature.py
    Enter a command (? for help) --> ?

    Documented commands (type help <topic>):
    ========================================
    celsius_to_fahrenheit

    Undocumented commands:
    ======================
    EOF fahrenheit_to_celsius help quit

    Enter a command (? for help) --> ? celsius_to_fahrenheit
    Convert Celsius to Fahrenheit
    Enter a command (? for help) --> celsius_to_fahrenheit 0
    32.000000 ?F
    Enter a command (? for help) --> fahrenheit_to_celsius 212
    100.000000 ?C
    Enter a command (? for help) --> quit
    $

    Peter
  • Terry Reedy at Nov 4, 2010 at 8:21 pm

    On 11/3/2010 9:19 PM, braden faulkner wrote:
    I'm using a menu for my command line app using this method.

    choice = "foobar"
    while choice != "q":
    if choice == "c":
    temp = input("Celsius temperature:")
    print "Fahrenheit:",celsius_to_fahrenheit(temp)
    elif choice == "f":
    temp = input("Fahrenheit temperature:")
    print "Celsius:",fahrenheit_to_celsius(temp)
    elif choice != "q":
    print_options()
    choice = raw_input("option:")

    Just wondering if there is another or more efficient way I should be doing it?
    Others have answered that, but I would point to the inefficiency for
    users of having to enter unit and value on two separate lines. The
    prompt could be "Enter value and unit (f, c, or k) or q to quit: "
    Allow upper and lower case, with or without a space between.

    --
    Terry Jan Reedy
  • Ben Finney at Nov 4, 2010 at 11:51 pm

    Terry Reedy <tjreedy at udel.edu> writes:

    Others have answered that, but I would point to the inefficiency for
    users of having to enter unit and value on two separate lines. The
    prompt could be "Enter value and unit (f, c, or k) or q to quit: "
    Allow upper and lower case, with or without a space between.
    Well, if we're going to critique the design, I'd say that I find the GNU
    Units program <URL:http://www.gnu.org/software/units/units.html> to be a
    good flexible implementation of a command-line units converter.

    I suspect, though, that the object of the OP was not so much to make a
    good unit converter, but rather to learn from a simple example exercise.

    --
    \ ?I am too firm in my consciousness of the marvelous to be ever |
    `\ fascinated by the mere supernatural ?? ?Joseph Conrad, _The |
    _o__) Shadow-Line_ |
    Ben Finney
  • Terry Reedy at Nov 5, 2010 at 3:15 am

    On 11/4/2010 7:51 PM, Ben Finney wrote:
    Terry Reedy<tjreedy at udel.edu> writes:
    Others have answered that, but I would point to the inefficiency for
    users of having to enter unit and value on two separate lines. The
    prompt could be "Enter value and unit (f, c, or k) or q to quit: "
    Allow upper and lower case, with or without a space between.
    Well, if we're going to critique the design, I'd say that I find the GNU
    Units program<URL:http://www.gnu.org/software/units/units.html> to be a
    good flexible implementation of a command-line units converter.

    I suspect, though, that the object of the OP was not so much to make a
    good unit converter, but rather to learn from a simple example exercise.
    Right. I think he would learn something from the exercize I suggest.

    --
    Terry Jan Reedy

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedNov 4, '10 at 1:19a
activeNov 5, '10 at 3:15a
posts21
users13
websitepython.org

People

Translate

site design / logo © 2022 Grokbase