A few questions about customization and the docs, TIA: ------ http://www.python.org/dev/doc/devel/ref/customization.html tosses off this sentence in the section on rich comparisons: "A rich comparison method may return NotImplemented if it does not implement the operation for a given pair of arguments." ...but it says nothing about the effect that will have. Using Thomas Heller's search engine, I found http://www.python.org/dev/doc/devel/ref/types.html#l2h-59, which says "...Numeric methods and rich comparison methods may return this value if they do not implement the operation for the operands provided. (The interpreter will then try the reflected operation, or some other fallback, depending on the operator.) " This seems like the wrong place to bury the description of the mechanism for operating on heterogeneous arguments. Shouldn't a short description go into the Customization section of the docs? ------- It also mentions, "There are no reflected (swapped-argument) versions of these methods (to be used when the left argument does not support the operation but the right argument does)..." since these are the first binary operators described the whole concept of reflected methods hasn't been introduced yet, and the user has no reason to think that reflected versions should exist. [incidentally, "reflected" and "reflection" produce no hits with Thomas' engine] -------
I'll leave the doc questions for Fred (maybe better open a SF bug for them though). Then:
From what I could find in the docs, it's completely non-obvious how the following works for immutable objects in containers:
x = [ 1, 2, 3] x[1] += 3 x [1, 5, 3]
Is the sequence of operations described someplace?
Um, in the code. :-( Using dis(), you'll find that x[1]+=3 executes the following: 6 LOAD_FAST 0 (x) 9 LOAD_CONST 1 (1) 12 DUP_TOPX 2 15 BINARY_SUBSCR 16 LOAD_CONST 2 (3) 19 INPLACE_ADD 20 ROT_THREE 21 STORE_SUBSCR
How does Python decide that sequence elements are immutable?
Huh? It doesn't. If they were mutable, had you expected something else? >>> x = [[1], [3], [5]] >>> x[1] += [6] >>> x [[1], [3, 6], [5]] >>> Basically, += on an attribute or subscripted container does the following: (1) get the thing out (2) apply the inplace operation to the thing (3) put the thing back in The inplace operation, of course, is a binary operator that *may* modify its first operand in place, but *must* return the resulting value; if it modified the first operand in place, it *should* return that operand. If a type doesn't support an inplace operation, the regular binary operator is invoked instead. Does this help? (The whole thing is designed to be intuitive, but that probably doesn't work in your case. :-) --Guido van Rossum (home page: http://www.python.org/~guido/)
From: "Guido van Rossum" <guido@python.org>
Um, in the code. :-( Using dis(), you'll find that x[1]+=3 executes the following:
6 LOAD_FAST 0 (x) 9 LOAD_CONST 1 (1) 12 DUP_TOPX 2 15 BINARY_SUBSCR 16 LOAD_CONST 2 (3) 19 INPLACE_ADD 20 ROT_THREE 21 STORE_SUBSCR
How does Python decide that sequence elements are immutable?
Huh? It doesn't. If they were mutable, had you expected something else?
Actually, yes. I had expcected that Python would know it didn't need to "put the thing back in", since the thing gets modified in place. Knowing that it doesn't work that way clears up a lot.
>>> x = [[1], [3], [5]] >>> x[1] += [6] >>> x [[1], [3, 6], [5]] >>>
Well of /course/ I know that's the result. The question was, how is the result achieved?
Basically, += on an attribute or subscripted container does the following:
(1) get the thing out (2) apply the inplace operation to the thing (3) put the thing back in
The inplace operation, of course, is a binary operator that *may* modify its first operand in place, but *must* return the resulting value; if it modified the first operand in place, it *should* return that operand. If a type doesn't support an inplace operation, the regular binary operator is invoked instead.
That's the easy part.
Does this help? (The whole thing is designed to be intuitive, but that probably doesn't work in your case. :-)
I use this stuff from Python without thinking about it, but when it comes to building new types, I sometimes need to have a better sense of the underlying mechanism. Thanks, Dave P.S. Say, you could optimize away putting the thing back at runtime if the inplace operation returns its first argument... but you probably already thought of that one.
How does Python decide that sequence elements are immutable?
Huh? It doesn't. If they were mutable, had you expected something else?
Actually, yes. I had expcected that Python would know it didn't need to "put the thing back in", since the thing gets modified in place. Knowing that it doesn't work that way clears up a lot.
Still, I don't understand which other outcome than [1, 6, 5] you had expected. --Guido van Rossum (home page: http://www.python.org/~guido/)
From: "Guido van Rossum" <guido@python.org>
How does Python decide that sequence elements are immutable?
Huh? It doesn't. If they were mutable, had you expected something else?
Actually, yes. I had expcected that Python would know it didn't need to "put the thing back in", since the thing gets modified in place. Knowing that it doesn't work that way clears up a lot.
Still, I don't understand which other outcome than [1, 6, 5] you had expected.
As I indicated in my previous mail, I didn't expect any other result. My question was about what a new type needs to do in order for things to work properly in Python. If, as I had incorrectly assumed, Python were checking a type's mutability before deciding whether it would be putting the result back into the sequence, I would need to know what criteria Python uses to decide mutability. -Dave
On Sat, 1 Jun 2002, Guido van Rossum wrote:
How does Python decide that sequence elements are immutable?
Huh? It doesn't. If they were mutable, had you expected something else?
Actually, yes. I had expcected that Python would know it didn't need to "put the thing back in", since the thing gets modified in place. Knowing that it doesn't work that way clears up a lot.
Still, I don't understand which other outcome than [1, 6, 5] you had expected.
Well, _I_ would have expected this to work: Python 2.1 (#4, Jun 6 2001, 08:54:49) [GCC 2.95.2 19991024 (release)] on linux2 Type "copyright", "credits" or "license" for more information. >>> x = ([],[],[]) >>> x[1] += [1] Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: object doesn't support item assignment Given that the object x[1] can be (and is) modified in place, I find this behaviour quite counter-intuitive, specially considering: >>> z = x[1] >>> z += [2] >>> x ([], [1, 2], []) /Paul
Well, _I_ would have expected this to work:
Python 2.1 (#4, Jun 6 2001, 08:54:49) [GCC 2.95.2 19991024 (release)] on linux2 Type "copyright", "credits" or "license" for more information.
x = ([],[],[]) x[1] += [1] Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: object doesn't support item assignment
Yes, but that can't be fixed without breaking other things. Too bad. It's not like this is an important use case in real life. --Guido van Rossum (home page: http://www.python.org/~guido/)
participants (3)
-
David Abrahams
-
Guido van Rossum
-
Paul Svensson