3

I wrote two function f and g with same functionality

def f(l, count):
    if count > 1:
        for i in f(l, count-1):
            yield i + 1
    else:

        yield from l

for i in f(range(100000),900):
    pass
print('f')

and

def g(l, count):
    if count > 1:
        tmp = []
        for i in g(l, count-1):
            tmp.append(i+1)
        return tmp
    else:
        return l
for i in g(range(100000),900):
    pass
print('f')

and i I think f shuold be faster but g is faster when in run it

time for g

real    0m5.977s
user    0m5.956s
sys     0m0.020s

time for f

real    0m7.389s
user    0m7.376s
sys     0m0.012s
sahama
  • 669
  • 8
  • 16
  • 1
    I don't know python specifics. But in general context changes are more costly than function returns. – Alper Kucukkomurler Jan 16 '17 at 07:09
  • 1
    the `timeit` module should give you more precise results. and: in the `else` part you do 2 completely different things! in `g` you just return a reference to the list `l`; in `f` you iterate over the list and `yield` every item individually. also: what is your input list `l`? – hiro protagonist Jan 16 '17 at 07:10
  • 1
    Your sample code has an error. `for i in h(...` That should be `f`, not `h`. When I correct this and run the code on my computer I get the opposite results that you get. ` – Dunes Jan 16 '17 at 07:13
  • 1
    else part will run just one time and it can't consume much time – sahama Jan 16 '17 at 07:23
  • h(.. was a mistake. i edited it – sahama Jan 16 '17 at 07:27
  • Does python really accept `yield from l`? I don't think so, not my implementation of python at least. Always make sure that the code you post actually work (as described in the question). – skyking Jan 16 '17 at 07:51
  • 2
    @skyking: starting from python 3.3 you can `yield from` an iterable. – hiro protagonist Jan 16 '17 at 07:53
  • After replacing the `yield from` with older construct I got the opposite result. Just a slight improvement with yield on python3 and a larger difference on python2. – skyking Jan 16 '17 at 07:56
  • @hiroprotagonist That could explain it, I was running python 3.2:( – skyking Jan 16 '17 at 07:56

2 Answers2

9

There are a couple of big differences between a solution that yields a result and one that computes the complete result.

The yield keeps returning the next result until exhausted while the complete calculation is always done fully so if you had a test that might terminate your calculation early, (often the case), the yield method will only be called enough times to meet that criteria - this often results in faster code.

The yield result only consumes enough memory to hold the generator and a single result at any moment in time - the full calculation consumes enough memory to hold all of the results at once. When you get to really large data sets that can make the difference between something that runs regardless of the size and something that crashes.

So yield is slightly more expensive, per operation, but much more reliable and often faster in cases where you don't exhaust the results.

Steve Barnes
  • 27,618
  • 6
  • 63
  • 73
-4

I have no idea what your h and g functions are doing but remember this,

Yield is a keyword that is used like return, except the function will return a generator and that is the reason it takes time.

There is a wonderful explanation about what yeild does. Check this answer on stackoverflow.

Community
  • 1
  • 1
Harish Talanki
  • 866
  • 13
  • 27
  • i khow what yield does. it f function geted argument iterate just 1 time but in g function geted argument iterate about 900 time – sahama Jan 16 '17 at 07:25