That horrible regexp idiom
Duncan Booth
duncan.booth at invalid.invalid
Thu Feb 10 09:20:57 EST 2005
Nick Coghlan wrote:
> I knew if/elif was a much better argument in favour of embedded
> assignment than while loops are.
>
I know I'm going to regret posting this, but here is an alternative, very
hackish way to do all those things people keep asking for, like setting
variables in outer scopes or doing lots of nested ifs for regex matching or
simulating passing a local variable by reference.
My excuse for the following code is that was unwell and I think I was
slightly feverish when I wrote it:
----- hack.py -----------
import new
def mksetter(baa):
'''Cruel hack to set scoped variables.
baa should be a lambda which accesses the variable you wish to set.
It must be a local or outer scope variable, not a global
'''
closure = baa.func_closure
name = baa.func_code.co_names[0]
if not isinstance(closure, tuple) or len(closure) != 1:
raise TypeError('''mksetter() argument must be a lambda accessing a
local or scoped variable''')
def f(v):
a = v
return v
lambda: a
c = f.func_code
newcode = new.code(
c.co_argcount, 1, c.co_stacksize, c.co_flags, c.co_code,
c.co_consts, c.co_names, c.co_varnames, c.co_filename, 'set_'+name,
c.co_firstlineno, c.co_lnotab, (name,), (),
)
return new.function(newcode, f.func_globals,
'set_'+name, None, closure)
if __name__=='__main__':
def set_a_local():
a = 42
print "a=",a
set_a = mksetter(lambda: a)
set_a(24)
print set_a
print "a=",a
set_a_local()
def set_scoped():
count = 0
set_count = mksetter(lambda: count)
def inc():
set_count(count+1)
for i in range(10):
print "count=",count
inc()
print "Final value",count
set_scoped()
import re
def silly_regex():
name = re.compile('[a-zA-Z_][a-zA-Z0-9_]*')
number = re.compile('[0-9]+(\\.[0-9]*)?([eE][-+]?[0-9]+)?')
m = None
set_m = mksetter(lambda: m)
for s in 'abc', '2.5e-3', '!':
if set_m(name.match(s)):
print "name", m.group(0)
elif set_m(number.match(s)):
print "number", m.group(0)
else:
print "no match", m, s
silly_regex()
----- end of hack.py ----
Sorry.
If anyone actually feels tempted to use this: I take no responsibility for
the results. I can't particularly see why future versions of Python would
change to stop it working, but they could, and of course it is definitely a
'C-Python only' trick.
More information about the Python-list
mailing list