Reputation: 1553
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
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
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