From: Patrick Maupin on
On May 1, 7:13 am, Tim Chase <t...(a)thechases.com> wrote:
> On 05/01/2010 12:08 AM, Patrick Maupin wrote:
>
> > +=, -=, /=, *=, etc.  conceptually (and, if lhs object supports in-
> > place operator methods, actually) *modify* the lhs object.
>
> > Your proposed .= syntax conceptually *replaces* the lhs object
> > (actually, rebinds the lhs symbol to the new object).
>
> The += family of operators really do rebind the symbol, not
> modify the object.
>
>    >>> from decimal import Decimal
>    >>> d = Decimal(42)
>    >>> e = Decimal(18)
>    >>> orig = d
>    >>> d += e
>    >>> d
>    Decimal("60")
>    >>> e
>    Decimal("18")
>    >>> orig
>    Decimal("42")
>    >>> d is orig
>    False
>
> If your suggestion that += *modifies* the object, then orig would
> now unintuitively contain 60 and "d is orig" would return True.

Well, I wrote "conceptually" (which I believe is true; it's certainly
true for me) and "sometimes actually" (which I know is true):

>>> x = [1,2,3,4,5]
>>> y = x
>>> x += [6]
>>> y
[1, 2, 3, 4, 5, 6]

>>>
>>> x = set()
>>> y = x
>>> x |= set([1])
>>> y
set([1])

SO, if you find those results "unintuitive", perhaps you should
upgrade your understanding of python. Personally, I don't find any of
the results I gave, or the results you gave, surprising, so I'm not
saying my "conceptually and sometimes actually modifies the result" is
right for *you* but it works great for me. :-)

> This doesn't preclude you from implementing a self-mutating +=
> style __add__ method and returning "self", but it's usually a bad
> idea unless it's dire for performance (and even then, think it
> over a couple times).

Well, you should submit a bug report to fix the operation of lists and
sets for a starter.

But first, you might want to read PEP 203 -- augmented assignments. I
particularly like the section which says:

"The idea behind augmented assignment in Python is that it isn't just
an easier way to write the common practice of storing the result of a
binary operation in its left-hand operand, but also a way for the left-
hand operand in question to know that it should operate `on itself',
rather than creating a modified copy of itself."

There are a lot of sections which have a similar flavor. If (which I
doubt), the "augmented dot" is accepted, it won't necessarily have the
same meaning. x = x.foo could replace x with any other kind of
object, and I view it as a replacement, while I view x += foo as a
modification.

Regards,
Pat
From: D'Arcy J.M. Cain on
On Sun, 02 May 2010 05:08:53 +1000
Lie Ryan <lie.1296(a)gmail.com> wrote:
> On 05/01/10 11:16, Steven D'Aprano wrote:
> > On Fri, 30 Apr 2010 12:34:34 -0400, D'Arcy J.M. Cain wrote:
> >
> > In practice though, I think that's a difference that makes no difference.
> > It walks like an operator, it swims like an operator, and it quacks like
> > an operator.
> >
>
> Nope it's not. A full-time operator in python have a reflected version

Hi. Please watch the attributions. I didn't write that. I was the
one who said that '.' was not an operator.

--
D'Arcy J.M. Cain <darcy(a)druid.net> | Democracy is three wolves
http://www.druid.net/darcy/ | and a sheep voting on
+1 416 425 1212 (DoD#0082) (eNTP) | what's for dinner.
From: Steven D'Aprano on
On Sun, 02 May 2010 05:08:53 +1000, Lie Ryan wrote:

> On 05/01/10 11:16, Steven D'Aprano wrote:
>> On Fri, 30 Apr 2010 12:34:34 -0400, D'Arcy J.M. Cain wrote:
>>
>> In practice though, I think that's a difference that makes no
>> difference. It walks like an operator, it swims like an operator, and
>> it quacks like an operator.
>>
>>
> Nope it's not. A full-time operator in python have a reflected version
> (e.g. __radd__), which dot does not have.

What are the reflected versions of __eq__ and __ne__ (binary == and !=
operators)?

And __neg__, __pos__ and __inv__ (for the unary - + and ~ operators)?

And the three-argument form of __pow__ for power(1, 2, x)?



> And Python's object system
> makes it that the argument to __getattr__ is always a string even though
> there might be a valid variable that corresponds to it:

That is nothing to do with the object system, it is related to the
semantics of Python syntax. a.b doesn't mean "apply the binary dot
operator to arguments a and b". It is syntactic sugar for "look for an
attribute named 'b' on object a". As such, the operands that __getattr__
receives are the object a and the *name* b (implemented as a string).

Also, the implementation of attribute lookup is quite complex, with all
sorts of special cases and optimizations.


> a = MyClass()
> b = MyClass()
> print a . b
>
> I've often wanted to figure out a way to (ab)use python's dot operator
> for function composition (i.e. f.g(x) ==> f(g(x)) ). There's no way to
> do it, not without being way too hackish.

That's a good example of where the difference does make a difference.



--
Steven
From: Steven D'Aprano on
On Sat, 01 May 2010 07:13:42 -0500, Tim Chase wrote:

> On 05/01/2010 12:08 AM, Patrick Maupin wrote:
>> +=, -=, /=, *=, etc. conceptually (and, if lhs object supports in-
>> place operator methods, actually) *modify* the lhs object.
>>
>> Your proposed .= syntax conceptually *replaces* the lhs object
>> (actually, rebinds the lhs symbol to the new object).
>
> The += family of operators really do rebind the symbol, not modify the
> object.

They potentially do both, depending on the object, even for built-ins.


> >>> from decimal import Decimal
[...]

I'm not sure why you took the trouble to import Decimal for this example,
when you could have shown the same thing with built-ins int or float. All
three types are immutable.

A counter example with a mutable type:

>>> a = []
>>> b = a
>>> a += [2]
>>> a
[2]
>>> b
[2]

thus demonstrating that __iadd__ modifies in place as well as rebinds for
at least one mutable type.

> This doesn't preclude you from implementing a self-mutating += style
> __add__ method and returning "self", but it's usually a bad idea

Obviously the Python dev team don't agree with that :)

Just to prove that += for lists is not an accident:

>>> a = set()
>>> b = a
>>> a |= set([1])
>>> a
set([1])
>>> b
set([1])



--
Steven
From: Chris Rebert on
On Sat, May 1, 2010 at 6:32 PM, Steven D'Aprano
<steve(a)remove-this-cybersource.com.au> wrote:
> On Sat, 01 May 2010 07:13:42 -0500, Tim Chase wrote:
>> This doesn't preclude you from implementing a self-mutating += style
>> __add__ method and returning "self", but it's usually a bad idea
>
> Obviously the Python dev team don't agree with that :)
>
> Just to prove that += for lists is not an accident:
>
>>>> a = set()
>>>> b = a
>>>> a |= set([1])
>>>> a
> set([1])
>>>> b
> set([1])

In both cases, __iOP__ operator methods are being used, not vanilla
__OP__ methods, so neither of your examples are relevant to Mr.
Chase's point.

Cheers,
Chris
--
http://blog.rebertia.com