473,395 Members | 1,502 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

accumulator generators

I was reading this <a href="this http://www.paulgraham.com/icad.html">Paul
Graham article</aand he builds an accumuator generator function in
the appendix. His looks like this:

<pre>
def foo(n):
s = [n]
def bar(i):
s[0] += i
return s[0]
return bar
</pre>

Why does that work, but not this:

<pre>
def foo(n):
s = n
def bar(i):
s += i
return s
return bar
</pre>
Jun 27 '08 #1
7 1593
Cameron schrieb:
I was reading this <a href="this http://www.paulgraham.com/icad.html">Paul
Graham article</aand he builds an accumuator generator function in
the appendix. His looks like this:

<pre>
def foo(n):
s = [n]
def bar(i):
s[0] += i
return s[0]
return bar
</pre>

Why does that work, but not this:

<pre>
def foo(n):
s = n
def bar(i):
s += i
return s
return bar
</pre>
Because python's static analysis infers s as being a variable local to
bar in the second case - so you can't modify it in the outer scope.

In the future, you may declare

def bar(i):
nonlocal s
...
Diez
Jun 27 '08 #2
At 2008-05-30T19:50:43Z, Cameron <ca**********@gmail.comwrites:
Why does that work, but not this:

def foo(n):
s = n
def bar(i):
s += i
return s
return bar
Assume that n is an int, making s one also. Ints are immutable; you can
only copy them. So your bar is taking s, adding i to it, then assigning the
value back to the local variable named s.
--
Kirk Strauser
The Day Companies
Jun 27 '08 #3
On May 30, 1:04*pm, "Diez B. Roggisch" <de...@nospam.web.dewrote:
Cameron schrieb:
I was reading this <a href="thishttp://www.paulgraham.com/icad.html">Paul
Graham article</aand he builds an accumuator generator function in
the appendix. His looks like this:
<pre>
def foo(n):
* s = [n]
* def bar(i):
* * s[0] += i
* * return s[0]
* return bar
</pre>
Why does that work, but not this:
<pre>
def foo(n):
* s = n
* def bar(i):
* * s += i
* * return s
* return bar
</pre>

Because python's static analysis infers s as being a variable local to
bar in the second case - so you can't modify it in the outer scope.

In the future, you may declare

def bar(i):
* * *nonlocal s
* * *...

Diez
thanks for the response. Just to make sure I understand- Is the reason
it works in the first case because s[0] is undefined at that point (in
bar), and so python looks in the outer scope and finds it there?

Cameron

Jun 27 '08 #4
Cameron wrote:
On May 30, 1:04 pm, "Diez B. Roggisch" <de...@nospam.web.dewrote:
>Cameron schrieb:
>>I was reading this <a href="thishttp://www.paulgraham.com/icad.html">Paul
Graham article</aand he builds an accumuator generator function in
the appendix. His looks like this:
<pre>
def foo(n):
s = [n]
def bar(i):
s[0] += i
return s[0]
return bar
</pre>
Why does that work, but not this:
<pre>
def foo(n):
s = n
def bar(i):
s += i
return s
return bar
</pre>
Because python's static analysis infers s as being a variable local to
bar in the second case - so you can't modify it in the outer scope.

In the future, you may declare

def bar(i):
nonlocal s
...

Diez

thanks for the response. Just to make sure I understand- Is the reason
it works in the first case because s[0] is undefined at that point (in
bar), and so python looks in the outer scope and finds it there?
You can refer to variables in enclosing scopes, just not redefine them in that
same scope. That's why in the first example, bar can refer to to s (defined in
foo). By assigning to s[0], it modifies the list, which is OK; trying to
redefine the name 's' (like the second example tries to do) would not be OK.

Also see: http://zephyrfalcon.org/labs/python_pitfalls.html (pitfall #6).

--
Hans Nowak (zephyrfalcon at gmail dot com)
http://4.flowsnake.org/
Jun 27 '08 #5
Cameron <ca**********@gmail.comwrites:
I was reading this <a href="this http://www.paulgraham.com/icad.html">Paul
Graham article</aand he builds an accumuator generator function in
the appendix. His looks like this:

<pre>
def foo(n):
s = [n]
def bar(i):
s[0] += i
return s[0]
return bar
</pre>

Why does that work, but not this:

<pre>
def foo(n):
s = n
def bar(i):
s += i
return s
return bar
</pre>
Others have explained why, but this looks like "pythonized LISP" to
me. I would rather use a generator function:

def foo(n):
while True:
n += yield n

Although the problem is that you can't send it values the first time
round!
>>bar = foo('s')
bar.next()
's'
>>bar.send('p')
'sp'
>>bar.send('am')
'spam'

