On Tue, 20 Dec 2005 16:10:30 +0200, [EMAIL PROTECTED] (David MacKay) wrote:
>Dear Greater Py, > ><motivation note="reading this bit is optional"> > I am writing a command-line reader for python. > > I'm trying to write something with the same brevity >as perl's one-liner > >eval "\$$1=\$2" while @ARGV && $ARGV[0]=~ /^(\w+)=(.*)/ && shift; > >and with similar functionality. I've decided I don't like >getopt, because it seems to require me to write pages and pages >of elif's as I add new arguments. It slows me down, whereas the >perlism above liberates. > >My solution is a twenty-line python chunk equivalent to the perl one-liner. >(Twenty lines because, to process a (name, value) pair, I have to find the >current type of the variable "name" before setting "name" to >righttype("value"). > >I'm happy with this 20-line chunk and wish to re-use it in many python >programs. ></motivation> > ><question> > What is the pythonic way to embed a 20-line chunk of code into a function? >I'd love to define these 20 lines as a module, and reuse the module over and >over. >but this chunk of code needs to have access to >the local variables of main, whatever they are called. > > In tcl, IIRC, the command "upvar" allows one function to get access to its >parent function's local variables. > > Is there a pythonic way to tell a function "you are allowed to see all your >parent's variables?" Or, to tell a chunk of code, "you are just a chunk of >code, not really a function"? ></question> > You can see them, but you can't rebind them without nasty hacks. I would suggest just instantiating an object that initializes the way you want to contain the values you pre-specify, and optionally get overridden by command line info as you specify. E.g., a quick hack (not tested beyond what you see ;-) ----< clvalues.py >----------------------------------------------------- class CLValues(dict): """ A dict whose initialization values are overridden by -name value pairs in the overrides list, by default taken from command line args sys.argv[1:], but a list may be passed. Existing values get overridden by cmd line values converted to the same type. New values are assumed str type. Existing values may be specified non-overridable by prefixing an underscore, which is removed after cmd line args have been processed. Since keys are valid names, access is also provided via attribute syntax. """ def __init__(self, overrides=None, *args, **kw): dict.__init__(self, *args, **kw) if overrides is None: overrides = __import__('sys').argv[1:] while overrides: name = overrides.pop(0) if not name.startswith('-') or not name[1:]: raise ValueError, "Names must be non-null and prefixed with '-', unlike %r" % name name = name[1:] if '_'+name in self or name.startswith('_') and name in self: raise ValueError, "%r may not be overridden" % name if not overrides: raise ValueError, 'No value following %r'% '-'+name value = overrides.pop(0) self[name] = type(self.get(name, ''))(value) # default str type if not pre-existing for k,v in self.items(): if k.startswith('_'): # make plain names for non-overridables self[k[1:]] = v del self[k] def __getattr__(self, name): return self[name] # provide key access as attributes def test(): clv = CLValues( decode=0, verbose=0, bits=7, N = 10000, file="blah", _securityLevel = 3) for name, value in clv.items(): print '%15s: %r' %(name, value) print 'N accessed as clv.N => %r' % clv.N if __name__ == '__main__': test() ------------------------------------------------------------------------ Running it to run the test: [ 9:54] C:\pywk\ut>py24 clvalues.py -bits 8 -file other\path\and\file decode: 0 securityLevel: 3 verbose: 0 file: 'other\\path\\and\\file' bits: 8 N: 10000 N accessed as clv.N => 10000 [ 9:54] C:\pywk\ut>py24 clvalues.py -securityLevel 0 Traceback (most recent call last): File "clvalues.py", line 44, in ? test() File "clvalues.py", line 38, in test _securityLevel = 3) File "clvalues.py", line 21, in __init__ raise ValueError, "%r may not be overridden" % name ValueError: 'securityLevel' may not be overridden Quoting command line arg to make a single arg with embedded spaces: [ 9:54] C:\pywk\ut>py24 clvalues.py -added "should be string" decode: 0 securityLevel: 3 added: 'should be string' verbose: 0 file: 'blah' bits: 7 N: 10000 N accessed as clv.N => 10000 >Thanks very much > De nada. >David > >PS -- example below illustrates the chunk of code, in case anyone is >interested. > <snip code, from which I tried to translate the functionality> Usage in a program would go something like from clvalues import CLValues clv = CLValues( # ... like test above ) # ... # use values spelled clv.name or clv['name'] or clv.get('name') etc # Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list