Is the behavior expected?

Alphones Xiaobin.Huang at gmail.com
Wed Nov 26 23:16:29 EST 2008


On 11月27日, 上午12时07分, Peter Otten <__pete... at web.de> wrote:
> Alphones wrote:
> > On 11月26日, 下午9时28分, bearophileH... at lycos.com wrote:
> >> Alphones:
>
> >> > it is a little deferent from other script language.
>
> >> See also here:http://en.wikipedia.org/wiki/Dynamic_scope#Dynamic_scoping
>
> >> Python doesn't have such automatic closures, probably for performance
> >> reasons and/or maybe to keep its C implementation simpler (maybe other
> >> people here can give you an explanation of this, I too am curious).
>
> >> Bye,
> >> bearophile
>
> > i encountered this problem when i'm writing a program for packaging
> > files.
> > the program generates tasks according to description file.
> > and tasks are deferent from each other, and should be excuted at the
> > last of program.
>
> > i have experience on Lua and have learned about scheme and haskell, so
> > i wrote the wrong code in python.
>
> > now my solution is, using class taskCreator to create tasks and put
> > them into tasklist.
> > class taskCreator:
> >     def __init__(self, proc, input, output):
> >         self.proc = proc
> >         self.input = input
> >         self.output = output
> >     def call(self):
> >         return self.proc.call(self.input, self.output)
> > 'proc' is generated by procCreators, it's specified.
>
> > it looks more complex than lambda one.
>
> > is there any other simple way to implement it?
>
> Yes, you can have closures in Python (you already had one, the getFunc()
> function in your initial post).
>
> Random remarks:
>
> You don't need an explicit call() method, you can make instances callable:>>> class A:
>
> ...     def __init__(self, name):
> ...             self.name = name
> ...     def __call__(self):
> ...             print "calling", self.name
> ...>>> a = A("foo")
> >>> a()
>
> calling foo
>
> If your object has just this one method you can instead use a closure:
>
> >>> def make_a(name):
>
> ...     def call():
> ...             print "calling", name
> ...     return call
> ...>>> a = make_a("bar")
> >>> a()
>
> calling bar
>
> This can be simplified further with some help from the library:
>
> >>> from functools import partial
> >>> def call(name):
>
> ...     print "calling", name
> ...>>> a = partial(call, "baz")
> >>> a()
>
> calling baz
>
> Here is a complete example:
>
> import sys
> from functools import partial
>
> def lower(input, output):
>     output.writelines(line.lower() for line  in input)
>
> def prefix(input, output):
>     for index_line in enumerate(input):
>         output.write("%d: %s" % index_line)
>
> tasks = [partial(lower, open("tmp.py"), sys.stdout),
>          partial(prefix, open("tmp.py"), sys.stdout)]
>
> for t in tasks:
>     t()
>
> Peter

functools.partial is useful to my program.
i wrote
            task = partial(lambda input, output, proc: proc(input,
output), archive_input.name, archive_output, proc)
            self.todo.append(task)
instead of those TaskCreators.

and wrote
    def __getExportor(self, name):
        if not self.exportors.has_key(name):
            return lambda input, ouput: False
        return partial(lambda input, output, cmdline: filter( # filter
successed exit code to make list not empty, and it means success
                lambda x: x == 0 or x == 36, # hack, 36 is the success
code for kzip, i hope there isn't any program use 36 as it's failed
exit code.
                map(lambda l: os.system(l), self.interpret(cmdline,
input, output))), cmdline=self.exportors[name])
instead of ProcCreators.

I know it looks more obscure and not in the 'Python Style', it's just
for me to understand these discussions :P





More information about the Python-list mailing list