Movatterモバイル変換


[0]ホーム

URL:


[Python-Dev] partition() (was: Remove str.find in 3.0?)

Josiah Carlsonjcarlson at uci.edu
Tue Aug 30 19:06:55 CEST 2005


Pierre Barbier de Reuille <pierre.barbier at cirad.fr> wrote:> Well, what it does is exactly what I tought, you can express most of the> use-cases of partition with:>> head, sep, tail = s.partition(sep)> if not sep:>   #do something when it does not work> else:>   #do something when it works>> And I propose to replace it by :>> try:>   head, sep, tail = s.partition(sep)>   # do something when it works> except SeparatorError:>   # do something when it does not workNo, you can't.  As Tim Peters pointed out, in order to be correct, youneed to use...try:    head, found, tail = s.partition(sep)except ValueError:    # do something when it can't find sepelse:    # do something when it can find sepBy embedding the 'found' case inside the try/except clause as you offer,you could be hiding another exception, which is incorrect.> What I'm talking about is consistency. In most cases in Python, or at> least AFAIU, error testing is avoided and exception launching is> preferred mainly for efficiency reasons. So my question remains: why> prefer for that specific method returning an "error" value (i.e. an> empty separator) against an exception ?It is known among those who tune their Python code that try/except isrelatively expensive when exceptions are raised, but not significantlyfaster (if any) when they are not. I'll provide an updated set ofmicrobenchmarks...>>> if 1:...     x = 'h'...     t = time.time()...     for i in xrange(1000000):...             _ = x.find('h')...             if _ >= 0:...                     pass...             else:...                     pass...     print time.time()-t...0.84299993515>>> if 1:...     x = 'h'...     t = time.time()...     for i in xrange(1000000):...             try:...                     _ = x.index('h')...             except ValueError:...                     pass...             else:...                     pass...     print time.time()-t...0.81299996376BUT!>>> if 1:...     x = 'h'...     t = time.time()...     for i in xrange(1000000):...             try:...                     _ = x.index('i')...             except ValueError:...                     pass...             else:...                     pass...     print time.time()-t...4.29700016975We should subtract the time of the for loop, the method call overhead,perhaps the integer object creation/fetch, and the assignment.str.__len__() is pretty fast (really just a member check, which is at aconstant offset...), let us use that.>>> if 1:...     x = 'h'...     t = time.time()...     for i in xrange(1000000):...             _ = x.__len__()...     print time.time()-t...0.5So, subtracting that .5 seconds from all the cases gives us...0.343 seconds for .find's comparison0.313 seconds for .index's exception handling when an exception is notraised3.797 seconds for .index's exception handling when an exception israised.In the case of a string being found, .index is about 10% faster than.find .  In the case of a string not being found, .index's exceptionhandlnig mechanics are over 11 times slower than .find's comparison.Those numbers should speak for themselves.  In terms of the stringsbeing automatically chopped up vs. manually chopping them up with slices,it is obvious which will be faster: C-level slicing.I agree with Raymond that if you are going to poo-poo on str.partition()not raising an exception, you should do some translations using thecorrect structure that Tim Peters provided, and post them here onpython-dev as 'proof' that raising an exception in the cases provided isbetter. - Josiah


More information about the Python-Devmailing list

[8]ページ先頭

©2009-2025 Movatter.jp