Simulating call-by-reference

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Rikard Bosnjakovic

    #1

    Simulating call-by-reference

    I'm tidying up some code. Basically, the code runs a bunch of
    regexp-searches (> 10) on a text and stores the match in a different variable.

    Like this:

    re1 = r' ..(.*).. '
    re2 = r' .... '
    re3 = r' .(.*).. '
    ...
    m = re.search(re1, data)
    if m:
    myclass.bar = m.group(1)

    m = re.search(re2, data)
    if m:
    myclass.foo = m.group(1)

    m = re.search(re3, data)
    if m:
    myclass.baz = m.group(1)


    While this code works, it's not very good looking.

    What I want is to rewrite it to something like this:

    l = [ (re1, myclass.bar),
    (re2, myclass.foo),
    (re3, myclass.baz),
    ]

    for (x,y) in l:
    m = re.search(x, y)
    if m:
    y = m.group(1)

    But since Python doesn't work that way, that idea is doomed. What I'm
    looking for are other (better) ways or pointers to accomplish this task of
    cleanup.


    --
    Sincerely, | http://bos.hack.org/cv/
    Rikard Bosnjakovic | Code chef - will cook for food
    ------------------------------------------------------------------------
  • bonono@gmail.com

    #2
    Re: Simulating call-by-reference


    Rikard Bosnjakovic wrote:[color=blue]
    > I'm tidying up some code. Basically, the code runs a bunch of
    > regexp-searches (> 10) on a text and stores the match in a different variable.
    >
    > Like this:
    >
    > re1 = r' ..(.*).. '
    > re2 = r' .... '
    > re3 = r' .(.*).. '
    > ...
    > m = re.search(re1, data)
    > if m:
    > myclass.bar = m.group(1)
    >
    > m = re.search(re2, data)
    > if m:
    > myclass.foo = m.group(1)
    >
    > m = re.search(re3, data)
    > if m:
    > myclass.baz = m.group(1)
    >
    >
    > While this code works, it's not very good looking.
    >
    > What I want is to rewrite it to something like this:
    >
    > l = [ (re1, myclass.bar),
    > (re2, myclass.foo),
    > (re3, myclass.baz),
    > ]
    >
    > for (x,y) in l:
    > m = re.search(x, y)
    > if m:
    > y = m.group(1)
    >
    > But since Python doesn't work that way, that idea is doomed. What I'm
    > looking for are other (better) ways or pointers to accomplish this task of
    > cleanup.
    > -----------------[/color]

    I believe you can use the "setattr/getattr" call

    l = [ (re1, myclass, "bar") ]

    for x,y,z in l:
    m = re.search(x,get attr(y,z))
    if m: setattr(y,z,m.g roup(1))

    Comment

    • bonono@gmail.com

      #3
      Re: Simulating call-by-reference


      Rikard Bosnjakovic wrote:[color=blue]
      > I'm tidying up some code. Basically, the code runs a bunch of
      > regexp-searches (> 10) on a text and stores the match in a different variable.
      >
      > Like this:
      >
      > re1 = r' ..(.*).. '
      > re2 = r' .... '
      > re3 = r' .(.*).. '
      > ...
      > m = re.search(re1, data)
      > if m:
      > myclass.bar = m.group(1)
      >
      > m = re.search(re2, data)
      > if m:
      > myclass.foo = m.group(1)
      >
      > m = re.search(re3, data)
      > if m:
      > myclass.baz = m.group(1)
      >
      >
      > While this code works, it's not very good looking.
      >
      > What I want is to rewrite it to something like this:
      >
      > l = [ (re1, myclass.bar),
      > (re2, myclass.foo),
      > (re3, myclass.baz),
      > ]
      >
      > for (x,y) in l:
      > m = re.search(x, y)
      > if m:
      > y = m.group(1)
      >
      > But since Python doesn't work that way, that idea is doomed. What I'm
      > looking for are other (better) ways or pointers to accomplish this task of
      > cleanup.
      > -----------------[/color]

      I believe you can use the "setattr/getattr" call

      l = [ (re1, myclass, "bar") ]

      for x,y,z in l:
      m = re.search(x,get attr(y,z))
      if m: setattr(y,z,m.g roup(1))

      Comment

      • Dan Sommers

        #4
        Re: Simulating call-by-reference

        On Thu, 17 Nov 2005 10:03:50 GMT,
        Rikard Bosnjakovic <bos@REMOVETHIS hack.org> wrote:
        [color=blue]
        > What I want is to rewrite it to something like this:[/color]
        [color=blue]
        > l = [ (re1, myclass.bar),
        > (re2, myclass.foo),
        > (re3, myclass.baz),
        > ][/color]
        [color=blue]
        > for (x,y) in l:
        > m = re.search(x, y)
        > if m:
        > y = m.group(1)[/color]
        [color=blue]
        > But since Python doesn't work that way, that idea is doomed. What I'm
        > looking for are other (better) ways or pointers to accomplish this
        > task of cleanup.[/color]

        Put the results into a dictionary (untested code follows!):

        l = [ (re1, 'bar'),
        (re2, 'foo'),
        (re3, 'baz'),
        ]
        results = {}
        for (regexp, key) in l:
        m = re.search(regex p, data)
        if m:
        results[key] = m.group(1)

        Now you can access the results as results['foo'], etc. Or look up the
        Borg pattern in the ASPN cookbook and you can access the results as
        results.foo, etc.

        Regards,
        Dan

        --
        Dan Sommers
        <http://www.tombstoneze ro.net/dan/>

        Comment

        • Dan Sommers

          #5
          Re: Simulating call-by-reference

          On Thu, 17 Nov 2005 10:03:50 GMT,
          Rikard Bosnjakovic <bos@REMOVETHIS hack.org> wrote:
          [color=blue]
          > What I want is to rewrite it to something like this:[/color]
          [color=blue]
          > l = [ (re1, myclass.bar),
          > (re2, myclass.foo),
          > (re3, myclass.baz),
          > ][/color]
          [color=blue]
          > for (x,y) in l:
          > m = re.search(x, y)
          > if m:
          > y = m.group(1)[/color]
          [color=blue]
          > But since Python doesn't work that way, that idea is doomed. What I'm
          > looking for are other (better) ways or pointers to accomplish this
          > task of cleanup.[/color]

          Put the results into a dictionary (untested code follows!):

          l = [ (re1, 'bar'),
          (re2, 'foo'),
          (re3, 'baz'),
          ]
          results = {}
          for (regexp, key) in l:
          m = re.search(regex p, data)
          if m:
          results[key] = m.group(1)

          Now you can access the results as results['foo'], etc. Or look up the
          Borg pattern in the ASPN cookbook and you can access the results as
          results.foo, etc.

          Regards,
          Dan

          --
          Dan Sommers
          <http://www.tombstoneze ro.net/dan/>

          Comment

          • Alex Martelli

            #6
            Re: Simulating call-by-reference

            Dan Sommers <me@privacy.net > wrote:
            ...[color=blue]
            > Put the results into a dictionary (untested code follows!):
            >
            > l = [ (re1, 'bar'),
            > (re2, 'foo'),
            > (re3, 'baz'),
            > ]
            > results = {}
            > for (regexp, key) in l:
            > m = re.search(regex p, data)
            > if m:
            > results[key] = m.group(1)
            >
            > Now you can access the results as results['foo'], etc. Or look up the
            > Borg pattern in the ASPN cookbook and you can access the results as
            > results.foo, etc.[/color]

            I think you mean the Bunch idiom, rather than the Borg one (which has to
            do with having instances of the same class share state).

            Personally, I would rather pass myvar as well as the attribute names,
            and set them with setattr, as I see some others already suggested.


            Alex

            Comment

            • Dan Sommers

              #7
              Re: Simulating call-by-reference

              On Thu, 17 Nov 2005 12:31:08 -0800,
              aleax@mail.comc ast.net (Alex Martelli) wrote:
              [color=blue]
              > Dan Sommers <me@privacy.net > wrote:
              > ...[color=green]
              >> Put the results into a dictionary (untested code follows!):[/color][/color]

              [ example code snipped ]
              [color=blue][color=green]
              >> Now you can access the results as results['foo'], etc. Or look up
              >> the Borg pattern in the ASPN cookbook and you can access the results
              >> as results.foo, etc.[/color][/color]
              [color=blue]
              > I think you mean the Bunch idiom, rather than the Borg one (which has to
              > do with having instances of the same class share state).[/color]

              Oops. <sheepish grin>

              You're right.

              Sorry.
              [color=blue]
              > Personally, I would rather pass myvar as well as the attribute names,
              > and set them with setattr, as I see some others already suggested.[/color]

              I lose track of things too easily that way. YMMV.

              Regards,
              Dan

              --
              Dan Sommers
              <http://www.tombstoneze ro.net/dan/>

              Comment

              • Alex Martelli

                #8
                Re: Simulating call-by-reference

                Dan Sommers <me@privacy.net > wrote:
                ...[color=blue]
                > Put the results into a dictionary (untested code follows!):
                >
                > l = [ (re1, 'bar'),
                > (re2, 'foo'),
                > (re3, 'baz'),
                > ]
                > results = {}
                > for (regexp, key) in l:
                > m = re.search(regex p, data)
                > if m:
                > results[key] = m.group(1)
                >
                > Now you can access the results as results['foo'], etc. Or look up the
                > Borg pattern in the ASPN cookbook and you can access the results as
                > results.foo, etc.[/color]

                I think you mean the Bunch idiom, rather than the Borg one (which has to
                do with having instances of the same class share state).

                Personally, I would rather pass myvar as well as the attribute names,
                and set them with setattr, as I see some others already suggested.


                Alex

                Comment

                • Dan Sommers

                  #9
                  Re: Simulating call-by-reference

                  On Thu, 17 Nov 2005 12:31:08 -0800,
                  aleax@mail.comc ast.net (Alex Martelli) wrote:
                  [color=blue]
                  > Dan Sommers <me@privacy.net > wrote:
                  > ...[color=green]
                  >> Put the results into a dictionary (untested code follows!):[/color][/color]

                  [ example code snipped ]
                  [color=blue][color=green]
                  >> Now you can access the results as results['foo'], etc. Or look up
                  >> the Borg pattern in the ASPN cookbook and you can access the results
                  >> as results.foo, etc.[/color][/color]
                  [color=blue]
                  > I think you mean the Bunch idiom, rather than the Borg one (which has to
                  > do with having instances of the same class share state).[/color]

                  Oops. <sheepish grin>

                  You're right.

                  Sorry.
                  [color=blue]
                  > Personally, I would rather pass myvar as well as the attribute names,
                  > and set them with setattr, as I see some others already suggested.[/color]

                  I lose track of things too easily that way. YMMV.

                  Regards,
                  Dan

                  --
                  Dan Sommers
                  <http://www.tombstoneze ro.net/dan/>

                  Comment

                  • Bengt Richter

                    #10
                    Re: Simulating call-by-reference

                    On Thu, 17 Nov 2005 10:03:50 GMT, Rikard Bosnjakovic <bos@REMOVETHIS hack.org> wrote:
                    [color=blue]
                    >I'm tidying up some code. Basically, the code runs a bunch of
                    >regexp-searches (> 10) on a text and stores the match in a different variable.
                    >
                    >Like this:
                    >
                    > re1 = r' ..(.*).. '
                    > re2 = r' .... '
                    > re3 = r' .(.*).. '
                    > ...
                    > m = re.search(re1, data)
                    > if m:
                    > myclass.bar = m.group(1)
                    >
                    > m = re.search(re2, data)
                    > if m:
                    > myclass.foo = m.group(1)
                    >
                    > m = re.search(re3, data)
                    > if m:
                    > myclass.baz = m.group(1)
                    >
                    >
                    >While this code works, it's not very good looking.
                    >
                    >What I want is to rewrite it to something like this:
                    >
                    > l = [ (re1, myclass.bar),
                    > (re2, myclass.foo),
                    > (re3, myclass.baz),
                    > ]
                    >
                    > for (x,y) in l:
                    > m = re.search(x, y)
                    > if m:
                    > y = m.group(1)
                    >
                    >But since Python doesn't work that way, that idea is doomed. What I'm
                    >looking for are other (better) ways or pointers to accomplish this task of
                    >cleanup.
                    >[/color]
                    You could tag your regexs with the foo bar baz names, and pre-compile them.
                    Then you could do something like
                    [color=blue][color=green][color=darkred]
                    >>> import re
                    >>> re1 = re.compile(r'(? P<bar>\d+)') # find an int
                    >>> re2 = re.compile(r'(? P<foo>[A-Z]+)') # find a cap seq
                    >>> re3 = re.compile(r'(? P<baz>[a-z]+)') # find a lower case seq
                    >>>
                    >>> data = 'abc12 34CAPS lowercase'
                    >>>
                    >>> class myclass(object) : pass # ??[/color][/color][/color]
                    ...[color=blue][color=green][color=darkred]
                    >>> class myotherclass(ob ject): pass # ???[/color][/color][/color]
                    ...[color=blue][color=green][color=darkred]
                    >>> L = [ (re1, myclass),[/color][/color][/color]
                    ... (re2, myclass),
                    ... (re3, myotherclass),
                    ... ][color=blue][color=green][color=darkred]
                    >>> for (rx, cls) in L:[/color][/color][/color]
                    ... m = rx.search(data)
                    ... if m:
                    ... setattr(cls, *m.groupdict(). items()[0])
                    ...[color=blue][color=green][color=darkred]
                    >>> myclass.bar[/color][/color][/color]
                    '12'[color=blue][color=green][color=darkred]
                    >>> myclass.foo[/color][/color][/color]
                    'CAPS'[color=blue][color=green][color=darkred]
                    >>> myotherclass.ba z[/color][/color][/color]
                    'abc'

                    Of course, this is only finding a single group, so this specific code
                    might not work for other searches you might like to do. Also, if you don't
                    need an alternate myotherclass, DRY says don't repeat it in L. I.e., you
                    could write (spelling myclass more conventionally)
                    [color=blue][color=green][color=darkred]
                    >>> class MyClass(object) : pass # ??[/color][/color][/color]
                    ...[color=blue][color=green][color=darkred]
                    >>> L = (re1, re2, re3)
                    >>> for (rx) in L:[/color][/color][/color]
                    ... m = rx.search(data)
                    ... if m: setattr(MyClass , *m.groupdict(). items()[0])
                    ...[color=blue][color=green][color=darkred]
                    >>> for k,v in MyClass.__dict_ _.items(): print '%15s: %r'%(k,v)[/color][/color][/color]
                    ...
                    __module__: '__main__'
                    bar: '12'
                    baz: 'abc'
                    __dict__: <attribute '__dict__' of 'MyClass' objects>
                    foo: 'CAPS'
                    __weakref__: <attribute '__weakref__' of 'MyClass' objects>
                    __doc__: None[color=blue][color=green][color=darkred]
                    >>> for it in (it for it in MyClass.__dict_ _.items() if not it[0].startswith('_' )): print '%15s: %r'%it[/color][/color][/color]
                    ...
                    bar: '12'
                    baz: 'abc'
                    foo: 'CAPS'

                    The
                    setattr(MyClass , *m.groupdict(). items()[0])

                    just makes an assignment of whatever comes out to be the first of name-tagged
                    matches (of which there has to at least one here also). If you want several name-tagged
                    matches in a single regex, you could do that and do a setattr for each item in m.groubdict().i tems().

                    What else you can do is only limited by your imagination ;-)

                    Regards,
                    Bengt Richter

                    Comment

                    • Bengt Richter

                      #11
                      Re: Simulating call-by-reference

                      On Thu, 17 Nov 2005 10:03:50 GMT, Rikard Bosnjakovic <bos@REMOVETHIS hack.org> wrote:
                      [color=blue]
                      >I'm tidying up some code. Basically, the code runs a bunch of
                      >regexp-searches (> 10) on a text and stores the match in a different variable.
                      >
                      >Like this:
                      >
                      > re1 = r' ..(.*).. '
                      > re2 = r' .... '
                      > re3 = r' .(.*).. '
                      > ...
                      > m = re.search(re1, data)
                      > if m:
                      > myclass.bar = m.group(1)
                      >
                      > m = re.search(re2, data)
                      > if m:
                      > myclass.foo = m.group(1)
                      >
                      > m = re.search(re3, data)
                      > if m:
                      > myclass.baz = m.group(1)
                      >
                      >
                      >While this code works, it's not very good looking.
                      >
                      >What I want is to rewrite it to something like this:
                      >
                      > l = [ (re1, myclass.bar),
                      > (re2, myclass.foo),
                      > (re3, myclass.baz),
                      > ]
                      >
                      > for (x,y) in l:
                      > m = re.search(x, y)
                      > if m:
                      > y = m.group(1)
                      >
                      >But since Python doesn't work that way, that idea is doomed. What I'm
                      >looking for are other (better) ways or pointers to accomplish this task of
                      >cleanup.
                      >[/color]
                      You could tag your regexs with the foo bar baz names, and pre-compile them.
                      Then you could do something like
                      [color=blue][color=green][color=darkred]
                      >>> import re
                      >>> re1 = re.compile(r'(? P<bar>\d+)') # find an int
                      >>> re2 = re.compile(r'(? P<foo>[A-Z]+)') # find a cap seq
                      >>> re3 = re.compile(r'(? P<baz>[a-z]+)') # find a lower case seq
                      >>>
                      >>> data = 'abc12 34CAPS lowercase'
                      >>>
                      >>> class myclass(object) : pass # ??[/color][/color][/color]
                      ...[color=blue][color=green][color=darkred]
                      >>> class myotherclass(ob ject): pass # ???[/color][/color][/color]
                      ...[color=blue][color=green][color=darkred]
                      >>> L = [ (re1, myclass),[/color][/color][/color]
                      ... (re2, myclass),
                      ... (re3, myotherclass),
                      ... ][color=blue][color=green][color=darkred]
                      >>> for (rx, cls) in L:[/color][/color][/color]
                      ... m = rx.search(data)
                      ... if m:
                      ... setattr(cls, *m.groupdict(). items()[0])
                      ...[color=blue][color=green][color=darkred]
                      >>> myclass.bar[/color][/color][/color]
                      '12'[color=blue][color=green][color=darkred]
                      >>> myclass.foo[/color][/color][/color]
                      'CAPS'[color=blue][color=green][color=darkred]
                      >>> myotherclass.ba z[/color][/color][/color]
                      'abc'

                      Of course, this is only finding a single group, so this specific code
                      might not work for other searches you might like to do. Also, if you don't
                      need an alternate myotherclass, DRY says don't repeat it in L. I.e., you
                      could write (spelling myclass more conventionally)
                      [color=blue][color=green][color=darkred]
                      >>> class MyClass(object) : pass # ??[/color][/color][/color]
                      ...[color=blue][color=green][color=darkred]
                      >>> L = (re1, re2, re3)
                      >>> for (rx) in L:[/color][/color][/color]
                      ... m = rx.search(data)
                      ... if m: setattr(MyClass , *m.groupdict(). items()[0])
                      ...[color=blue][color=green][color=darkred]
                      >>> for k,v in MyClass.__dict_ _.items(): print '%15s: %r'%(k,v)[/color][/color][/color]
                      ...
                      __module__: '__main__'
                      bar: '12'
                      baz: 'abc'
                      __dict__: <attribute '__dict__' of 'MyClass' objects>
                      foo: 'CAPS'
                      __weakref__: <attribute '__weakref__' of 'MyClass' objects>
                      __doc__: None[color=blue][color=green][color=darkred]
                      >>> for it in (it for it in MyClass.__dict_ _.items() if not it[0].startswith('_' )): print '%15s: %r'%it[/color][/color][/color]
                      ...
                      bar: '12'
                      baz: 'abc'
                      foo: 'CAPS'

                      The
                      setattr(MyClass , *m.groupdict(). items()[0])

                      just makes an assignment of whatever comes out to be the first of name-tagged
                      matches (of which there has to at least one here also). If you want several name-tagged
                      matches in a single regex, you could do that and do a setattr for each item in m.groubdict().i tems().

                      What else you can do is only limited by your imagination ;-)

                      Regards,
                      Bengt Richter

                      Comment

                      Working...