A curious bit of code...

N

Neil Cerutti

In a fit of curiosity, I did some timings:

'and'ed indexing:

C:\tmp>py -m timeit -s "key = '<test>'" "key[0] == '<' and key[-1] == '>'"
1000000 loops, best of 3: 0.35 usec per loop

C:\tmp>py -m timeit -s "key = '<test'" "key[0] == '<' and key[-1] == '>'"
1000000 loops, best of 3: 0.398 usec per loop

C:\tmp>py -m timeit -s "key = 'test>'" "key[0] == '<' and key[-1] == '>'"
1000000 loops, best of 3: 0.188 usec per loop

C:\tmp>py -m timeit -s "key = 'test'" "key[0] == '<' and key[-1] == '>'"
10000000 loops, best of 3: 0.211 usec per loop

C:\tmp>py -m timeit -s "key = ''" "key[0] == '<' and key[-1] == '>'"
Traceback (most recent call last):
File "P:\Python34\lib\timeit.py", line 292, in main
x = t.timeit(number)
File "P:\Python34\lib\timeit.py", line 178, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
key[0] == '<' and key[-1] == '>'
IndexError: string index out of range

The corrected version

key and key[0] == '<' and key[-1] == '>'

probably still wins the Pretty Unimportant Olympics.
 
C

Chris Angelico

In a fit of curiosity, I did some timings:


Snip of lots of TMTOWTDT/TIMTOWTDI/whatever... timed examples :)

But I didn't see this one:

s[::len(s)-1]

..... AAAAAAAAAAAAAAAAAAARGGGGGGGGGGHHHH!

Really, I actually did pause, double-take, and then scream under my
breath, when I saw that. Yes, it works. But please, if you EVER do
this, save me the trouble and just submit your code to thedailywtf.com
straight away!

ChrisA
 
P

Peter Otten

Chris said:
In a fit of curiosity, I did some timings:


Snip of lots of TMTOWTDT/TIMTOWTDI/whatever... timed examples :)

But I didn't see this one:

s[::len(s)-1]

.... AAAAAAAAAAAAAAAAAAARGGGGGGGGGGHHHH!

Really, I actually did pause, double-take, and then scream under my
breath, when I saw that. Yes, it works. But please, if you EVER do
this, save me the trouble and just submit your code to thedailywtf.com
straight away!

For the record:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: slice step cannot be zero
 
M

Mark Lawrence

In a fit of curiosity, I did some timings:

'and'ed indexing:

C:\tmp>py -m timeit -s "key = '<test>'" "key[0] == '<' and key[-1] == '>'"
1000000 loops, best of 3: 0.35 usec per loop

C:\tmp>py -m timeit -s "key = '<test'" "key[0] == '<' and key[-1] == '>'"
1000000 loops, best of 3: 0.398 usec per loop

C:\tmp>py -m timeit -s "key = 'test>'" "key[0] == '<' and key[-1] == '>'"
1000000 loops, best of 3: 0.188 usec per loop

C:\tmp>py -m timeit -s "key = 'test'" "key[0] == '<' and key[-1] == '>'"
10000000 loops, best of 3: 0.211 usec per loop

C:\tmp>py -m timeit -s "key = ''" "key[0] == '<' and key[-1] == '>'"
Traceback (most recent call last):
File "P:\Python34\lib\timeit.py", line 292, in main
x = t.timeit(number)
File "P:\Python34\lib\timeit.py", line 178, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
key[0] == '<' and key[-1] == '>'
IndexError: string index out of range

The corrected version

key and key[0] == '<' and key[-1] == '>'

probably still wins the Pretty Unimportant Olympics.

Exactly how I'd write it. To me it wins awards for being most boring
and most obvious, obviously YMMV or we wouldn't be having this
discussion. Or argument. Or contradiction :)
 
Z

Zachary Ware

In a fit of curiosity, I did some timings:


Snip of lots of TMTOWTDT/TIMTOWTDI/whatever... timed examples :)

But I didn't see this one:

s[::len(s)-1]

It's not great, around 0.520 usec (the builtin lookup and function
call is what gets it). Also, uglier than sin itself.
 
