Augmented Assignment question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Doug Tolton

    Augmented Assignment question

    I have a function that returns a tuple:

    def checkdoc(self, document):
    blen = document['length']
    bates = document['obates']

    normal, truncated, semicolon = 0,0,0
    for bat in bates:
    if len(bat) == 2 * blen:
    semicolon += 1
    if len(bat) == blen - 1:
    truncated += 1
    if len(bat) == blen:
    normal += 1

    return normal, truncated, semicolon

    on the other side I have 3 variables:
    normal, truncated and semicolon

    I would like to be able to do an augmented assignment such as:

    normal, truncated, semicol += self.checkdoc(m ydoc)

    however this returns the following error:
    SyntaxError: augmented assign to tuple not possible

    I did some reading and it seems that an augmented assignment is
    specifically verboten on tuples and lists. Is there a clean way to
    accomplish this? I dislike in the extreme what I've resorted to:

    fnormal, ftruncated, fsemicolon = 0,0,0

    // loop through a file and process all documents:
    normal, truncated, semicolon = self.checkdoc(c urdoc)
    fnormal += normal
    ftruncated += truncated
    fsemicolon += semicolon

    This solution strikes me as inelegant and ugly. Is there a cleaner
    way of accomplishing this?

    Thanks in advance,
    Doug Tolton
    dougt at<remove this>case<remov e this too>data dot com
  • Adam Ruth

    #2
    Re: Augmented Assignment question

    In <215bhv0bnkn13e ivh0s64ic5ml8ob [email protected]> Doug Tolton wrote:[color=blue]
    > I have a function that returns a tuple:
    >
    > def checkdoc(self, document):
    > blen = document['length']
    > bates = document['obates']
    >
    > normal, truncated, semicolon = 0,0,0
    > for bat in bates:
    > if len(bat) == 2 * blen:
    > semicolon += 1
    > if len(bat) == blen - 1:
    > truncated += 1
    > if len(bat) == blen:
    > normal += 1
    >
    > return normal, truncated, semicolon
    >
    > on the other side I have 3 variables:
    > normal, truncated and semicolon
    >
    > I would like to be able to do an augmented assignment such as:
    >
    > normal, truncated, semicol += self.checkdoc(m ydoc)
    >
    > however this returns the following error:
    > SyntaxError: augmented assign to tuple not possible
    >
    > I did some reading and it seems that an augmented assignment is
    > specifically verboten on tuples and lists. Is there a clean way to
    > accomplish this? I dislike in the extreme what I've resorted to:
    >
    > fnormal, ftruncated, fsemicolon = 0,0,0
    >
    > // loop through a file and process all documents:
    > normal, truncated, semicolon = self.checkdoc(c urdoc)
    > fnormal += normal
    > ftruncated += truncated
    > fsemicolon += semicolon
    >
    > This solution strikes me as inelegant and ugly. Is there a cleaner
    > way of accomplishing this?
    >
    > Thanks in advance,
    > Doug Tolton
    > dougt at<remove this>case<remov e this too>data dot com
    >[/color]

    I don't think it's all that inelegant, and it's definitely clear. I can
    see, though, why a one liner would seem a little cleaner.

    Off the top of my head, I'd say to change your checkdoc function to this:
    [color=blue]
    > def checkdoc(self, document, normal=0, truncated=0, semicolon=0):
    > blen = document['length']
    > bates = document['obates']
    > for bat in bates:
    > if len(bat) == 2 * blen:
    > semicolon += 1
    > if len(bat) == blen - 1:
    > truncated += 1
    > if len(bat) == blen:
    > normal += 1
    >
    > return normal, truncated, semicolon[/color]

    And then call it like this:
    [color=blue]
    > normal, truncated, semicolon = self.checkdoc(c urdoc, normal,
    > truncated, semicolon)[/color]

    As a side note, I wouldn't have thought that the augmented assign would
    work the way you tried to use it. I would have thought that it would be
    analagous to the + operator and sequences:
    [color=blue]
    > x = [1,2,3]
    > y = [1,2,3]
    > x + y[/color]
    [1,2,3,1,2,3]

    So that the agumented form would be:
    [color=blue]
    > x = [1,2,3]
    > x += [1,2,3][/color]
    [1,2,3,1,2,3]

    But I've never tried it before and didn't know that it didn't work with
    sequences. You learn something new every day.

    Adam Ruth

    Comment

    • Aahz

      #3
      Re: Augmented Assignment question

      In article <215bhv0bnkn13e ivh0s64ic5ml8ob [email protected]>,
      Doug Tolton <dtolton@yahoo. com> wrote:[color=blue]
      >
      >I did some reading and it seems that an augmented assignment is
      >specifically verboten on tuples and lists. Is there a clean way to
      >accomplish this?[/color]

      Really?
      [color=blue][color=green][color=darkred]
      >>> l = []
      >>> l+=[1]
      >>> l[/color][/color][/color]
      [1][color=blue][color=green][color=darkred]
      >>> l+=['foo']
      >>> l[/color][/color][/color]
      [1, 'foo']
      --
      Aahz (aahz@pythoncra ft.com) <*> http://www.pythoncraft.com/

      A: No.
      Q: Is top-posting okay?

      Comment

      • Tim Lesher

        #4
        Re: Augmented Assignment question

        Doug Tolton <dtolton@yahoo. com> wrote in message news:<215bhv0bn kn13eivh0s64ic5 ml8obpgfg7@4ax. com>...[color=blue]
        > This solution strikes me as inelegant and ugly. Is there a cleaner
        > way of accomplishing this?[/color]

        The problem is this: performing addition of tuples is concatenation,
        not addition of the elements. If you try to decompose the augmented
        addition into an addition and an assignment, you get a tuple that is
        (in your case) the concatenation of the two 3-tuples, or a 6-tuple,
        which can't unpack into a 3-tuple.

        That said, for some definition of "cleaner", you could do:
        def accumulate(i,j) :
        return map(int.__add__ , i, j)

        // loop
        i,j,k = accumulate((i,j ,k), fn())

        Comment

        • Steven Taschuk

          #5
          Re: Augmented Assignment question

          Quoth Doug Tolton:
          [...][color=blue]
          > fnormal, ftruncated, fsemicolon = 0,0,0
          >
          > // loop through a file and process all documents:
          > normal, truncated, semicolon = self.checkdoc(c urdoc)
          > fnormal += normal
          > ftruncated += truncated
          > fsemicolon += semicolon
          >
          > This solution strikes me as inelegant and ugly. Is there a cleaner
          > way of accomplishing this?[/color]

          It seems possible that your normal, truncated and semicolon
          variables should be bundled into a single object:

          class DocumentStatist ics(object):
          # ...
          def __iadd__(self, (deltanormal, deltatruncated, deltasemicolon) ):
          self.normal += deltanormal
          self.truncated += deltatruncated
          self.semicolon += deltasemicolon

          Then you can just do
          docstats = DocumentStatist ics()
          # ...
          docstats += self.checkdoc(c urdoc)
          If these variables usually change in synch, this seems a natural
          way to organize them.

          You might also want to look into Numeric's arrays.

          (And there's always

          normal, truncated, semicolon = map(operator.ad d,
          (normal, truncated, semicolon),
          self.checkdoc(c urdoc))

          which I consider inferior to your straightforward approach with
          three augmented assignments.)

          --
          Steven Taschuk staschuk@telusp lanet.net
          "Please don't damage the horticulturalis t."
          -- _Little Shop of Horrors_ (1960)

          Comment

          • Bengt Richter

            #6
            Re: Augmented Assignment question

            On Wed, 16 Jul 2003 22:17:40 GMT, Doug Tolton <dtolton@yahoo. com> wrote:
            [color=blue]
            >On 16 Jul 2003 16:51:38 -0400, aahz@pythoncraf t.com (Aahz) wrote:
            >[color=green]
            >>In article <215bhv0bnkn13e ivh0s64ic5ml8ob [email protected]>,
            >>Doug Tolton <dtolton@yahoo. com> wrote:[color=darkred]
            >>>
            >>>I did some reading and it seems that an augmented assignment is
            >>>specifical ly verboten on tuples and lists. Is there a clean way to
            >>>accomplish this?[/color]
            >>
            >>Really?
            >>[color=darkred]
            >>>>> l = []
            >>>>> l+=[1]
            >>>>> l[/color]
            >>[1][color=darkred]
            >>>>> l+=['foo']
            >>>>> l[/color]
            >>[1, 'foo'][/color]
            >
            >
            >I mis-spoke, lists are not included. You cannot do augmented
            >assignments on tuples or multiple targets.
            >
            >you can do what you typed, but you can't do.
            >[color=green][color=darkred]
            >>>> a,b = 0,0
            >>>> a,b += 1,1[/color][/color]
            >SyntaxError: augmented assign to tuple not possible
            >
            >or this:
            >[color=green][color=darkred]
            >>>> a,b = [],[]
            >>>> a,b += [1],[1][/color][/color]
            >SyntaxError: augmented assign to tuple not possible
            >
            >That is specifically the point I was getting at. Forgive the
            >technical slip of including lists in the discussion.
            >[/color]
            A little experiment (not tested beyond what you see ;-):
            [color=blue][color=green][color=darkred]
            >>> class TX(tuple):[/color][/color][/color]
            ... def __add__(self, other):
            ... return TX([s+o for s,o in zip(self, other)])
            ...[color=blue][color=green][color=darkred]
            >>> tx = TX((2,2))
            >>> tx[/color][/color][/color]
            (2, 2)[color=blue][color=green][color=darkred]
            >>> tx + (3,5)[/color][/color][/color]
            (5, 7)[color=blue][color=green][color=darkred]
            >>> tx[/color][/color][/color]
            (2, 2)[color=blue][color=green][color=darkred]
            >>> tx += (3,5)
            >>> tx[/color][/color][/color]
            (5, 7)[color=blue][color=green][color=darkred]
            >>> tx += 10,20
            >>> tx[/color][/color][/color]
            (15, 27)[color=blue][color=green][color=darkred]
            >>> tt = TX(('ab','cd',' ef'))
            >>> tt[/color][/color][/color]
            ('ab', 'cd', 'ef')[color=blue][color=green][color=darkred]
            >>> tt += '123'
            >>> tt[/color][/color][/color]
            ('ab1', 'cd2', 'ef3')


            Regards,
            Bengt Richter

            Comment

            • John Machin

              #7
              Re: Augmented Assignment question

              Doug Tolton <dtolton@yahoo. com> wrote in message news:<215bhv0bn kn13eivh0s64ic5 ml8obpgfg7@4ax. com>...[color=blue]
              > I have a function that returns a tuple:
              >
              > def checkdoc(self, document):
              > blen = document['length']
              > bates = document['obates']
              >
              > normal, truncated, semicolon = 0,0,0
              > for bat in bates:
              > if len(bat) == 2 * blen:
              > semicolon += 1
              > if len(bat) == blen - 1:
              > truncated += 1
              > if len(bat) == blen:
              > normal += 1[/color]

              self.total_norm al += normal
              # etc etc
              # someone else suggested a separate class just for statistics
              # --- this is overkill IMHO[color=blue]
              >
              > return normal, truncated, semicolon
              >[/color]

              Comment

              Working...