473,287 Members | 1,413 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,287 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 1589
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,...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...

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.