Z

Zachary Ware

C:\tmp>py -m timeit -s "key = ''" "key[0] == '<' and key[-1] == '>'"
Traceback (most recent call last):
File "P:\Python34\lib\timeit.py", line 292, in main
x = t.timeit(number)
File "P:\Python34\lib\timeit.py", line 178, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
key[0] == '<' and key[-1] == '>'
IndexError: string index out of range

The corrected version

key and key[0] == '<' and key[-1] == '>'

probably still wins the Pretty Unimportant Olympics.

Indeed, see the last set of timings and moral ;)
 
E

Emile van Sebille

For the record:
s = "x"
s[::len(s)-1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: slice step cannot be zero

And that, my friends, is a classic example of a Python exception that
ought to be a subclass of UnhingedProgrammerError.

And certainly s[::len(s)-1 or 1] isn't any better. :)

Emile
 
R

Roy Smith

Emile van Sebille said:
In a fit of curiosity, I did some timings:

Snip of lots of TMTOWTDT/TIMTOWTDI/whatever... timed examples :)

But I didn't see this one:

s[::len(s)-1]

Emile

I love it. I need to add this to my list of Python trivia questions.
 
E

Ethan Furman

In a fit of curiosity, I did some timings:


Snip of lots of TMTOWTDT/TIMTOWTDI/whatever... timed examples :)

But I didn't see this one:

s[::len(s)-1]

.... AAAAAAAAAAAAAAAAAAARGGGGGGGGGGHHHH!

Really, I actually did pause, double-take, and then scream under my
breath, when I saw that. Yes, it works. But please, if you EVER do
this, save me the trouble and just submit your code to thedailywtf.com
straight away!

Oh, it's not that bad! All you have to do is handle the edge case of an empty string:

s[::len(s)-1 if s else True]

*ducks and runs*
 
S

Serhiy Storchaka

13.02.14 21:59, Zachary Ware напиÑав(ла):
don't use re for simple stuff (because while it may be very fast, it's
dominated by attribute lookup and function call overhead),

And the time of re variant depends on the size of input.
 
R

Roy Smith

Serhiy Storchaka said:
13.02.14 21:59, Zachary Ware напиÑав(ла):

And the time of re variant depends on the size of input.

That's a good point. It's nice, for a change, to see somebody shoot
down a regex solution for a valid reason :)
 
C

Chris Angelico

Oh, it's not that bad! All you have to do is handle the edge case of an
empty string:

s[::len(s)-1 if s else True]

*ducks and runs*

And the edge case of the one-character string. Also, it's been noted
that calling the built-in function len() is slow, so I propose
changing that.

s[::(sys.getsizeof("\N{MATHEMATICAL BOLD CAPITAL
L}"+s)-sys.getsizeof("\N{MATHEMATICAL BOLD CAPITAL E}\N{MATHEMATICAL
BOLD CAPITAL N}") or 4)//4]

Note the elegance of using the word LEN across two string literals
(because string literals are fast) as a means of clearly describing
what we are doing - an optimization of the built-in len() function.

ChrisA
 
E

Ethan Furman

Oh, it's not that bad! All you have to do is handle the edge case of an
empty string:

s[::len(s)-1 if s else True]

And the edge case of the one-character string.

Oops, my description should have said "edge case of a one-character string". The empty string needs no extra handling.
 
T

Terry Reedy

I ran across this and I thought there must be a better way of doing it, but then after further consideration I wasn't so sure.

if key[:1] + key[-1:] == '<>': ...

if key[:1] == '<' and key[-1:] == '>: ...
is the obvious choice to me. If the first clause is false, it never
computes the second.
 
F

forman.simon

For the record I wasn't worried about the performance. ;-)

It was for Tkinter event strings not markup tags.

I'm glad this was the time winner!

"key and key[0] == '<' and key[-1] == '>'"


Cheers to the folks who did the timings (and saved me from the trouble!)

Last but not least... s[::len(s)-1] omg!!? ;-D
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,787
Messages
2,569,631
Members
45,338
Latest member
41Pearline46

Latest Threads

Top