Feature request: subclassing FunctionType [Was: Some language proposals]

Jacek Generowicz jacek.generowicz at cern.ch
Fri Feb 27 10:01:22 EST 2004


michele.simionato at poste.it (Michele Simionato) writes:

> def make_adders(n):
>     return [(lambda x: x+i) for i in range(n)]
> 
> add0,add1=make_adders(2)
> 
> print add0(0) #=> 1
> print add1(0) #=> 1
> 
> This does not work as expected,

Hmm, I think that what is expected is not an invariant between
different people and even between more careful or less careful
readings by the same person.

On careful reading, it does exatly what I expect it to do.

All the closures in the list share the same free-variable binding[*];
there is only one binding of i, so they all find that single binding.

I don't think that Python's behaviour differs from other languages, in
this respect. For example in Common Lisp:

* (defun make-adders (n)
    (loop for i below n collect
  	  (lambda (x) (+ x i))))
MAKE-ADDERS
* (destructuring-bind (add0 add1) (make-adders 2)
    (list (funcall add0 0) 
  	  (funcall add1 0)))
(2 2)

[The important point is that the two resulting numbers are the same,
the fact that they are both twos rather than ones is a feature of the
looping construct and is irrelevant to the scoping issues.]

> and the solution is an ugly hack
> with default arguments:
> 
> def make_adders(n):
>     return [(lambda x,i=i: x+i) for i in range(n)]
> 
> add0,add1=make_adders(2)
> 
> print add0(0) #=> 0
> print add1(0) #=> 1

Yes, if you want the free variables to be bound differently, then
you need to bind i in a seperate "more inner" scope for each closure:

(defun make-adders (n)
  (loop for i below n collect
	(let ((i i))
	  (lambda (x) (+ x i)))))
MAKE-ADDERS
* 
(destructuring-bind (add0 add1) (make-adders 2)
  (list (funcall add0 0) 
	(funcall add1 0)))
(0 1)

> I don't like that, but I don't think that the current scope rules
> will change any soon.

I'm not sure how you would like them to change.

> OTOH, Paul Prescod is right and Python is primarily an 
> OOP language, so I would prefer to use real objects over
> closures.

Bah! Humbug! It's multi-paradigm, I tell you :-)

> So, I submit it as a feature request for Python 2.4.  Maybe, if
> enough people wants the feature, we may get it!

In complete ignorance of the technical difficulties and second order
consequences of allowing this, is second your request.


[*] I have a feeling that "free variable binding" is not a correct way
    of expressing this, but I can't think of anything better just now.



More information about the Python-list mailing list