[Python-ideas] Object grabbing
Chris Angelico
rosuav at gmail.com
Sun May 1 22:05:13 EDT 2016
On Mon, May 2, 2016 at 11:36 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> On Sun, May 01, 2016 at 09:25:17PM -0400, Random832 wrote:
>
>> Is there any reason not to simply implement a performance optimization
>> for the normal syntax?
>
> Yes. You can't assume that myobject is the same object in both
> statements. A silly toy example:
>
> class MyObject:
> def deactivate(self):
> global myobject
> myobject = None
> def fire(self):
> launch_missiles()
>
> myobject.deactivate()
> myobject.fire()
>
> A more realistic case would be if you have a mutable object:
>
> myobject[1].lookup['key'].property.a()
> myobject[1].lookup['key'].property.b()
>
> The compiler cannot assume that (myobject[1].lookup['key'].property)
> will refer to the same thing in the two calls. But the programmer can
> explicitly do so, using either a temporary variable, or the proposed
> "using" statement.
If you profile a big program, I expect you'll find that module-level
code amounts to a tiny proportion of run-time. Restricting this
optimization to function-local names (no nonlocals, no globals - the
LOAD_FAST opcode in current CPython) wouldn't materially harm it, and
it would make the code a lot easier to reason about. The only possible
issue that I can see is with an inner function messing with the outer
function:
def f():
obj = MyObject()
def switch_obj():
nonlocal obj
obj = MyObject()
return 5
obj.attr1 = switch_obj()
obj.attr2 = 42
return obj
But a quick check with dis.dis(f) shows that this, too, uses
LOAD_DEREF, so that should be safe - a byte-code transformation should
safely be able to look for the LOAD_FAST and depend on it not changing
(short of insane shenanigans - if you mutate sys._getframe().f_locals
to tamper with another function's locals, you deserve all you get...
and I'm not sure if it'd even work).
This would be restricted to lookups on simple names. Frankly, I
wouldn't expect anything else. If you want to call
"myobject[1].lookup['key'].property.a" and "etc etc .b", you should
probably be giving that a name *for the benefit of humans*, never mind
about the interpreter! And if you want it optimized, definitely assign
that to a local name.
ChrisA
More information about the Python-ideas
mailing list