But:
>>bar = foo(3)
bar.send(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't send non-None value to a just-started generator
>>>
--
Arnaud
Jun 27 '08 #6
On May 31, 4:19*am, Arnaud Delobelle <arno...@googlemail.comwrote:
Cameron <cameronla...@gmail.comwrites:
I was reading this <a href="thishttp://www.paulgraham.com/icad.html">Paul
Graham article</aand he builds an accumuator generator function in
the appendix. His looks like this:
<pre>
def foo(n):
* s = [n]
* def bar(i):
* * s[0] += i
* * return s[0]
* return bar
</pre>
Why does that work, but not this:
<pre>
def foo(n):
* s = n
* def bar(i):
* * s += i
* * return s
* return bar
</pre>

Others have explained why, but this looks like "pythonized LISP" to
me. *I would rather use a generator function:

def foo(n):
* * while True:
* * * * n += yield n

Although the problem is that you can't send it values the first time
round!
>bar = foo('s')
bar.next()
's'
>bar.send('p')
'sp'
>bar.send('am')

'spam'

But:
>bar = foo(3)
bar.send(2)

Traceback (most recent call last):
* File "<stdin>", line 1, in <module>
TypeError: can't send non-None value to a just-started generator
I find the "pythonized LISP" solution more understandable, even
without the initial next() requirement. YMMV

George
Jun 27 '08 #7
George Sakkis <ge***********@gmail.comwrites:
On May 31, 4:19*am, Arnaud Delobelle <arno...@googlemail.comwrote:
>Cameron <cameronla...@gmail.comwrites:
I was reading this <a href="thishttp://www.paulgraham.com/icad.html">Paul
Graham article</aand he builds an accumuator generator function in
the appendix. His looks like this:
<pre>
def foo(n):
* s = [n]
* def bar(i):
* * s[0] += i
* * return s[0]
* return bar
</pre>
Why does that work, but not this:
<pre>
def foo(n):
* s = n
* def bar(i):
* * s += i
* * return s
* return bar
</pre>

Others have explained why, but this looks like "pythonized LISP" to
me. *I would rather use a generator function:

def foo(n):
* * while True:
* * * * n += yield n

Although the problem is that you can't send it values the first time
round!
>>bar = foo('s')
bar.next()
's'
>>bar.send('p')
'sp'
>>bar.send('am')

'spam'

But:
>>bar = foo(3)
bar.send(2)

Traceback (most recent call last):
* File "<stdin>", line 1, in <module>
TypeError: can't send non-None value to a just-started generator

I find the "pythonized LISP" solution more understandable, even
without the initial next() requirement. YMMV

George
In that case a class may be better? IMHO, what is such a natural
idiom in LISP does not translate well literally into Python.

class Foo(object):
def __init__(self, n):
self.s = n
def __call__(self, i)
self.s += i
return self.s

Anything to avoid the mutable container trick! Of course 'nonlocal'
takes care of this in py3k. I have missed the absence of 'nonlocal' a
lot, but now that it is around the corner, I grow less sure about it.

--
Arnaud
Jun 27 '08 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

23
by: Francis Avila | last post by:
Below is an implementation a 'flattening' recursive generator (take a nested iterator and remove all its nesting). Is this possibly general and useful enough to be included in itertools? (I know...
9
by: Francis Avila | last post by:
A little annoyed one day that I couldn't use the statefulness of generators as "resumable functions", I came across Hettinger's PEP 288 (http://www.python.org/peps/pep-0288.html, still listed as...
8
by: Timothy Fitz | last post by:
It seems to me that in python, generators are not truly coroutines. I do not understand why. What I see is that generators are used almost exclusively for generation of lists just-in-time. Side...
3
by: Carlos Ribeiro | last post by:
As a side track of my latest investigations, I began to rely heavily on generators for some stuff where I would previsouly use a more conventional approach. Whenever I need to process a list, I'm...
5
by: Robert Oschler | last post by:
Preamble: - I know this is the Python forum - I know about (and have used) Jython I already posted this question in comp.lang.java. But after a week I have still not received a single reply....
125
by: Raymond Hettinger | last post by:
I would like to get everyone's thoughts on two new dictionary methods: def count(self, value, qty=1): try: self += qty except KeyError: self = qty def appendlist(self, key, *values): try:
15
by: Jordan Rastrick | last post by:
First, a disclaimer. I am a second year Maths and Computer Science undergraduate, and this is my first time ever on Usenet (I guess I'm part of the http generation). On top of that, I have been...
3
by: Michael Sparks | last post by:
Hi, I'm posting a link to this since I hope it's of interest to people here :) I've written up the talk I gave at ACCU Python UK on the Kamaelia Framework, and it's been published as a BBC...
6
by: Talin | last post by:
I've been using generators to implement backtracking search for a while now. Unfortunately, my code is large and complex enough (doing unification on math expressions) that its hard to post a...
13
by: Martin Sand Christensen | last post by:
Hi! First a bit of context. Yesterday I spent a lot of time debugging the following method in a rather slim database abstraction layer we've developed: ,---- | def selectColumn(self,...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.