You are not logged in.
It's a small thing, but I'd like to know what is more efficient when checking if object "a" is the same as objects "b" and "c";
def c1():
... a = 1
... if a == 2 or a == 3:
... print "ok, no"
... else:
... print "kk"
2 0 LOAD_CONST 1 (1)
3 STORE_FAST 0 (a)
3 6 LOAD_FAST 0 (a)
9 LOAD_CONST 2 (2)
12 COMPARE_OP 2 (==)
15 JUMP_IF_TRUE 13 (to 31)
18 POP_TOP
19 LOAD_FAST 0 (a)
22 LOAD_CONST 3 (3)
25 COMPARE_OP 2 (==)
28 JUMP_IF_FALSE 9 (to 40)
>> 31 POP_TOP
4 32 LOAD_CONST 4 ('ok, no')
35 PRINT_ITEM
36 PRINT_NEWLINE
37 JUMP_FORWARD 6 (to 46)
>> 40 POP_TOP
6 41 LOAD_CONST 5 ('kk')
44 PRINT_ITEM
45 PRINT_NEWLINE
>> 46 LOAD_CONST 0 (None)
49 RETURN_VALUE
or...
def c2():
... a = 1
... if a in (2, 3):
... print "lol whut?"
... else:
... print "fine.."
2 0 LOAD_CONST 1 (1)
3 STORE_FAST 0 (a)
3 6 LOAD_FAST 0 (a)
9 LOAD_CONST 6 ((2, 3))
12 COMPARE_OP 6 (in)
15 JUMP_IF_FALSE 9 (to 27)
18 POP_TOP
4 19 LOAD_CONST 4 ('lol whut?')
22 PRINT_ITEM
23 PRINT_NEWLINE
24 JUMP_FORWARD 6 (to 33)
>> 27 POP_TOP
6 28 LOAD_CONST 5 ('fine..')
31 PRINT_ITEM
32 PRINT_NEWLINE
>> 33 LOAD_CONST 0 (None)
36 RETURN_VALUE
c2 appears to use less instructions, but it also populates a tuple and uses the "in" operator - both of which appear heavier than their atom and "==" counterparts.
Any thoughts?
div curl F = 0
Offline
I think c2() is just silly.
c1() makes a lot more sense, and would be less likely to enrage the people who read your code.
I have no idea which one is faster, but either way I'd say c1() is better.
Offline
I think c2() is just silly.
c1() makes a lot more sense, and would be less likely to enrage the people who read your code.
I have no idea which one is faster, but either way I'd say c1() is better.
I'm not sure I could disagree with this more.
c2 is more readable and concise.
It is also likely to be more consistent. i.e., what if it were 4 variables?
if a == 1 or a == 2 or a == 3 or a == 4
or
if a in xrange(1,5)
etc.
Cthulhu For President!
Offline
On topic, there's an easy way to test this.
I took your code (minus the print statements) and added a for loop that ran it a million times and timed it a few times and recorded the average. Obviously there could be other factors, but in general this is pretty good. You could use python -c cProfile if you REALLY wanted exact numbers.
c1 avg over a million: 0.258
c2 avg over a million: 0.264
If this is in your inner loop, it will need to execute 125,000,000 times before you would notice 1s of difference.
Cthulhu For President!
Offline
This thread is Hilarious!
Last edited by cactus (2009-04-12 04:11:37)
"Be conservative in what you send; be liberal in what you accept." -- Postel's Law
"tacos" -- Cactus' Law
"t̥͍͎̪̪͗a̴̻̩͈͚ͨc̠o̩̙͈ͫͅs͙͎̙͊ ͔͇̫̜t͎̳̀a̜̞̗ͩc̗͍͚o̲̯̿s̖̣̤̙͌ ̖̜̈ț̰̫͓ạ̪͖̳c̲͎͕̰̯̃̈o͉ͅs̪ͪ ̜̻̖̜͕" -- -̖͚̫̙̓-̺̠͇ͤ̃ ̜̪̜ͯZ͔̗̭̞ͪA̝͈̙͖̩L͉̠̺͓G̙̞̦͖O̳̗͍
Offline
lol @ cactus showing up with that same post over and over
The day Microsoft makes a product that doesn't suck, is the day they make a vacuum cleaner.
--------------------------------------------------------------------------------------------------------------
But if they tell you that I've lost my mind, maybe it's not gone just a little hard to find...
Offline
If this is in your inner loop, it will need to execute 125,000,000 times before you would notice 1s of difference.
!
"a == 2 or a == 3" it is, then.
edit:
I'm not great at this math stuff, but I don't get 125,000,000.. 0.264x - 0.258x = 0.006x, 1x / 0.006x = 167. 167 * 1,000,000 = 167,000,000 runs, on average.
edit #2:
Yeah, but still, death to "in"!!
edit #3:
Hm.. but is this a valid "in" benchmark? By examining the disassembly, we find that Python creates and assigns to "a" every time c{1,2} is run - so if that was nested in a for loop, it would be done *n* amount of times. The same is true for the (2, 3) tuple. This is overhead! So I propose;
a = 1
conds = (2, 3)
for x in range(0, 1000000):
if a == 2 or a == 3:
# if a in conds:
pass
else:
pass
Last edited by vkumar (2009-04-12 16:55:38)
div curl F = 0
Offline
And the shocking results;
Python 3.0.1 (r301:69561, Feb 13 2009, 20:04:18) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import cProfile
>>> def c1():
... for x in range(0, 1000000):
... if a == 2 or a == 3:
... pass
... else:
... pass
...
>>> def c2():
... for x in range(0, 1000000):
... if a in conds:
... pass
... else:
... pass
...
>>> global a, conds
>>> a = 1
>>> conds = (2, 3)
>>> def t1():
... cProfile.run('c1()')
... cProfile.run('c2()')
...
>>> t1()
4 function calls in 0.348 CPU secondsOrdered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.348 0.348 0.348 0.348 <stdin>:1(c1)
1 0.000 0.000 0.348 0.348 <string>:1(<module>)
1 0.000 0.000 0.348 0.348 {built-in method exec}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}4 function calls in 0.274 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.274 0.274 0.274 0.274 <stdin>:1(c2)
1 0.000 0.000 0.274 0.274 <string>:1(<module>)
1 0.000 0.000 0.274 0.274 {built-in method exec}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}>>> t1()
4 function calls in 0.335 CPU secondsOrdered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.335 0.335 0.335 0.335 <stdin>:1(c1)
1 0.000 0.000 0.335 0.335 <string>:1(<module>)
1 0.000 0.000 0.335 0.335 {built-in method exec}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}4 function calls in 0.273 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.273 0.273 0.273 0.273 <stdin>:1(c2)
1 0.000 0.000 0.273 0.273 <string>:1(<module>)
1 0.000 0.000 0.273 0.273 {built-in method exec}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
So c2 is faster than c1 (after a million iterations) by (0.062+0.074)/2 seconds --> 0.068 secs. 1/0.068 = 14.706. 14.706 * 1000000 = 14,706,000 runs until you lose an entire second of time to c1.
Conclusion?
"in" is actually great!
div curl F = 0
Offline
More or less unrelated:
http://python.net/~goodger/projects/pyc … possible-1
You might also want to test the python 2.5 any() keyword here. I'd also run it through pypy's experimental JIT. Its always nice to have a collection of benchmarks to ignore.
Python is slow. Readability is more important than efficiency, or you would be writing a C extension. Even if you are using python, there are a lot more important things you can be optimizing. 'in' is definitely the winner when it comes to efficiency.
In short, I'm with cactus.
Dusty
Offline
Its always nice to have a collection of benchmarks to ignore.
What else am I going to do with my spare time? read? I'll stick with my useless benchmarks, thank you very much
div curl F = 0
Offline
For anything big you would be using sets or matrices anyway... "in" is a great shorthand.
Offline
Magic numbers are bad.
good_numbers = (2, 3)
a = 1
if a in good_numbers:
print "yay"
else:
print "boo"
Offline
And the shocking results;
Python 3.0.1 (r301:69561, Feb 13 2009, 20:04:18) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import cProfile
uhhh .. win32?
BUSTED !
but seriously; maybe you need to test 'in' against different expressions, as in, evaluating in lists vs tuples, mesure if there is greating difference when using a higher number of values to compare against, etc.. there might not be a big difference in finding within a list of 2 or 3 values, but the difference might be more obvious if searching for a substring in a string of a few thousand characters in lenght... (which is also not very elegant to do in any other way..)
Last edited by pedepy (2009-04-24 21:45:24)
chupocabra ... psupsuspsu psu psu
Offline