Re: Set & Frozenset?

2009-03-11 Thread Lie Ryan

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?

2009-03-10 Thread R. David Murray
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?

2009-03-10 Thread Terry Reedy

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?

2009-03-10 Thread Paul Rubin
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?

2009-03-10 Thread Terry Reedy

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?

2009-03-10 Thread Lie Ryan

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?

2009-03-09 Thread Matt Nordhoff
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?

2009-03-09 Thread Alan G Isaac

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?

2009-03-08 Thread Tim Golden

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?

2009-03-08 Thread Tim Golden

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?

2009-03-08 Thread Diez B. Roggisch

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?

2009-03-08 Thread Hans Larsen
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