[Python-ideas] Object grabbing
Steven D'Aprano
steve at pearwood.info
Sun May 1 21:29:16 EDT 2016
On Mon, May 02, 2016 at 11:56:00AM +1200, Greg Ewing wrote:
> Suggestions like this have been made before, and the conclusion
> has always been that very little would be gained over using
> a short intermediate name, e.g.
>
> m = myobject
> m.a()
> m.b()
> m.c()
> m.d = 1
>
> That's just as readable and almost as easy to type. It also
> has the advantage that you're not restricted to just one
> "easy acess" object at a time.
Multiple short, simple statements like the above are not the best
demonstration of the "one letter variable name" technique, nor of the
advantage of the "Pascal with" (using) keyword. We should be thinking of
larger expressions, with multiple references to the same name:
print(myobject.method(myobject.eggs + (myobject.spam or ham))
- myobject.tomato - cheese)
which becomes either:
m = myobject
print(m.method(m.eggs + (m.spam or ham)) - m.tomato - cheese)
del m
versus:
using myobject:
print(.method(.eggs + (.spam or ham)) - .tomato - cheese)
I don't think there's a lot between them, but if the second can be
significantly more efficient, that might push it over the line.
Why do I `del m` at the end? Because this might be in the global scope,
not inside a function, and you might not want an extraneous variable
floating around polluting the namespace.
> The only new thing in your proposal is the change to the
> bytecode, and that could be achieved by treating it as
> an optimisation. A sufficiently smart code generator
> could notice that you were repeatedly operating on the same
> object and produce the bytecode you suggest.
No, I don't think it can be. Or rather, the semantics are not the same,
and the compiler shouldn't choose to optimize the code. Consider:
myobject.a()
myobject.b()
You cannot assume that it is the same myobject in both statements!
Method a might have rebound the name to something else. Perhaps Victor's
FAT Python will be smart enough to tell whether or not a global name
myobject has been changed, but how about:
myobject[1].lookup['key'].property.a()
myobject[1].lookup['key'].property.b()
I don't think any Python compiler is going to be able to look deep
inside an arbitrarily complex reference and tell whether or not it is
safe to optimize. But the programmer may be able to explicitly choose
the optimization.
Of course, in this case, they can just as easily factor out the constant
part and assign it to a temporary short name:
m = myobject[1].lookup['key']
m.property.a()
m.property.b()
# versus
using myobject[1].lookup['key']:
.property.a()
.property.b()
so it becomes a matter of two things: taste and performance. In my
opinion, the two idioms are roughly the same in readability, give or
take a few concerns about temp variables versus grit on Tim's monitor.
But the first has to do two name lookups of "m", which the second can
optimize. Can the second beat that by a significant amount? What if
there were ten name lookups? Thirty?
--
Steve
More information about the Python-ideas
mailing list