#!/usr/bin/env python # encoding: utf-8 """Test the speed of different kinds of for loops over lists of tuples. The general_test_function can be used to test the execution time of any number of functions. """ def test_speed_of_for_loop_with_tuples(): """This function tests the speed of two different for loops to see, if there's a difference. Result: There is no big difference between the two approaches. One run: [0.14503340959548949, 0.16319561004638672] Another run: [0.12981771707534789, 0.14054121494293212] Factor on another run: 1.1451155855 That's about 14 percent longer execution time for the loop which selects the second item inside the loop. On 3 more runs, I got factors between 4% and 10% TODO: Test, if the factors are related to the numbers inside the tuples. TODO: Test, if a test with Strings comes to the same result. """ # We need random numbers, so we can create unoptimizeable lists. from random import random # Now we need an empty list. many_tuples = [] # Which we fill with 100.000 tuples of random numbers. for i in range(100000): many_tuples.append((random(), random())) # Now we get to the real test. # We just call the functions in our test function :) # For this we first create a list of functions we want to test. list_of_functions = [loop_which_directly_calls_each_tuple_item, loop_which_calls_the_whole_tuple_and_then_selects_the_second_item] # And pass it to the general test function with our arg, 10 times. # Results is a list of lists of tuples. results = [] for i in range(10): results.append(general_test_function(list_of_functions, many_tuples)) # Calculate the mean mean_time = [] # Work on each result for i in results: # Get the times of this result as list. times_list = [] # Work on each function inside the single run to gets its time for j in i: # Append the time to the times_list. times_list.append(j[0]) # Now add the times in the times list to the mean_time. # If the times_list has a different length than the mean_time list, this should be the first run. We need to append the times. if len(times_list) != len(mean_time): for i in times_list: mean_time.append(i) # Else, this is a following run, so we can just add to each element. else: for i in range(len(times_list)): mean_time[i] += times_list[i] # Now we divide each element inside the mean_time by the number of runs (the len of the results. for i in range(len(mean_time)): mean_time[i] = float(mean_time[i]) / len(results) return mean_time # TODO: Calculate the standard deviation, so we know how certain the result is. def loop_which_directly_calls_each_tuple_item(many_tuples): """Call each item directly in the loop and return a list of the second item.TODO: Test, if it makes a difference if we call the first or the second item""" second_items = [] for i, j in many_tuples: second_items.append(j) return second_items def loop_which_calls_the_whole_tuple_and_then_selects_the_second_item(many_tuples): """Call the whole tuple in the loop and then select the second item when assigning.""" second_items = [] for i in many_tuples: second_items.append(i[1]) return second_items def general_test_function(functions, *args): """Compare the execution speed of different functions in the list of functions @functions: [function1, function2, ...]. @*args: The argument(s) to pass to each of the functions. All functions get all and the same argument(s)""" # We need the current time in seconds from time import time # First evaluate how long Python takes to get two times. We need to substract this value from the result to remove a constant offset. # Get the current time two times start_time = time() finish_time = time() # Now calculate the difference which is how long Python takes for getting the time. #: The offset due to getting the time two times. This is less than 1*10e-5 s for me. time_offset = finish_time - start_time # Get start and stop times of all functions and put them into a list of tuples: (time_needed, function) - time needed first, so we can sort easily. #: A list of functions with execution speed execution_times = [] for i in functions: # Start time of the function. start_time = time() # Execute the function with the given argument i(*args) # Get the finish time finish_time = time() # Get the difference time_needed = finish_time - start_time - time_offset # append the tuple of execution time and function to the list of execution_speeds. execution_times.append((time_needed, i)) # Return the list of execution times, sorted by functions. return execution_times ### Self-Test ### if __name__ == "__main__": # Test the speed for loops with tuples. # 10 times. print "10 Speedtests of for loops." for i in range(10): result = test_speed_of_for_loop_with_tuples() # print result # The factor can only be done this simply for testing two functions. factor = result[1] / result[0] print "Faktor:", factor # Test mother sorting code. # mothers = {"mother1": ["child1", "child2"], "mother2": ["child3"], "mother3": [], "mother4": [1, 2, 3]} # print sort_by_children(mothers) # print mothers # Or just do nothing. pass