Recommended use of Python dictionary, functions as values

I am looking for some help in understanding best practices regarding dictionaries in Python.

I have an example below:

def convert_to_celsius(temp, source): conversion_dict = { 'kelvin': temp - 273.15, 'romer': (temp - 7.5) * 40 / 21 } return conversion_dict[source] def convert_to_celsius_lambda(temp, source): conversion_dict = { 'kelvin': lambda x: x - 273.15, 'romer': lambda x: (x - 7.5) * 40 / 21 } return conversion_dict[source](temp) 

Obviously, two functions achieve the same goal, but using different means. Can someone help me understand the subtle difference between the two, and what is the โ€œbestโ€ way to do this?

+7
python
source share
4 answers

If you have both dictionaries created inside the function, then the first will be more efficient - although the first does two calculations when only one is required, the latest version has more overhead for creating a lambda every time it is called

 >>> import timeit >>> setup = "from __main__ import convert_to_celsius, convert_to_celsius_lambda, convert_to_celsius_lambda_once" >>> timeit.timeit("convert_to_celsius(100, 'kelvin')", setup=setup) 0.5716437913429102 >>> timeit.timeit("convert_to_celsius_lambda(100, 'kelvin')", setup=setup) 0.6484164544288618 

However, if you move the lambda dictionary out , the function:

 CONVERSION_DICT = { 'kelvin': lambda x: x - 273.15, 'romer': lambda x: (x - 7.5) * 40 / 21 } def convert_to_celsius_lambda_once(temp, source): return CONVERSION_DICT[source](temp) 

then the latter is more efficient, since lambda objects are created only once, and the function performs only the necessary calculations for each call:

 >>> timeit.timeit("convert_to_celsius_lambda_once(100, 'kelvin')", setup=setup) 0.3904035060131186 

Note that this will only be an advantage when the function is called a lot (in this case, 1,000,000 times), so the overhead of creating two objects of the lambda function is less than the time taken to calculate the two results when only one is needed.

+3
source share

The dictionary is completely meaningless, since you need to recreate it with every call, but all you do is the only search. Juse uses if :

 def convert_to_celsius(temp, source): if source == "kelvin": return temp - 273.15 elif source == "romer": return (temp - 7.5) * 40 / 21 raise KeyError("unknown temperature source '%s'" % source) 
+1
source share

Despite the fact that both achieve the same, the first part is more readable and faster.

In the first example, you have a simple arithmetic operation that will be calculated after calling convert_to_celsius .

In the second example, you only calculate the required temperature.

If your second function performed an expensive calculation, then it would probably be advisable to use the function instead, but this is not required for this specific example.

0
source share

As others have noted, none of your options are perfect. The first performs both calculations each time and has an unnecessary dict. The second should create lambdas every time. If this example is the goal, I agree to just use the if statement. If the goal is to learn something that can be expanded for other purposes, I like this approach:

 convert_to_celsius = { 'kelvin' : lambda temp: temp - 273.15 , 'romer' : lambda temp: (temp-7.5) * 40 / 21} newtemp = convert_to_celsius[source](temp) 

Your settlement rates are stored together, and your function call is idle and meaningful.

0
source share

All Articles