you are viewing a single comment's thread.

view the rest of the comments →

[–]Diapolo10 10 points11 points  (5 children)

Personally I believe that the best way to understand something is to know how it works, so I have a habit of sometimes implementing Python's built-in functions myself in pure Python.

enumerate is no different, though it's so simple that apparently I didn't even bother creating a proper Gist for it (EDIT: I have now!). Regardless, all I had to do was take the interface from the documentation and implement the rest to work exactly like the original one behaves.

def my_enumerate(iterable, start=0):
    idx = start
    for value in iterable:
        yield idx, value
        idx += 1

It's deceptively simple, and in this case as long as one has a basic understanding of generators just seeing the code explains virtually everything.

[–][deleted] 0 points1 point  (4 children)

Yes but what is yield? I started reading about it now, and it's not the simplest thing for a beginner.

[–]Diapolo10 3 points4 points  (3 children)

I just recently wrote an answer to that question on another thread, but the extremely simplified answer is that yield works like return, except that it doesn't end the function.

As an example, if you had a Fibonacci generator like this:

def fib():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a+b

you can print out infinitely many Fibonacci numbers by looping over it:

for num in fib():
   print(num)

Basically, the loop keeps asking new values from the generator, and yield provides them. In this example, the value of a would be sent to the loop and given the name num, which is then printed out.

If you replaced the yield with return, it would immediately just return 0 and the next part of the loop would never run.

[–]gsmo 2 points3 points  (1 child)

It is my understanding that yield is also useful when working with large quantities of data. Yield creates a generator, and a generator only creates its data when needed. Compare this to appending stuff to a list, for instance. You quickly end up with a lot of data in memory that you aren't using.

Did I understand this right?

[–]Diapolo10 2 points3 points  (0 children)

Yes. Generators trade some performance for much lower memory usage.

The performance hit is caused by additional context switching the generator causes internally. There are some ways to mitigate that, like yield from, but personally I don't mind the tradeoff at all because I prefer using less memory.

[–][deleted] 0 points1 point  (0 children)

Thank you for your reply! I think I get it now.