Regular expression question
jepler at unpythonic.net
jepler at unpythonic.net
Sat Nov 23 22:38:31 EST 2002
You're doing a number of "unpythonic" things in this code. It's best to
learn to speak Python like a native, to get beyond building up a "phrasebook"
to translate Perl statements into Python statements.
The biggest "unpythonic" thing is referring to an arbitrary global
variable by its name at runtime. This is very bad, since it lets a
user refer to any function. Besides that, you'll probably encapsulate
the Python version in a module (since it's longer than a line or two),
but the Python "globals()" returns the globals of the current module,
not the calling module.
Anyway, here's an attempt at a Pythonic version of the perl code you
posted. Yes, it's longer than the Perl version. To use it, you'd write
def f(s): return s.upper()
def g(s): return s.title()
function_map = {'f': f, 'g': g}
print substitute_template("The lessons are: '%%f%%' and '%%g%%'",
function_map, "python is not perl")
# Test out error handling
print substitute_template("At the tone, time time is 10PM: %%z%%",
function_map, "")
(The third argument corresponds to $variable in your example)
Here's the code to implement the 'substitute_template' function:
import re
# Since python wouldn't just refer to a global 'variable', a Subfunc
# class records the desired argument and the function map for later use.
# You can call a Subfunc instance just like it was a plain function
class Subfunc:
def __init__(self, function_map, arg):
self.function_map = function_map
self.arg = arg
def __call__(self, s):
fname = s.group(1).lower()
# Error handling should probably be more sophisticated.
# But hell, it's better than terminating the whole program...
try:
f = function_map[s]
except KeyError:
return "*** ERROR: bad substitution %r ***" % fname
return f(self.arg)
# Compile the regular expression, since we expect to be matching it frequently
subre = re.compile("%%(.?)%%")
# Here's the function you call. It creates a Subfunc instance and passes
# it on to re.sub
def substitute_template(template, function_map, arg):
return subre.sub(Subfunc(function_map, arg), template)
Enhancing the code to let $variable be an arbitrary parameter list
is fairly easy. You'll need to learn about *args (and maybe **kw)
parameters, and either the f(*args, *kw) calling convention or the
apply function.
Jeff
More information about the Python-list
mailing list