Re: Set & Frozenset?
R. David Murray wrote: Lie Ryan wrote: Matt Nordhoff wrote: Alan G Isaac wrote: Hans Larsen schrieb: How could I "take" an elemment from a set or a frozenset On 3/8/2009 2:06 PM Diez B. Roggisch apparently wrote: You iterate over them. If you only want one value, use iter(the_set).next() I recall a claim that for result in myset: break is the most efficient way to get one result. Is this right? (It seems nearly the same.) Alan Isaac Checking Python 2.5 on Linux, your solution is much faster, but seeing as they both come in under a microsecond, it hardly matters. It's unexpected... >>> timeit.timeit('res=iter(myset).next()', 'myset=range(100)') 0.8894412399647 >>> timeit.timeit('res=myset.next()', 'myset=range(100); myset=iter(myset)') 0.4916552002516 >>> timeit.timeit('for res in myset: break', 'myset=range(100)') 0.3293300797699 I'd never expect that for-loop assignment is even faster than a precreated iter object (the second test)... but I don't think this for-looping variable leaking behavior is guaranteed, isn't it? My guess would be that what's controlling the timing here is name lookup. Three in the first example, two in the second, and one in the third. You got it: >>> timeit.timeit('res=myset()', 'myset=range(100); myset=iter(myset).next') 0.2646590399796 -- The following is a complete benchmark: >>> timeit.timeit('res=iter(myset).next()', 'myset=range(1000)', number=1000) 8.514500200432 >>> timeit.timeit('res=myset.next()', 'myset=range(1000); myset=iter(myset)', number=1000) 4.550980280898 >>> timeit.timeit('for res in myset: break', 'myset=range(1000)', number=1000) 2.999421360421 >>> timeit.timeit('res=myset()', 'myset=range(1000); myset=iter(myset).next', number=1000) 2.222883241011 -- I also performed additional timing for overhead: Local name lookup: >>> timeit.timeit('myset', 'myset=range(100)', number=1000) 1.108640079865 Global name lookup: >>> timeit.timeit('iter', number=1000) 1.814941079259 Attribute lookup: >>> timeit.timeit('myset.next', 'myset=range(1000); myset=iter(myset)', number=1000) 3.301133397987 Combined multiple name lookup that troubled first test >>> timeit.timeit('iter(myset).next', 'myset=range(1000)', number=1000) 6.559937480305 Creating iterables: >>> timeit.timeit('iter(myset)', 'myset=range(100)', number=1000) 4.25940671788 -- So adjusting the overheads: Attribute lookup: >>> timeit.timeit('myset.next', 'myset=range(1000); myset=iter(myset)', number=1000) 3.301133397987 The timing for Attribute also include a local name lookup (myset), so the real attribute lookup time shold be: 3.301133397987 - 1.108640079865 = 2.192493318122 Creating iterables: >>> timeit.timeit('iter(myset)', 'myset=range(100)', number=1000) 4.25940671788 Creating iterable involve global name lookup, so the real time should be: 4.25940671788 - 1.814941079259 = 2.65638621 -- To summarize the adjusted overheads: Local name lookup: 1.108640079865 Global name lookup: 1.814941079259 Attribute lookup: 2.192493318122 Creating iterables: 2.65638621 -- Back to the problem, now we'll be adjusting the timing of each codes: 'res=iter(myset).next()': 8.514500200432 Adjusting with the "Combined multiple name lookup" 8.514500200432 - 6.559937480305 = 1.954562720126 Another way to do the adjustment: Adjusting global name lookup (iter): 8.514500200432 - 1.814941079259 = 6.699559121172 Adjusting iterable creation: 6.699559121172 - 2.65638621 = 4.255093482551 Adjusting attribute lookup: 4.255093482551 - 2.192493318122 = 2.062600164429 'res=myset.next()': 4.550980280898 Adjusting with |unadjusted| attribute lookup: 4.550980280898 - 3.301133397987 = 1.249846882911 Another way to do the adjustment: Adjusting with local name lookup: 4.550980280898 - 1.108640079865 = 3.442340201033 Adjusting with attribute lookup: 3.442340201033 - 2.192493318122 = 1.249846882911 'for res in myset: break': 2.999421360421 Adjusting for local name lookup (myset): 2.999421360421 - 1.108640079865 = 1.890781280556 'res=myset()': 2.222883241011 Adjusting for local name lookup 2.222883241011 - 1.108640079865 = 1.114243161146 -- To summarize: 'res=iter(myset).next()': 1.954562720126 / 2.062600164429 'res=myset.next()': 1.249846882911 / 1.249846882911 'for res in myset: break': 1.890781280556 'res=myset()': 1.114243161146 -- To conclude, 'for res in myset: break' is actually not much faster than 'res=iter(myset).next()' except the former saves a lot of name lookup.
Re: Set & Frozenset?
Lie Ryan wrote: > Matt Nordhoff wrote: > > Alan G Isaac wrote: > >>> Hans Larsen schrieb: > How could I "take" an elemment from a set or a frozenset > >> > >> On 3/8/2009 2:06 PM Diez B. Roggisch apparently wrote: > >>> You iterate over them. If you only want one value, use > >>> iter(the_set).next() > >> > >> I recall a claim that > >> > >> for result in myset: break > >> > >> is the most efficient way to get one result. > >> Is this right? (It seems nearly the same.) > >> > >> Alan Isaac > > > > Checking Python 2.5 on Linux, your solution is much faster, but seeing > > as they both come in under a microsecond, it hardly matters. > > > It's unexpected... > > >>> timeit.timeit('res=iter(myset).next()', 'myset=range(100)') > 0.8894412399647 > >>> timeit.timeit('res=myset.next()', 'myset=range(100); > myset=iter(myset)') > 0.4916552002516 > >>> timeit.timeit('for res in myset: break', 'myset=range(100)') > 0.3293300797699 > > I'd never expect that for-loop assignment is even faster than a > precreated iter object (the second test)... but I don't think this > for-looping variable leaking behavior is guaranteed, isn't it? My guess would be that what's controlling the timing here is name lookup. Three in the first example, two in the second, and one in the third. -- R. David Murray http://www.bitdance.com -- http://mail.python.org/mailman/listinfo/python-list
Re: Set & Frozenset?
Paul Rubin wrote: Terry Reedy writes: I'd never expect that for-loop assignment is even faster than a precreated iter object (the second test)... but I don't think this for-looping variable leaking behavior is guaranteed, isn't it? It is an intentional, documented feature: ... I prefer thinking of it as a documented bug. It is fixed in 3.x. Nope to both. We are talking about for-loop statements. -- http://mail.python.org/mailman/listinfo/python-list
Re: Set & Frozenset?
Terry Reedy writes: > > I'd never expect that for-loop assignment is even faster than a > > precreated iter object (the second test)... but I don't think this > > for-looping variable leaking behavior is guaranteed, isn't it? > > It is an intentional, documented feature: ... I prefer thinking of it as a documented bug. It is fixed in 3.x. I usually avoid the [... for x in xiter] listcomp syntax in favor of list(... for x in xiter) just as an effort to be a bit less bug-prone. -- http://mail.python.org/mailman/listinfo/python-list
Re: Set & Frozenset?
Lie Ryan wrote: I recall a claim that for result in myset: break is the most efficient way to get one result. I'd never expect that for-loop assignment is even faster than a precreated iter object (the second test)... but I don't think this for-looping variable leaking behavior is guaranteed, isn't it? It is an intentional, documented feature: "Names in the target list are not deleted when the loop is finished, but if the sequence is empty, it will not have been assigned to at all by the loop." -- http://mail.python.org/mailman/listinfo/python-list
Re: Set & Frozenset?
Matt Nordhoff wrote: Alan G Isaac wrote: Hans Larsen schrieb: How could I "take" an elemment from a set or a frozenset On 3/8/2009 2:06 PM Diez B. Roggisch apparently wrote: You iterate over them. If you only want one value, use iter(the_set).next() I recall a claim that for result in myset: break is the most efficient way to get one result. Is this right? (It seems nearly the same.) Alan Isaac Checking Python 2.5 on Linux, your solution is much faster, but seeing as they both come in under a microsecond, it hardly matters. It's unexpected... >>> timeit.timeit('res=iter(myset).next()', 'myset=range(100)') 0.8894412399647 >>> timeit.timeit('res=myset.next()', 'myset=range(100); myset=iter(myset)') 0.4916552002516 >>> timeit.timeit('for res in myset: break', 'myset=range(100)') 0.3293300797699 I'd never expect that for-loop assignment is even faster than a precreated iter object (the second test)... but I don't think this for-looping variable leaking behavior is guaranteed, isn't it? Note: the second one exhausts the iter object. -- http://mail.python.org/mailman/listinfo/python-list
Re: Set & Frozenset?
Alan G Isaac wrote: >> Hans Larsen schrieb: >>> How could I "take" an elemment from a set or a frozenset > > > On 3/8/2009 2:06 PM Diez B. Roggisch apparently wrote: >> You iterate over them. If you only want one value, use >> iter(the_set).next() > > > I recall a claim that > > for result in myset: break > > is the most efficient way to get one result. > Is this right? (It seems nearly the same.) > > Alan Isaac Checking Python 2.5 on Linux, your solution is much faster, but seeing as they both come in under a microsecond, it hardly matters. -- -- http://mail.python.org/mailman/listinfo/python-list
Re: Set & Frozenset?
Hans Larsen schrieb: How could I "take" an elemment from a set or a frozenset On 3/8/2009 2:06 PM Diez B. Roggisch apparently wrote: You iterate over them. If you only want one value, use iter(the_set).next() I recall a claim that for result in myset: break is the most efficient way to get one result. Is this right? (It seems nearly the same.) Alan Isaac -- http://mail.python.org/mailman/listinfo/python-list
Re: Set & Frozenset?
Tim Golden wrote: Diez B. Roggisch wrote: Hans Larsen schrieb: Could you help me ? How could I "take" an elemment from a set or a frozenset .-) ? From a string (unicode? Python<3), or from a tuple,or from a list: Element by index or slice. From a dict: by key. But what concerning a set or frozenset! hope somebody can help! You iterate over them. If you only want one value, use iter(the_set).next() or the_set.pop () Which will, in addition, remove it from the set. (May not be what you want :) ). TJG -- http://mail.python.org/mailman/listinfo/python-list
Re: Set & Frozenset?
Diez B. Roggisch wrote: Hans Larsen schrieb: Could you help me ? How could I "take" an elemment from a set or a frozenset .-) ? From a string (unicode? Python<3), or from a tuple,or from a list: Element by index or slice. From a dict: by key. But what concerning a set or frozenset! hope somebody can help! You iterate over them. If you only want one value, use iter(the_set).next() or the_set.pop () TJG -- http://mail.python.org/mailman/listinfo/python-list
Re: Set & Frozenset?
Hans Larsen schrieb: Could you help me ? How could I "take" an elemment from a set or a frozenset .-) ? From a string (unicode? Python<3), or from a tuple,or from a list: Element by index or slice. From a dict: by key. But what concerning a set or frozenset! hope somebody can help! You iterate over them. If you only want one value, use iter(the_set).next() Diez -- http://mail.python.org/mailman/listinfo/python-list
Set & Frozenset?
Could you help me ? How could I "take" an elemment from a set or a frozenset .-) ? From a string (unicode? Python<3), or from a tuple,or from a list: Element by index or slice. From a dict: by key. But what concerning a set or frozenset! hope somebody can help! -- Hans Larsen Galgebakken Sønder 4-11A DK-2620 Albertslund Danmark/Danio begin 666 Hans Larsen.vcf M0D5'24XZ5D-!4D0-"E9%4E-)3TXZ,BXQ#0I..DQA-- http://mail.python.org/mailman/listinfo/python-list