Object grabbing (was: Re: Python-ideas Digest, Vol 114, Issue 5)
I'm receiving digests and seem to not have each individual mail, so here's a digested response: One side of this that's not discussed is the possible optimization. I can imagine if you've got a lot of objectproperty write and -reads this could actually make certain use cases a lot faster such as this one, saving 6 opcodes: def __init__(self, left, top, width, height, content): self.left = left self.top = top self.width = width self.height = height self.content = content.upper() self.decideColors() self.draw() versus: def __init__(self, left, top, width, height, content): with self: .left = left .top = top .width = width .height = height .content = content.upper() .decideColors() .draw() The suggestion that you could accomplish this with a (peephole) optimizer does not seem quite correct to me: x = myobject.b() ... z = myobject.c() does not necessarily have a consistent pointer to myobject although it would require some acrobatics to change them in a way that can not be seen by an optimizer. You can think about exec() or even another thread intervening into a generator function, not something I would do but who knows. The advantage of the construct is that the .dotted variable is guaranteed to point to the same physical object in memory with an increased reference count during the statement and a decrease happening at dedent. Django would break when the 'using' keyword would be used for that, but the choice of keyword is arbitrary. Maybe an extended use of the 'with' word would be elegant, when the object would not have an __enter__ and/or __exit__ function it could still run for the purpose of this mechanism. The disadvantage is that you could not use the with construct for this purpose only without also triggering the __enter__ function. On 5/2/2016 2:49 PM, python-ideas-request@python.org wrote:
[cut]
----------------------------------------------------------------------
Message: 1 Date: Mon, 2 May 2016 14:12:28 +0200 From: Jo?o Santos <jmcs@jsantos.eu> To: Robert van Geel <robert@bign.nl> Cc: python-ideas@python.org, "Franklin? Lee" <leewangzhong+python@gmail.com> Subject: Re: [Python-ideas] Object grabbing Message-ID: <CAH_XWH3vSfvYZit3SYdJ6K==B3iQiY58CbfTpga=shav_EaDzw@mail.gmail.com> Content-Type: text/plain; charset="utf-8"
That is matter of experience, I already lost too many hours of my life looking for weird bugs caused by misspellings and missing commas, and I don't even work with people new to python. On 2 May 2016 14:04, "Robert van Geel" <robert@bign.nl> wrote:
------------------------------ Message: 4 Date: Mon, 2 May 2016 13:48:17 +0100 From: SW <walker_s@hotmail.co.uk> To: python-ideas@python.org Subject: Re: [Python-ideas] Object grabbing Message-ID: <BLU436-SMTP21412FBE1145250B8A38DE8B8790@phx.gbl> Content-Type: text/plain; charset="utf-8" On 02/05/16 13:20, Koos Zevenhoven wrote:
On Mon, May 2, 2016 at 2:48 PM, Jo?o Santos <jmcs@jsantos.eu> wrote:
I think the ".d = 1" statement feels like a bug waiting to happen. It's very easy to miss a dot.
I suppose that's a valid concern, especially regarding assignments, because the code typically would still run. But in the beginning of the line, it is usually quite easy to see if there's a dot or not, assuming a fixed-width font and proper indenting. It may be easy to see if there's a dot or not, but it may not be easy to tell whether there /should/ be a dot when there isn't.
e.g. <snip> .configuration = {'yes': 'no'} vs <snip> configuration = {'yes': 'no'}
When you might have later in the code something that assigns to a variable with the same name, and/or operates on that variable I think it'd become more difficult to determine.
Thanks, S
------------------------------
Subject: Digest Footer
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas
------------------------------
End of Python-ideas Digest, Vol 114, Issue 5 ********************************************
On Mon, May 2, 2016 at 7:25 AM, Robert van Geel <robert@bign.nl> wrote:
I'm receiving digests and seem to not have each individual mail, so here's a digested response:
One side of this that's not discussed is the possible optimization. I can imagine if you've got a lot of objectproperty write and -reads this could actually make certain use cases a lot faster such as this one, saving 6 opcodes:
The continued suggestion that this would be a considerable performance boost worries me. Compared to caching the expression into a local variable the speed-up will be immeasurable. Staring at generated byte code and counting instructions is not a good way to think about Python performance; unlike the model you may have of the hardware underneath, Python instructions, being object-oriented, are not roughly equivalent. The savings on local variable operations of the proposal is minuscule.
def __init__(self, left, top, width, height, content): self.left = left self.top = top self.width = width self.height = height self.content = content.upper() self.decideColors() self.draw()
versus:
def __init__(self, left, top, width, height, content): with self: .left = left .top = top .width = width .height = height .content = content.upper() .decideColors() .draw()
The suggestion that you could accomplish this with a (peephole) optimizer does not seem quite correct to me:
x = myobject.b() ... z = myobject.c()
does not necessarily have a consistent pointer to myobject although it would require some acrobatics to change them in a way that can not be seen by an optimizer. You can think about exec() or even another thread intervening into a generator function, not something I would do but who knows.
If myobject is a local variable it's actually very simple to know just from looking at the bytecodes in between.
The advantage of the construct is that the .dotted variable is guaranteed to point to the same physical object in memory with an increased reference count during the statement and a decrease happening at dedent.
I think you're barking up the wrong tree. If you want this construct you have to explain how it makes code clearer, more readable, more writable, less error-prone.
Django would break when the 'using' keyword would be used for that, but the choice of keyword is arbitrary. Maybe an extended use of the 'with' word would be elegant, when the object would not have an __enter__ and/or __exit__ function it could still run for the purpose of this mechanism. The disadvantage is that you could not use the with construct for this purpose only without also triggering the __enter__ function.
Mixing this into 'with' would be terrible, because the two constructs have nothing in common. The choice if keyword is not entirely arbitrary; if we can't come up with a decent keyword the feature is dead. But the introduction would have to include a `from __future__ import <something>` statement anyway for at least one, maybe two release cycles (we did this with the `with` statement itself, around 2.4/2.5). So Django will have plenty of time to change. -- --Guido van Rossum (python.org/~guido)
On May 2, 2016 7:55 AM, "Robert van Geel" <robert@bign.nl> wrote:
I'm receiving digests and seem to not have each individual mail, so
here's a digested response:
One side of this that's not discussed is the possible optimization. I can
imagine if you've got a lot of objectproperty write and -reads this could actually make certain use cases a lot faster such as this one, saving 6 opcodes:
def __init__(self, left, top, width, height, content): self.left = left self.top = top self.width = width self.height = height self.content = content.upper() self.decideColors() self.draw()
versus:
def __init__(self, left, top, width, height, content): with self: .left = left .top = top .width = width .height = height .content = content.upper() .decideColors() .draw()
The suggestion that you could accomplish this with a (peephole) optimizer
does not seem quite correct to me:
x = myobject.b() ... z = myobject.c()
does not necessarily have a consistent pointer to myobject although it
would require some acrobatics to change them in a way that can not be seen by an optimizer.
You can think about exec() or even another thread intervening into a generator function, not something I would do but who knows.
It's actually part of CPython's current semantics that local variables cannot be modified via stack introspection exactly because it allows certain optimizations. You can read them, it might look like you can touch them (you can get access to what's allegedly the real dict of locals), but this is an illusion: modifications to that dict are not reflected back to the running code. See PyFrame_LocalsToFast and vice versa. So teaching the peephole optimizer to do this would be legal afaict. I'd be surprised and interested to see an example where those 6 opcodes made any non-trivial difference to a real program though -- thanks to the above-mentioned optimizations, accessing a local variable is already one of CPython's fastest operations. -n
On May 02, 2016, at 04:25 PM, Robert van Geel wrote:
Django would break when the 'using' keyword would be used for that
Not that it's super popular, but I'd hate to lose 'using' to a keyword too. http://flufli18n.readthedocs.io/en/latest/docs/using.html Cheers, -Barry
On May 2, 2016 11:46 AM, "Barry Warsaw" <barry@python.org> wrote:
On May 02, 2016, at 04:25 PM, Robert van Geel wrote:
Django would break when the 'using' keyword would be used for that
Not that it's super popular, but I'd hate to lose 'using' to a keyword
too.
I guess the obvious alternative would be in namespace: ... The pandas folks would love to have something like this actually, if it let you write in some_table: total_height = height_feet * 12 + height_inches instead of the current some_table["total_height"] = some_table["height_feet"] * 12 + some_table["height_inches"] Of course this requires that the namespace be accessed via some kind of hookable interface, not just a built in object or dict. -n
On May 02, 2016, at 11:51 AM, Nathaniel Smith wrote:
I guess the obvious alternative would be
in namespace: ...
Reusing an existing keyword would be better, yes.
The pandas folks would love to have something like this actually, if it let you write
in some_table: total_height = height_feet * 12 + height_inches
instead of the current
some_table["total_height"] = some_table["height_feet"] * 12 + some_table["height_inches"]
My first impression was yuk! because it wouldn't be clear to me where to find those names upon visual inspection of the code. But after thinking about it, it seems kind of interesting. I think what you're proposing is a layering of additional namespaces stack on (under?) the standard ones.
Of course this requires that the namespace be accessed via some kind of hookable interface, not just a built in object or dict.
Something like: class Kevinspacey: def __namespace__(self): return self.__dict__ Then an instance of Kevinspacey could be used in an in-namespace clause: hopper = Kevinspacey() in hopper: ants = 1 hopper.ants -> 1 Cheers, -Barry
participants (4)
-
Barry Warsaw
-
Guido van Rossum
-
Nathaniel Smith
-
Robert van Geel