Re: Basic question about speed/coding style/memory
Jan Riechers於 2012年7月21日星期六UTC+8下午3時33分27秒寫道: Hello Pythonlist, I have one very basic question about speed,memory friendly coding, and coding style of the following easy quot;ifquot;-statement in Python 2.7, but Im sure its also the same in Python 3.x Block #-- if statemente_true: if an evaluated expression result is non-zero, then doSomething() else: # execute this block if the expression evaluated as zero doSomethingElseInstead() #-- versus this block: #-- if statement_true: doSomething() return doSomethingElseInstead() #-- I understand the first pattern that I tell the interpreter to do: Check if the conditional is true, run quot;doSomething()quot; else go inside the else block and quot;doSomethingElseInstead()quot;. while the 2nd does only checks: doSomething() if statement_true, if not, just go directly to quot;doSomethingElseInstead() Now, very briefly, what is the better way to proceed in terms of execution speed, readability, coding style? Letting out the fact that, in order to prevent quot;doSomethingElseInsteadquot;-Block to execute, a return has to provided. Thank you for reading and hope someone brings light into that. Your fellow python programmer Jan Well, the C-style branching is inherited in python. Expressions and statements are different. -- http://mail.python.org/mailman/listinfo/python-list
Re: Basic question about speed/coding style/memory
Chris Angelico於 2012年7月21日星期六UTC+8下午5時04分12秒寫道: On Sat, Jul 21, 2012 at 5:33 PM, Jan Riechers lt;janpet...@freenet.degt; wrote: gt; Block gt; #-- gt; if statemente_true: gt; doSomething() gt; else: gt; doSomethingElseInstead() gt; gt; #-- This means, to me, that the two options are peers - you do this or you do that. gt; versus this block: gt; #-- gt; if statement_true: gt; doSomething() gt; return gt; gt; doSomethingElseInstead() gt; gt; #-- This would be for an early abort. Don#39;t bother doing most of this function#39;s work, just doSomething. Might be an error condition, or perhaps an optimized path. Definitely for error conditions, I would use the second option. The quot;fail and bailquot; notation keeps the entire error handling in one place: def func(x,y,z): if xlt;0: y+=5 return if ylt;0: raise PEBKAC(quot;There#39;s an idiot here somewherequot;) # ... do the rest of the work This is the caller responsible style when passing parameters to functions. Checking types of parameters both in the caller and the callee does slow down a little bit. Note the similarity between the control structures. Raising an exception immediately terminates processing, without polluting the rest of the function with an unnecessary indentation level. Early aborting through normal function return can do the same thing. But this is purely a matter of style. I don#39;t think there#39;s any significance in terms of processing time or memory usage, and even if there is, it would be dwarfed by considerations of readability. Make your code look like what it#39;s doing, and let the execution take care of itself. ChrisA -- http://mail.python.org/mailman/listinfo/python-list
Basic question about speed/coding style/memory
Hello Pythonlist, I have one very basic question about speed,memory friendly coding, and coding style of the following easy if-statement in Python 2.7, but Im sure its also the same in Python 3.x Block #-- if statemente_true: doSomething() else: doSomethingElseInstead() #-- versus this block: #-- if statement_true: doSomething() return doSomethingElseInstead() #-- I understand the first pattern that I tell the interpreter to do: Check if the conditional is true, run doSomething() else go inside the else block and doSomethingElseInstead(). while the 2nd does only checks: doSomething() if statement_true, if not, just go directly to doSomethingElseInstead() Now, very briefly, what is the better way to proceed in terms of execution speed, readability, coding style? Letting out the fact that, in order to prevent doSomethingElseInstead-Block to execute, a return has to provided. Thank you for reading and hope someone brings light into that. Your fellow python programmer Jan -- http://mail.python.org/mailman/listinfo/python-list
Re: Basic question about speed/coding style/memory
On 7/21/2012 2:33 AM, Jan Riechers wrote: Block ... versus this block: ... Now, very briefly, what is the better way to proceed in terms of execution speed, readability, coding style? Using if/else is the most readable in the general sense. Using return (or break or continue as applicable) in this manner would indicate (at least to me) that it's an exceptional or otherwise special case and that the function can't do what it's supposed to. In that case, I would try to catch an exception rather than use if/else whenever possible. I highly doubt there is a significant performance difference between them. -- CPython 3.3.0b1 | Windows NT 6.1.7601.17803 -- http://mail.python.org/mailman/listinfo/python-list
Re: Basic question about speed/coding style/memory
On 21.07.2012 11:02, Andrew Berg wrote: On 7/21/2012 2:33 AM, Jan Riechers wrote: Block ... versus this block: ... Now, very briefly, what is the better way to proceed in terms of execution speed, readability, coding style? Using if/else is the most readable in the general sense. Using return (or break or continue as applicable) in this manner would indicate (at least to me) that it's an exceptional or otherwise special case and that the function can't do what it's supposed to. In that case, I would try to catch an exception rather than use if/else whenever possible. I highly doubt there is a significant performance difference between them. Hello Andrew, Your answer is right, in other circumstances I also would stick to try/except, break-statements in loops and so forth. But the question was a bit more elementary. Cause, as I understand the interpreter chooses either the else (1st block) or just proceeds with following code outside the if. So if there is some overhead in some fashion in case we don't offer the else, assuming the interpreter has to exit the evaluation of the if-statement clause and return to a normal parsing code-state outside the if statement itself. I hope this explanation makes more sense in what I want to ask ;) Jan -- http://mail.python.org/mailman/listinfo/python-list
Re: Basic question about speed/coding style/memory
On Sat, Jul 21, 2012 at 5:33 PM, Jan Riechers janpet...@freenet.de wrote: Block #-- if statemente_true: doSomething() else: doSomethingElseInstead() #-- This means, to me, that the two options are peers - you do this or you do that. versus this block: #-- if statement_true: doSomething() return doSomethingElseInstead() #-- This would be for an early abort. Don't bother doing most of this function's work, just doSomething. Might be an error condition, or perhaps an optimized path. Definitely for error conditions, I would use the second option. The fail and bail notation keeps the entire error handling in one place: def func(x,y,z): if x0: y+=5 return if y0: raise PEBKAC(There's an idiot here somewhere) # ... do the rest of the work Note the similarity between the control structures. Raising an exception immediately terminates processing, without polluting the rest of the function with an unnecessary indentation level. Early aborting through normal function return can do the same thing. But this is purely a matter of style. I don't think there's any significance in terms of processing time or memory usage, and even if there is, it would be dwarfed by considerations of readability. Make your code look like what it's doing, and let the execution take care of itself. ChrisA -- http://mail.python.org/mailman/listinfo/python-list
Re: Basic question about speed/coding style/memory
On 7/21/2012 3:13 AM, Jan Riechers wrote: Cause, as I understand the interpreter chooses either the else (1st block) or just proceeds with following code outside the if. If none of the if/elif statements evaluate to something true, the else block is executed. So if there is some overhead in some fashion in case we don't offer the else, assuming the interpreter has to exit the evaluation of the if-statement clause and return to a normal parsing code-state outside the if statement itself. I really don't understand. You can look into the dis module if you want to look at how CPython bytecode is executed and the timeit module to measure speed. In any case, I don't see how there would be any significant difference. http://docs.python.org/py3k/library/dis.html http://docs.python.org/py3k/library/timeit.html -- CPython 3.3.0b1 | Windows NT 6.1.7601.17803 -- http://mail.python.org/mailman/listinfo/python-list
Re: Basic question about speed/coding style/memory
On Sat, 21 Jul 2012 10:33:27 +0300, Jan Riechers wrote: Hello Pythonlist, I have one very basic question about speed,memory friendly coding, and coding style of the following easy if-statement in Python 2.7, but Im sure its also the same in Python 3.x I assume that the following is meant to be inside a function, otherwise the return in the second example is illegal. But in general, you're worrying too much about trivia. One way or the other, any speed difference will be trivial. Write whatever style reads and writes most naturally, and only worry about what's faster where it actually counts. To give it an analogy that might be clear, this question is not too far from worrying about whether your car will be faster with the radio aerial up or down. Yes, technically the car will be slower with the aerial up, due to air resistance, but you'd have a job measuring it, and it makes no difference whether you are zooming down the highway at 120mph or stuck in traffic crawling along at 5mph. Here's a minimal example: def with_else(x): if x: a = x else: a = x+1 return a def without_else(x): if x: a = x return a a = x+1 return a Notice that I try to make each function do the same amount of work, so that we're seeing only the difference between else vs no else. Now let's test the speed difference with Python 2.7. Because this is timing small code snippets, we should use the timeit module to time the code: from timeit import Timer setup = from __main__ import with_else, without_else t1 = Timer(for i in (0, 1): result = with_else(i), setup) t2 = Timer(for i in (0, 1): result = without_else(i), setup) Each snippet calls the function twice, once to take the if branch, then to take the else branch. Now we time how long it takes to run each code snippet 100 times. We do that six times each, and print the best (lowest) speed: py min(t1.repeat(repeat=6)) 0.9761919975280762 py min(t2.repeat(repeat=6)) 0.9494419097900391 So there is approximately 0.03 second difference per TWO MILLION if...else blocks, or about 15 nanoseconds each. This is highly unlikely to be the bottleneck in your code. Assuming the difference is real, and not just measurement error, the difference is insignificant. So, don't worry about which is faster. Write whichever is more natural, easier to read and write. Block #-- if statemente_true: doSomething() else: doSomethingElseInstead() This style is especially recommended when the two clauses are equal in importance. versus this block: #-- if statement_true: doSomething() return doSomethingElseInstead() This style is especially recommended when the doSomethingElseInstead() block is the normal procedure, and the doSomething() block is a special case. Not necessarily rare, but nevertheless special in some sense. Of course, the decision as to which is the special case and which is the normal case is often entirely arbitrary. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Basic question about speed/coding style/memory
On 21.07.2012 12:06, Steven D'Aprano wrote: But in general, you're worrying too much about trivia. One way or the other, any speed difference will be trivial. Write whatever style reads and writes most naturally, and only worry about what's faster where it actually counts. Notice that I try to make each function do the same amount of work, so that we're seeing only the difference between else vs no else. Now let's test the speed difference with Python 2.7. Because this is timing small code snippets, we should use the timeit module to time the code: from timeit import Timer setup = from __main__ import with_else, without_else t1 = Timer(for i in (0, 1): result = with_else(i), setup) t2 = Timer(for i in (0, 1): result = without_else(i), setup) Each snippet calls the function twice, once to take the if branch, then to take the else branch. Now we time how long it takes to run each code snippet 100 times. We do that six times each, and print the best (lowest) speed: py min(t1.repeat(repeat=6)) 0.9761919975280762 py min(t2.repeat(repeat=6)) 0.9494419097900391 So there is approximately 0.03 second difference per TWO MILLION if...else blocks, or about 15 nanoseconds each. This is highly unlikely to be the bottleneck in your code. Assuming the difference is real, and not just measurement error, the difference is insignificant. So, don't worry about which is faster. Write whichever is more natural, easier to read and write. Hello Steven, very nice example and thank you very much for also for the Timeit test! Actually it confirms my assumption in some way: [SNIP myself] So if there is some overhead in some fashion in case we don't offer the else, assuming the interpreter has to exit the evaluation of the if-statement clause and return to a normal parsing code-state outside the if statement itself. [SNAP] Without having looked at Andrew's bytecode excecution hint, using the dis module, to see how the interpreter handles the task on lower level. But fare enough for me :) But I agree, the return in my example is misleading and it would be illegal outside of a function call. I just added it to make clear that the fellow code below the return should not be executed in comparison to the 2nd example. Thank you very much Jan -- http://mail.python.org/mailman/listinfo/python-list
Re: Basic question about speed/coding style/memory
Jan Riechers wrote: I have one very basic question about speed,memory friendly coding, and coding style of the following easy if-statement in Python 2.7, but Im sure its also the same in Python 3.x Block #-- if statemente_true: doSomething() else: doSomethingElseInstead() #-- versus this block: #-- if statement_true: doSomething() return doSomethingElseInstead() #-- I understand the first pattern that I tell the interpreter to do: A common misconception. As a writer of Python source code, (usually) you never tell the (CPython) interpreter anything (but to start working on the source code). Python source code is automatically *compiled* into bytecode by the (CPython) interpreter, and that bytecode is executed by a virtual machine.¹ So at most, you are telling that virtual machine to do something, through the bytecode created from your source code. Check if the conditional is true, run doSomething() else go inside the else block and doSomethingElseInstead(). while the 2nd does only checks: doSomething() if statement_true, if not, just go directly to doSomethingElseInstead() Now, very briefly, what is the better way to proceed in terms of execution speed, readability, coding style? Since this is comp.lang.python, you just need to check against the Zen of Python to know what you should do ;-) http://www.python.org/dev/peps/pep-0020/ For me, this boils down in this case to the common recommendation return early, return often as explicit is better than implicit and readability counts. If there is nothing else than the `else' block in the function, there is no use for you to continue in the function, so you should return explicitly at this point. On the other hand, if you can *avoid repeating code* in each branch by _not_ returning in the first branch, you should do that instead (practicality beats purity). HTH _ ¹ This is not unlike in other so-called scripting languages; although for reasons that escape me, the software that compiles the source code – the compiler – is called the (C)Python *interpreter*, even in http://docs.python.org/faq/general.html. -- PointedEars Please do not Cc: me. / Bitte keine Kopien per E-Mail. -- http://mail.python.org/mailman/listinfo/python-list
Re: Basic question about speed/coding style/memory
On Sat, Jul 21, 2012 at 5:06 AM, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote: So there is approximately 0.03 second difference per TWO MILLION if...else blocks, or about 15 nanoseconds each. This is highly unlikely to be the bottleneck in your code. Assuming the difference is real, and not just measurement error, the difference is insignificant. It's probably real. For if-else, the true case needs to make a jump before it returns, but for if-return, there's no jump and the return is inlined. -- Devin So, don't worry about which is faster. Write whichever is more natural, easier to read and write. The most important advice. Even when it's a larger difference! :) -- Devin -- http://mail.python.org/mailman/listinfo/python-list