Simulating call-by-reference

R

Rikard Bosnjakovic

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.
 
B

bonono

Rikard said:
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.
-----------------

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

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

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

Dan Sommers

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.

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(regexp, 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
 
A

Alex Martelli

Dan Sommers said:
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(regexp, 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.

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
 
D

Dan Sommers

On Thu, 17 Nov 2005 12:31:08 -0800,

[ example code snipped ]
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.
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).

Oops. <sheepish grin>

You're right.

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

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

Regards,
Dan
 
B

Bengt Richter

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.
You could tag your regexs with the foo bar baz names, and pre-compile them.
Then you could do something like
>>> 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 # ?? ...
>>> class myotherclass(object): pass # ??? ...
>>> L = [ (re1, myclass),
... (re2, myclass),
... (re3, myotherclass),
... ] ... m = rx.search(data)
... if m:
... setattr(cls, *m.groupdict().items()[0])
... '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)
... m = rx.search(data)
... if m: setattr(MyClass, *m.groupdict().items()[0])
... ...
__module__: '__main__'
bar: '12'
baz: 'abc'
__dict__: <attribute '__dict__' of 'MyClass' objects>
foo: 'CAPS'
__weakref__: said:
>>> for it in (it for it in MyClass.__dict__.items() if not it[0].startswith('_')): print '%15s: %r'%it
...
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().items().

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

Regards,
Bengt Richter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top