Update locals()

holger krekel pyth at devel.trillke.net
Sun Apr 28 10:24:17 EDT 2002


On Sun, Apr 28, 2002 at 08:50:13AM -0500, jepler at unpythonic.net wrote:
> > class filename:
> >     """ Abstraction for filename ... """
> >     # ...
> > 
> >     for name in filters._stateful_all:
> >         doc=filters.__dict__.get(name,undoc).__doc__.strip()+'\n'
> >         exec indentedcode("""
> > 
> >     def %(name)s (self,*args,**kargs):
> >         '''%(doc)s'''
> >         return filters.%(name)s (*args,**kargs) (self)
> >     """ % locals()) 
> > 
> >     # ...
> 
> I don't quite see what you're doing here, but you might try something like
> (given nested scopes) (untested):

i dynamically define functions as filename-methods. Assume
name is 'access' you get

    def access(self,*args,**kargs):
        ''' checks filename for a given access-mode... '''
        return filters.access (*args,**kargs) (self)

defined right in your class scope. After you imported 
the module the methods will be there...
 
>     class filename:
> 	def __getattr__(self, attr):
> 	    if not hasattr(filters, attr): raise AttributeError, attr
> 	    filter_func = getattr(filters, attr)
> 	    ret = lambda *args, **kargs: filter_func(*args, **kargs)(self)
> 	    ret.__doc__ = getattr(filter_func, __doc__, undoc)
> 	    #setattr(self, attr, ret)
> 	    return ret

I am working a lot interactively (like many others with rlcompleter). Dynamic 
constructions like this won't show up. So the ret.__doc__ does not make much sense
here IMHO. help ('filename') won't show it either.  Otherwise your version 
should work. I don't know if you could handle working with
inspect.getargspec to construct the precise signature, though. This can
be done with the above 'templating' (i didn't bother so far).

> My version will also work properly if "filters" is extended at runtime with
> new attributes... It's reasonbly efficient to construct a function at
> runtime with 'lambda', and you can trade time for space by caching the
> attribute on the instance once it's been computed once

My construction was not about extending filters at run time but about
avoiding redundancies and expressing an adapter pattern at compile
time.

> Of course, given that you always immediately call the instance of the
> filters. function, I don't see why you can't simply write

quoting from the example at the end of my posting:

#...
resultfilters = AND(isfile, nolink, fnmatch('data*'), count)
recursefilter = access('wx')

for dir, fnlist in base.filterwalk( resultfilters, recursefilter ):
#...

Note especially that 

    recursefilter = access('wx')

does not map to

>     class filename:
> 	def access(self, mode='r'):

You would need an unbound partially initialized class-method.
You could try to use Currying (see ASPN-Cookbook) 
but it probably gets difficult if you look at the 'resultfilters'-
line. The AND is a stateful-filter as well and you can because
of the templating also do 

fn.AND(isfile,nolink,...) 

> There's probably some reason which isn't as apparent in this example as
> some of the more complex ones you've written, though...

The problem is i don't want to explain my filename+filters module
in boring details. I tried to extract the basic templating mechanism
and still provide some context to answer Alex Martellis question
about "Give me ONE use..." (for exec without explicit dictionaries).

I am not saying at all that there is no other solution (see your
own solution). Given the context, my 'templating' does still make a lot of sense
to me. Although it might be considered unusual or even unpythonic
but that's a matter of taste to some degree :-)

    holger





More information about the Python-list mailing list