Closures / Blocks in Python

5 views
Skip to first unread message

treble54

unread,
Jul 24, 2007, 10:58:32 AM7/24/07
to
Does anyone know a way to use closures or blocks in python like those
used in Ruby? Particularly those used in the { } braces.

Carsten Haese

unread,
Jul 24, 2007, 11:12:36 AM7/24/07
to pytho...@python.org
On Tue, 2007-07-24 at 14:58 +0000, treble54 wrote:
> Does anyone know a way to use closures or blocks in python like those
> used in Ruby? Particularly those used in the { } braces.

Please describe the problem you're trying to solve. Even if Python had a
direct equivalent of "Ruby closures or blocks", which I don't think it
does, it may not be the best solution to your problem.

--
Carsten Haese
http://informixdb.sourceforge.net


Neil Cerutti

unread,
Jul 24, 2007, 11:30:12 AM7/24/07
to
On 2007-07-24, treble54 <treb...@gmail.com> wrote:
> Does anyone know a way to use closures or blocks in python like
> those used in Ruby? Particularly those used in the { } braces.

Python's nameless functions are week. So it supports iterators
and generators using protocols, comprehensions and a few simple
statements, rather than promoting the use of nameless functions.

Ruby's

some_list.each do |item|
puts item
end

if I understood it correctly, In Python would be:

for item in some_list:
print item

That works for any object that supports the iterator protocol.

--
Neil Cerutti

Jason

unread,
Jul 24, 2007, 11:32:26 AM7/24/07
to
On Jul 24, 8:58 am, treble54 <trebl...@gmail.com> wrote:
> Does anyone know a way to use closures or blocks in python like those
> used in Ruby? Particularly those used in the { } braces.

Python isn't Ruby. Python has a lambda function for creating
anonymous functions, but many of the common use cases expired with the
introduction of iterators and comprehensions. Python's functions are
first class objects, and can be passed around, bound to names, and
used like any other object. (I don't know whether Ruby's functions
are first class objects.) Python's function objects are callable, but
so are classes (calling them creates a class instance) and some
instances (those that define the __call__ special method).

If you can't find a way of doing what you want with iterators,
comprehensions, or lambda, consider writing a little function. Heck,
you can even nest functions in Python or pass a function as a
parameter.

For example, removing all names that start with a 'J' from a list of
names:
newListOfNames = [ name for name in nameList if not
name.startswith('J') ] # List comprehension
newListOfNames = filter(lambda name: not name.startswith('J'),
nameList) # Filter with lambda

# Explicit for-loop
newListOfNames = []
for name in nameList:
if not name.startswith('J'): newListOfNames.append(name)


Take a look at "http://ivan.truemesh.com/archives/000392.html" for a
comparison between some simple Ruby code and Python. Hope this helps.

--Jason

Bruno Desthuilliers

unread,
Jul 24, 2007, 11:44:30 AM7/24/07
to
treble54 a écrit :

> Does anyone know a way to use closures or blocks in python like those
> used in Ruby? Particularly those used in the { } braces.
>
Instead of looking for what you think is the solution, you'd be better
explaining your concrete problem.

Cameron Laird

unread,
Jul 25, 2007, 9:30:47 AM7/25/07
to
In article <1185291146.7...@n60g2000hse.googlegroups.com>,
Jason <tenax....@gmail.com> wrote:
.
[good detail]
.

.
>If you can't find a way of doing what you want with iterators,
>comprehensions, or lambda, consider writing a little function. Heck,
.
.
.
"[C]onsider writing a little function", indeed; that's
a crucial summary. From a Ruby or Lisp perspective,
this proliferation of named functions is clumsy and
unsightly; Pythoneers see small def-s as opportunities
to clarify. I've come to suspect both sides are right.
The marvelous thing is that, taken as a whole, each of
Python, Ruby, ... *works*, and admits a strong, effec-
tive style. Moreover, they share enough conceptually
that it's not hard for speakers of one to understand
the others. As has already been proposed in this
thread, though, good Ruby and good Python will always
look different.

Jeff

unread,
Jul 25, 2007, 10:45:00 AM7/25/07
to
You can create a lexical closure using a Python generator function,
which allows iteration using a block of code while maintaining
internal state. A generator is a regular function which uses yield
(like Ruby) to define the point at which the function should return an
expression to the calling code. For example:

# Generic counter
def counter(min=None, max):
if not min:
min = 0
for i in xrange(min, max):
yield i
i = i + 1

When called, this function will yield the value of i and remember its
state. The next time it's called, it will increment i, then continue
on another iteration of the loop, yielding the new value of i.

For example:

my_counter = counter(0, 10)
my_counter() # <-- 0
my_counter() # <-- 1
for i in my_counter():
print i
# Prints 2-10 (the remaining numbers in xrange(min, max))

Wildemar Wildenburger

unread,
Jul 25, 2007, 12:21:32 PM7/25/07
to pytho...@python.org
Jeff wrote:
> # Generic counter
> def counter(min=None, max):
> if not min:
> min = 0
> for i in xrange(min, max):
> yield i
> i = i + 1
>
Just for the record:
>>> # Generic counter
... def counter(min=None, max):
... if not min:
... min = 0
... for i in xrange(min, max):
... yield i
... i = i + 1
...
File "<stdin>", line 2
SyntaxError: non-default argument follows default argument


You'd have to add a little more parameter-checking for this to work like
you intend.
/W

Jeff

unread,
Jul 25, 2007, 12:35:17 PM7/25/07
to
True, and I should have known better than to not have thoroughly
tested code I post to Usenet :). That being said, it was intended as
a fast example of how a generator operates for someone coming from
Ruby.

Klaas

unread,
Jul 25, 2007, 1:48:52 PM7/25/07
to
On Jul 24, 7:58 am, treble54 <trebl...@gmail.com> wrote:
> Does anyone know a way to use closures or blocks in python like those
> used in Ruby? Particularly those used in the { } braces.

Inner functions allow you to define closures and (named) blocks
anywhere). Anonymous blocks must consist of a single expression.

-Mike

Gabriel Genellina

unread,
Jul 25, 2007, 8:04:04 PM7/25/07
to pytho...@python.org

Uhmm, I think this won't win the Best Python Code Of The Week Award :)
Apart from the already noted syntax error in the function definition, the
`i = i + 1` is useless because `i` gets reassigned right on the next loop.
And you don't "call" a generator, you have to iterate over it;
my_counter() will raise an error. This would be the right way:

my_counter = counter(0, 10)
my_counter.next() <-- 0
my_counter.next() <-- 1
for value in my_counter:
print value <-- 2 to 9

--
Gabriel Genellina

Reply all
Reply to author
Forward
0 new messages