expression in an if statement

E

ernest

Hi,

In this code:

if set(a).union(b) == set(a): pass

Does Python compute set(a) twice?
Thanks in advance.

Ernest
 
P

Peter Otten

ernest said:
In this code:

if set(a).union(b) == set(a): pass

Does Python compute set(a) twice?
.... print "computing set(%r)" % x
.... return _set(x)
........
computing set('abc')
computing set('abc')

So yes, set(a) is computed twice.

Peter
 
J

John Nagle

Hi,

In this code:

if set(a).union(b) == set(a): pass

Does Python compute set(a) twice?

CPython does. Shed Skin might optimize. Don't know
about Iron Python.

John Nagle
 
T

Thomas Jollans

CPython does. Shed Skin might optimize. Don't know
about Iron Python.

I doubt any actual Python implementation optimizes this -- how could it? The
object "set" is clearly being called twice, and it happens to be called with
the object "a" as a sole argument twice. What if "set" has side effects? A
compiler could only exclude this possibility if it knew exactly what "set"
will be at run time, which it can't.

I expect that "set" and "a" have to be looked up twice, actually:
"set(a).union(b)" might rebind either one of them. This would be considered a
very rude and inappropriate thing to do, but Python usually guarantees to
allow bad taste and behaviour.

I might be wrong on some points here, but this is what I expect the expression
(set(a).union(b) == set(a)) has to do, in any conforming implementation of
Python. Please correct me if I'm wrong.

1. find out which object "set" refers to
2. find out which object "a" refers to
3. call (set) with the single positional argument (a), no keyword arguments
4. get the attribute "union" of the return value of [3]
5. find out which object "b" refers to
6. call (.union) with the single positional argument (b).
7. look up __eq__ in the __class__ of the return value of [6]
8. find out which object "set" refers to
9. find out which object "a" refers to
10. call (set) with the single positional argument (a), no keyword arguments
11. call [7] with two positional arguments: the return values [6] & [10]

I'm not 100% sure if there are any guarantees as to when (5) is taken care of
-- what would happen if set(a) or even set(a).__getattr__ changed the global
"b"?
My list there is obviously referring to Python 3.x, so there is no __cmp__ to
worry about.
 
F

Frederic Rentsch

I doubt any actual Python implementation optimizes this -- how could it?

And why should it if a programmer uses its facilities inefficiently. I
would write

Frederic
 
E

ernest

And why should it if a programmer uses its facilities inefficiently. I
would write


Frederic

Yes, maybe the example is silly, but situations like this arise
frequently and it's good to know.

Thanks for the answers.

Ernest
 
J

John Nagle

I doubt any actual Python implementation optimizes this -- how could it? The
object "set" is clearly being called twice, and it happens to be called with
the object "a" as a sole argument twice. What if "set" has side effects? A
compiler could only exclude this possibility if it knew exactly what "set"
will be at run time, which it can't.

That just reflects the rather lame state of Python implementations.
For some other languages, there are JIT compilers that can optimize such
things. If you rebind a function at run time, the compiled code has to
be invalidated and recompiled with the new binding.

The HotSpot Java JIT compiler did this. See

http://books.google.com/books?id=GB...&resnum=9&ved=0CDsQ6AEwCA#v=onepage&q&f=false

It's really tough to get this right. There's a huge overhead in
either performance or complexity for allowing rebinding of
functions during execution. It's also a feature very seldom
used after program startup.

I was talking to the Facebook guys doing the compiler for PHP, and they
said that it was a huge win for them that PHP doesn't allow dynamically
replacing a function.

John Nagle
 
A

alex23

John Nagle said:
I was talking to the Facebook guys doing the compiler for PHP, and they
said that it was a huge win for them that PHP doesn't allow dynamically
replacing a function.

I'm not sure if I call all that effort for a 50% speed increase a win.
PyPy is seeing speed increases of up to 15 times that of CPython 2.6.2
without reducing the flexibility of the language at all.
 
G

Gregory Ewing

Thomas said:
What if "set" has side effects? A
compiler could only exclude this possibility if it knew exactly what "set"
will be at run time,

And also that 'a' remains bound to the same object, and that
object or anything reachable from it is not mutated in
any way that could affect the result of set(a). That's
quite a lot of information for an optimiser to deduce,
particularly in a language as dynamic as Python.
 

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

No members online now.

Forum statistics

Threads
474,170
Messages
2,570,925
Members
47,466
Latest member
DrusillaYa

Latest Threads

Top