Snerd
Snerd

Reputation: 1553

Python input and exceptions vs. C++

I want to duplicate the following C++ code with input and exception handling as close as possible in a pythonic way. I achieved success but probably not exactly what I wanted. I would have liked to quit the program similar to the C++ way of inputting a random char, in this case it was a 'q'. The cin object in the while condition is different from the python way of making a while True. Also I want to know if the simple line on converting the 2 inputs to an int was the an adequate way. Finally, in the python code, the "bye!" never runs because of the EOF (control+z) method of forcing the app to close. There are quirks and overall I am pleased with the less code needed in python.

extra: if you look at the code in the last print statements, is that a good way to print var and strings together?

Any simple tricks/tips are are welcome.

C++

#include <iostream>

using namespace std;

double hmean(double a, double b);  //the harmonic mean of 2 numbers is defined as the invese of the average of the inverses.

int main()
{
    double x, y, z;
    cout << "Enter two numbers: ";

    while (cin >> x >> y)
    {
        try     //start of try block
        {
            z = hmean(x, y);
        }           //end of try block
        catch (const char * s)      //start of exception handler; char * s means that this handler matches a thrown exception that is a string
        {
            cout << s << endl;
            cout << "Enter a new pair of numbers: ";
            continue;       //skips the next statements in this while loop and asks for input again; jumps back to beginning again
        }                                       //end of handler
        cout << "Harmonic mean of " << x << " and " << y
            << " is " << z << endl;
        cout << "Enter next set of numbers <q to quit>: ";
    }
    cout << "Bye!\n";

    system("PAUSE");
    return 0;
}

double hmean(double a, double b)
{
    if (a == -b)
        throw "bad hmean() arguments: a = -b not allowed";
    return 2.0 * a * b / (a + b);
}

Python

class MyError(Exception):   #custom exception class
    pass

def hmean(a, b):
    if (a == -b):
        raise MyError("bad hmean() arguments: a = -b not allowed")  #raise similar to throw in C++?
    return 2 * a * b / (a + b);

print "Enter two numbers: "

while True:
    try:
        x, y = raw_input('> ').split() #enter a space between the 2 numbers; this is what .split() allows.
        x, y = int(x), int(y)   #convert string to int
        z = hmean(x, y)
    except MyError as error:
        print error
        print "Enter a new pair of numbers: "
        continue

    print "Harmonic mean of", x, 'and', y, 'is', z, #is this the most pythonic way using commas? 
    print "Enter next set of numbers <control + z to quit>: "   #force EOF

#print "Bye!" #not getting this far because of EOF

Upvotes: 1

Views: 2711

Answers (2)

Ulrich Eckhardt
Ulrich Eckhardt

Reputation: 17415

Here's a piece of code I'd like to toss at you. Something like it is not easily possible in C++, but it makes things much clearer in Python by separating concerns:

# so-called "generator" function
def read_two_numbers():
    """parse lines of user input into pairs of two numbers"""
    try:
        l = raw_input()
        x, y = l.split()
        yield float(x), float(y)
    except Exception:
        pass

for x, y in read_two_numbers():
    print('input = {}, {}'.format(x, y))
print('done.')

It uses a so-called generator function that only handles the input parsing to separate the input from the computations. This isn't "as close as possible" but rather "in a pythonic way" that you asked for, but I hope you will find this useful nonetheless. Also, I took the liberty to use floats instead of ints to represent the numbers.

One more thing: Upgrade to Python 3, version 2 isn't developed any more but merely receives bugfixes. If you don't depend on any libraries only available for Python 2, you shouldn't feel too much of a difference.

Upvotes: 1

A. Rodas
A. Rodas

Reputation: 20679

For the function hmean I would try to execute the return statement, and raise the exception if a equals -b:

def hmean(a, b):
    try:
        return 2 * a * b / (a + b)
    except ZeroDivisionError:
        raise MyError, "bad hmean() arguments: a = -b not allowed"

To interpolate variables in a string, the method format is a common alternative:

print "Harmonic mean of {} and {} is {}".format(x, y, z)

Finally, you might want to use an except block if a ValueError is raised when casting x or y to int.

Upvotes: 1

Related Questions