User-defined augmented assignment

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Pierre Barbier de Reuille

    #1

    User-defined augmented assignment

    Hello,

    a discussion began on python-dev about this. It began by a bug report,
    but is shifted and it now belongs to this discussion group.

    The problem I find with augmented assignment is it's too complex, it's
    badly explained, it's error-prone. And most of all, I don't see any
    use-case for it !

    The most common error is to consider that :

    a += b <==> a.__iadd__(b)

    when the truth is :

    a += b <==> a = a.__iadd__(b)

    which can be very confusing, as the two "a" are not necessarily the
    same. It then leads to subtle errors like:
    [color=blue][color=green][color=darkred]
    >>> class A(object):
    >>> a = 0[/color][/color][/color]
    [color=blue][color=green][color=darkred]
    >>> a = A()
    >>> b = A()
    >>> a.a += 1
    >>> A.a += 2
    >>> print a.a[/color][/color][/color]
    1[color=blue][color=green][color=darkred]
    >>> print b.a[/color][/color][/color]
    2

    Also, the following behavior is pretty confusing :
    [color=blue][color=green][color=darkred]
    >>> a = [1]
    >>> b = [a]
    >>> c = (a,)
    >>> b[0] += [2] # Ok, no pb
    >>> print a[/color][/color][/color]
    [1,2][color=blue][color=green][color=darkred]
    >>> c[0] += [3][/color][/color][/color]
    Traceback (most recent call last):
    File "<string>", line 1, in ?
    TypeError: object doesn't support item assignment[color=blue][color=green][color=darkred]
    >>> print a[/color][/color][/color]
    [1,2,3]

    Then, in the standard library, there is no use-case of user-defined
    augmented assignment I could find. Of course, I find the augmented
    assignement itself very useful ! I use it a lot with immutable objects
    (strings, numbers, tuples, ...) but I tend to avoid it with mutables,
    and so it seems in the standard library that uses extensively the
    "extend" method of lists and very seldom the "+=" operator with lists.
    And even where the "a+=b" is used, it could be replaced with either
    "a.extend(b )" or "a = a+b" without bugs.

    So, what I would suggest is to drop the user-defined augmented
    assignment and to ensure this equivalence :

    a X= b <=> a = a X b

    with 'X' begin one of the operators.

    Pierre
  • Reinhold Birkenfeld

    #2
    Re: User-defined augmented assignment

    Pierre Barbier de Reuille wrote:
    [color=blue]
    > So, what I would suggest is to drop the user-defined augmented
    > assignment and to ensure this equivalence :
    >
    > a X= b <=> a = a X b
    >
    > with 'X' begin one of the operators.[/color]

    It can be done, but it's unnecessary for mutable objects like
    sets or lists. A new object must be created in these cases where
    one would suffice.

    Reinhold

    Comment

    • Pierre Barbier de Reuille

      #3
      Re: User-defined augmented assignment

      Reinhold Birkenfeld a écrit :[color=blue]
      > Pierre Barbier de Reuille wrote:
      >
      >[color=green]
      >>So, what I would suggest is to drop the user-defined augmented
      >>assignment and to ensure this equivalence :
      >>
      >>a X= b <=> a = a X b
      >>
      >>with 'X' begin one of the operators.[/color]
      >
      >
      > It can be done, but it's unnecessary for mutable objects like
      > sets or lists. A new object must be created in these cases where
      > one would suffice.[/color]

      Well, my point is: the benefit is too small compared to the
      disadvantage. If you really have a mutable (let say a list with +=) then
      you do:
      [color=blue][color=green][color=darkred]
      >>> a.extend(b)[/color][/color][/color]

      and there is no interpretation error possible. BTW, that's what's done
      in the standard library ...

      Pierre
      [color=blue]
      >
      > Reinhold[/color]

      Comment

      • Paddy

        #4
        Re: User-defined augmented assignment

        I thought along these lines:
        It is an augmented ASSIGNMENT. (It even has an equals sign in it).
        tuples are immutable so you should not be able to assign to one of
        its elements.

        - So there is no problem for me - I shouldn't be messing with an
        element of an
        immutable type!

        - Cheers, Paddy.

        Comment

        • Tom Anderson

          #5
          Re: User-defined augmented assignment

          On Thu, 29 Sep 2005, Pierre Barbier de Reuille wrote:
          [color=blue]
          > a discussion began on python-dev about this. It began by a bug report,
          > but is shifted and it now belongs to this discussion group.
          >
          > The problem I find with augmented assignment is it's too complex, it's
          > badly explained, it's error-prone. And most of all, I don't see any
          > use-case for it !
          >
          > The most common error is to consider that :
          >
          > a += b <==> a.__iadd__(b)
          >
          > when the truth is :
          >
          > a += b <==> a = a.__iadd__(b)
          >
          > which can be very confusing, as the two "a" are not necessarily the
          > same.[/color]

          Indeed. I certainly didn't realise that was how it worked.
          [color=blue]
          > So, what I would suggest is to drop the user-defined augmented
          > assignment and to ensure this equivalence :
          >
          > a X= b <=> a = a X b
          >
          > with 'X' begin one of the operators.[/color]

          That seems quite an odd move. Your proposal would lead to even more
          surprising behaviour; consider this:

          a = [1, 2, 3]
          b = a
          a += [4, 5, 6]
          print b

          At present, this prints [1, 2, 3, 4, 5, 6]; if we were to follow your
          suggestion, it would be [1, 2, 3].

          So, -1, i'm afraid.

          I think the right solution here is staring us in the face: if everyone
          seems to think that:

          a += b <==> a.__iadd__(b)

          Then why not make it so that:

          a += b <==> a.__iadd__(b)

          Principle of Least Surprise and all that.

          Since not everything that should support += is mutable (integers, for
          example), how about saying that if the recipient of a += doesn't have an
          __iadd__ method, execution falls back to:

          a = a + b

          I say 'a + b', because that means we invoke __add__ and __radd__
          appropriately; indeed, the __add__ vs __radd__ thing is a precedent for
          this sort of fallback.

          Doesn't that leave everyone happy?

          tom

          --
          I'm not quite sure how that works but I like it ...

          Comment

          Working...