Aleksandr Zakirov Aleksandr Zakirov - 3 months ago 9
Python Question

How to create a list containing names of functions?

I am completely new to python and programming but I am trying to learn it using more practical approach.

What I am trying to do is an exercise for converting different units, e.g. pounds -> kilograms, foot -> meter etc.

I have defined all the functions for different unit pairs:

def kg_to_g(value):
return round(value*1000.0,2)
def g_to_kg(value):
return round(value/1000.0,2)
def inch_to_cm(value):
return round(value*2.54,2)
def cm_to_inch(value):
return round(value/2.54,2)
def ft_to_cm(value):
return round(value*30.48,2)


etc.

and created a list with names of these functions:

unit_list = ['kg_to_g','g_to_kg','inch_to_cm','cm_to_inch',
'ft_to_cm','cm_to_ft','yard_to_m','m_to_yard',
'mile_to_km','km_to_mile','oz_to_g','g_to_oz',
'pound_to_kg','kg_to_pound','stone_to_kg','kg_to_stone',
'pint_to_l','l_to_pint','quart_to_l','l_to_quart',
'gal_to_l','l_to_gal','bar_to_l','l_to_bar']


The program should randomly choose a unit pair(e.g. kg->pounds) and value (e.g. 134.23), and the user will be asked to convert those values.

random_unit = random.choice(unit_list)
lower = 0.1001
upper = 2000.1001
range_width = upper - lower
ranval = round(random.random() * range_width + lower, 2)


When user enters answer, the program should compare answer with the calculations defined by function and tell user if it is a correct answer or wrong answer:

def input_handler(answer):
if answer == random_unit(ranval):
label2.set_text("Correct!")
else:
label2.set_text("Wrong!")


Unfortunately, that way program doesn't work, and codesculptor(codesculptor.org) returns with an error

TypeError: 'str' object is not callable


Could someone please explain to me what is wrong with the code and suggest something to solve the problem.

Answer

Because you've enclosed the function names (in the list) in quotes, they have become strings.

Change your list to:

unit_list = [kg_to_g, g_to_kg, inch_to_cm, cm_to_inch,
         ft_to_cm, cm_to_ft, yard_to_m, m_to_yard,
         mile_to_km, km_to_mile, oz_to_g, g_to_oz,
         pound_to_kg, kg_to_pound, stone_to_kg, kg_to_stone,
         pint_to_l, l_to_pint, quart_to_l, l_to_quart,
         gal_to_l, l_to_gal, bar_to_l, l_to_bar]

And now it is a list of functions, which can be called like this: unit_list[0](34), for example.

So now random_unit(ranval) should not throw an exception.

Note also that comparing floats (if answer == random_unit(ranval)) will most likely cause you problems. See Is floating point math broken? for some detailed explanations of why this is.

As you are rounding you may get away with it, but it's good to be aware of this and understand that you need to deal with it in your code.