Is the behavior expected?

Peter Otten __peter__ at web.de
Wed Nov 26 17:07:27 CET 2008


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



More information about the Python-list mailing list