Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Benefits of using enumerate?

Tags:

python

I'm a beginner at Python. I'm wondering is enumerate a more efficient way of doing this? Or does it not matter so much here, and really only comes into play when doing more complex things?

My code without enumerate:

for x in thing:
    if thing.index(x) % 2 == 0:
        x += 7
        print (x)
    else:
        print (x)

and my code using enumerate:

for index,x in enumerate(thing):
    if index % 2 == 0:
        x += 7
        print (x)
    else:
        print (x)
like image 709
Dovahkiin Avatar asked Oct 22 '16 19:10

Dovahkiin


2 Answers

list.index has a complexity of O(n) which means you'll be traversing the list more than twice (also considering the for loop itself), and it returns the first index of a given item, which means you'll get incorrect results for lists with duplicate items.

enumerate solves this by simply generating the indices and the items on the fly; I don't think you can get more performance than what the builtin enumerate provides.

Also keep in mind that enumerate is evaluated lazily; a huge plus for large lists. On the contrary, you don't want to call the index method of a large list, even if there were no duplicates in the list and the results were correct, you'll still be making unnecesary traversals across the list.

like image 90
Moses Koledoye Avatar answered Oct 19 '22 21:10

Moses Koledoye


If you're wondering about efficiency, there are several tools you can use to check which solution/algorithm is more efficient. This is called profiling.

The first aim of profiling is to test a representative system to identify what’s slow (or using too much RAM, or causing too much disk I/O or network I/O).

Profiling typically adds an overhead (10x to 100x slowdowns can be typical), and you still want your code to be used as similarly to in a real-world situation as possible. Extract a test case and isolate the piece of the system that you need to test. Preferably, it’ll have been written to be in its own set of modules already.

Basic techniques include the %timeit magic in IPython, time.time(), and a timing decorator (see example below). You can use these techniques to understand the behavior of statements and functions.

Then you have cProfile which will give you a high-level view of the problem so you can direct your attention to the critical functions.

Next, look at line_profiler, which will profile your chosen functions on a line-by-line basis. The result will include a count of the number of times each line is called and the percentage of time spent on each line. This is exactly the information you need to understand what’s running slowly and why.

perf stat helps you understand the number of instructions that are ultimately executed on a CPU and how efficiently the CPU’s caches are utilized. This allows for advanced-level tuning of matrix operations.

heapy can track all of the objects inside Python’s memory. This is great for hunting down strange memory leaks. If you’re working with long-running systems, then dowser will interest you: it allows you to introspect live objects in a long-running process via a web browser interface.

To help you understand why your RAM usage is high, check out memory_profiler. It is particularly useful for tracking RAM usage over time on a labeled chart, so you can explain to colleagues (or yourself) why certain functions use more RAM than expected.

Example: Defining a decorator to automate timing measurements

from functools import wraps

def timefn(fn):
    @wraps(fn)
    def measure_time(*args, **kwargs):
        t1 = time.time()
        result = fn(*args, **kwargs)
        t2 = time.time()
        print ("@timefn:" + fn.func_name + " took " + str(t2 - t1) + " seconds")
        return result
    return measure_time

@timefn
def your_func(var1, var2):
    ...

For more information, I suggest reading High performance Python (Micha Gorelick; Ian Ozsvald) from which the above was sourced.

like image 26
boardrider Avatar answered Oct 19 '22 19:10

boardrider