473,387 Members | 1,528 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,387 software developers and data experts.

For review: PEP 343: Anonymous Block Redux and Generator Enhancements

After many rounds of discussion on python-dev, I'm inviting public
comments for PEP 343. Rather than posting the entire PEP text here,
I'm inviting everyone to read it on line
(http://www.python.org/peps/pep-0343.html) and then post comments on a
Wiki page I've created for this purpose
(http://wiki.python.org/moin/WithStatement).

I think this is a good one; I hope people agree. Its acceptance will
obsolete about 4 other PEPs! (A sign that it fulfills a need and that
the proposed solution is powerful.)

--
--Guido van Rossum (home page: http://www.python.org/~guido/)
Jul 19 '05 #1
13 1487
Guido van Rossum wrote:
After many rounds of discussion on python-dev, I'm inviting public
comments for PEP 343. Rather than posting the entire PEP text here,
I'm inviting everyone to read it on line
(http://www.python.org/peps/pep-0343.html) and then post comments on a
Wiki page I've created for this purpose
(http://wiki.python.org/moin/WithStatement).

I think this is a good one; I hope people agree. Its acceptance will
obsolete about 4 other PEPs! (A sign that it fulfills a need and that
the proposed solution is powerful.)


I like the PEP very much; I guess most C++ programmers are missing that
capability in Python. (I was following the discussion on python-dev,
and I'm pleased and surprised how good the result/compromise is).

What about making the ':' optional (and end implicitly at end of current
block) to avoid over-indentation?

def foo():
with locking(someMutex)
with opening(readFilename) as input
with opening(writeFilename) as output
...

would be equivalent to:

def foo():
with locking(someMutex)
with opening(readFilename) as input
with opening(writeFilename) as output
...

Regards,

Nicolas
Jul 19 '05 #2
Nicolas Fleury wrote:
What about making the ':' optional (and end implicitly at end of current
block) to avoid over-indentation?

def foo():
with locking(someMutex)
with opening(readFilename) as input
with opening(writeFilename) as output
...

would be equivalent to:

def foo():
with locking(someMutex)
with opening(readFilename) as input
with opening(writeFilename) as output
...


Nothing in Python ends at the end of the current block.
They only end with the scope exits. The order of deletion
is not defined, and you would change that as well.

Your approach wouldn't allow the following

with locking(mutex):
increment_counter()

x = counter()

with locking(mutex):
decrement_counter()
except by making a new block, as

if 1:
locking(mutex)

x = counter()

if 1:
locking(mutex)
If the number of blocks is a problem it wouldn't be that
hard to do

with multi( locking(someMutex),
opening(readFilename),
opening(writeFilename) ) as _, input, output:
...

Untested sketch of an implementation
class multi(object):
def __init__(self, *args):
self.args = args
def __enter__(self):
results = []
for i, arg in enumerate(self.args):
try:
results.append(arg.__enter__())
except:
# back up through the already __entered__ args
exc = sys.exc_info()
for j in range(i-1, -1, -1):
try:
self.args[j].__exit__(*exc)
except:
# Need to get the new exception, to match the PEP behavior
exc = sys.exc_info()
raise exc[0], exc[1], exc[2]
return results

def __exit__(self, type, value, traceback):
for arg in self.args[::-1]:
try:
arg.__exit__(type, value, traceback)
except:
type, value, traceback = sys.exc_info()

Andrew
da***@dalkescientific.com

Jul 19 '05 #3
Andrew Dalke wrote:
def foo():
with locking(someMutex)
with opening(readFilename) as input
with opening(writeFilename) as output
...

Nothing in Python ends at the end of the current block.
They only end with the scope exits. The order of deletion
is not defined, and you would change that as well.


There's no change in order of deletion, it's just about defining the
order of calls to __exit__, and they are exactly the same. As far as I
know, PEP343 has nothing to do with order of deletion, which is still
implementation-dependant. It's not a constructor/destructor thing like
in C++ RAII, but __enter__/__exit__.

But yes, it creates a precedent by creating a statement affecting the
end of the current indentation block. But that's what this PEP is all
about...
Your approach wouldn't allow the following
No, I said making the ':' *optional*. I totally agree supporting ':' is
useful.
If the number of blocks is a problem it wouldn't be that
hard to do

with multi( locking(someMutex),
opening(readFilename),
opening(writeFilename) ) as _, input, output:
...


True. But does it look as good? Particularly the _ part?

Regards,
Nicolas
Jul 19 '05 #4
Nicolas Fleury <ni******@yahoo.com_remove_the_> writes:
What about making the ':' optional (and end implicitly at end of current
block) to avoid over-indentation?

def foo():
with locking(someMutex)
with opening(readFilename) as input
with opening(writeFilename) as output
...
How about this instead:

with locking(mutex), opening(readfile) as input:
...

So there could be more than one expression in one with.
would be equivalent to:

def foo():
with locking(someMutex)
with opening(readFilename) as input
with opening(writeFilename) as output
...


The thing is that with normal try-finally block, you can add more
things to it easily. This kind of with thing does not allow adding
more stuff to it in any other way than adding more indentation.

Anyway, I like the idea of the PEP too.

--
Ilpo Nyyssönen # biny # /* :-) */
Jul 19 '05 #5
Nicolas Fleury wrote:
There's no change in order of deletion, it's just about defining the
order of calls to __exit__, and they are exactly the same.
BTW, my own understanding of this is proposal is still slight.
I realize a bit better that I'm not explaining myself correctly.
As far as I
know, PEP343 has nothing to do with order of deletion, which is still
implementation-dependant. It's not a constructor/destructor thing like
in C++ RAII, but __enter__/__exit__.
I'm mixing (because of my lack of full comprehension) RAII with
your proposal.

What I meant to say was in the PEP

with locking(someMutex)
with opening(readFilename) as input
with opening(writeFilename) as output
...

it's very well defined when the __exit__() methods are
called and in which order. If it's
with locking(someMutex)
with opening(readFilename) as input
with opening(writeFilename) as output

with the __exit__()s called at the end of the scope (as if it
were a __del__, which it isn't) then the implementation could
still get the __exit__ order correct, by being careful. Though
there would be no way to catch an exception raised in an __exit__.
I think.
Your approach wouldn't allow the following


No, I said making the ':' *optional*. I totally agree supporting ':' is
useful.


Ahh, I think I understand. You want both

with abc:
with cde:
pass

and

with abc
with def

and to have the second form act somewhat like RAII in that
the __exit__() for that case is called when the scope ends.
Hmm. My first thought is I don't like it because I'm a stodgy
old traditionalist and don't like the ambiguity of having to look
multiple tokens ahead to figure out which form is which.

I can see that it would work. Umm, though it's tricky. Consider

with abc

with defg:
with ghi
with jkl:
1/0

The implementation would need to track all the with/as forms
in a block so they can be __exit__()ed as appropriate. In this
case ghi.__exit() is called after jkl.__exit__() and
before defg.__exit__

The PEP gives an easy-to-understand mapping from the proposed
change to how it could be implemented by hand in the existing
Python. Can you do the same?
True. But does it look as good? Particularly the _ part?


I have not idea if the problem you propose (multiple with/as
blocks) will even exist so I can't comment on which solution
looks good. It may not be a problem in real code, so not needing
any solution.

Andrew
da***@dalkescientific.com

Jul 19 '05 #6
Ilpo Nyyssönen wrote:
........

with locking(mutex), opening(readfile) as input:
...

.....

with EXPR as x:
BLOCK

EXPR can be a tuple so the above would be ambiguous.

--
Robin Becker
Jul 19 '05 #7
Robin Becker wrote:
Ilpo Nyyssönen wrote:

with locking(mutex), opening(readfile) as input:
...


with EXPR as x:
BLOCK

EXPR can be a tuple so the above would be ambiguous.


I don't think EXPR can be a tuple; the result of evaluating EXPR must have __enter__() and __exit__() methods. *x* can be a tuple.

Kent
Jul 19 '05 #8
Kent Johnson wrote:
Robin Becker wrote:
Ilpo Nyyssönen wrote:

with locking(mutex), opening(readfile) as input:
...

with EXPR as x:
BLOCK

EXPR can be a tuple so the above would be ambiguous.

I don't think EXPR can be a tuple; the result of evaluating EXPR must
have __enter__() and __exit__() methods. *x* can be a tuple.

Kent


Well perhaps this would fly then. I reread the PEP and it says EXPR is
arbitrary, but cannot be an expression list so maybe this was already
considered and rejected.
--
Robin Becker
Jul 19 '05 #9
Ilpo Nyyssönen wrote:
Nicolas Fleury <ni******@yahoo.com_remove_the_> writes:
def foo():
with locking(someMutex)
with opening(readFilename) as input
with opening(writeFilename) as output
...


How about this instead:

with locking(mutex), opening(readfile) as input:
...


+1, and add PEP-328-like parentheses for multiline.

Oren

Jul 19 '05 #10
Ilpo Nyyssönen wrote:
How about this instead:

with locking(mutex), opening(readfile) as input:
...


I don't like the ambiguity this proposal introduces. What is input
bound to? The return value of locking(mutex).__enter__() or the return
value of opening(readfile).__enter__()? Seems ambiguous to me. And is
the file opened with the mutex held, or not? Sure, all of these
questions can be answered with an arbitrary decision. But the point is
that, whatever decision you make, I now have to *memorize* that decision.

Note that if I wrote:

with locking(mutex):
with opening(readfile) as input:
...

it's clear that input is the return value of
opening(readfile).__enter__(), and that the mutex is held while the file
is opened. I don't need to memorize these things; they are explicit in
the syntax.

I can see making the with-statement proposal more complex if you had
some very good motivating examples for wanting the multiple-expressions
extension. But you have yet to provide a real-world use case. Go
search your codebase, and find some examples of where you would actually
use this. For the complexity that you want to add to the
with-statement, you need to show that there's a *large* advantage to a
*variety* of use cases in *real-world* code.

STeVe
Jul 19 '05 #11
Andrew Dalke wrote:
The implementation would need to track all the with/as forms
in a block so they can be __exit__()ed as appropriate. In this
case ghi.__exit() is called after jkl.__exit__() and
before defg.__exit__

The PEP gives an easy-to-understand mapping from the proposed
change to how it could be implemented by hand in the existing
Python. Can you do the same?
I think it is simple and that the implementation is as much
straight-forward. Think about it, it just means that:
with abc

with defg:
with ghi
with jkl:
1/0
is equivalent to:
with abc:

with defg:
with ghi:
with jkl:
1/0
That's it. Nothing more complex. It's only about syntax.
I have not idea if the problem you propose (multiple with/as
blocks) will even exist so I can't comment on which solution
looks good. It may not be a problem in real code, so not needing
any solution.


Good point. As a C++ programmer, I use RAII a lot. However, there's
situations in C++ that don't apply, like allocating dynamic memory in a
scope. However, I still expect some Python programmers to use it enough
to ask for that syntax to be added, in the same way operators like +=
have been added.

But there's another point that has nothing to do with how many "with"
statements you have in a function. In C++, very very rarely I've seen
something like:

void foo() {
{ // (define a scope for the Lock object)
Lock locking(myMutex);
...
}
...
{
Lock locking(myMutex);
...
}
}

So I come to another conclusion: the indentation syntax will most of the
time result in a waste of space. Typically a programmer would want its
with-block to end at the end of the current block.

So basically, there's two 10-90% points, one in favor of my proposal,
one against:

- Most of the time, you don't have a lot of with-statements in a single
function, so not so much indentation.
- Most of the time, a with-statement ends at the end of current block,
so indentation-syntax most of the time result in a waste of space.

The way to see my proposal is not "to be used when you have multiple
with-blocks" but instead "never use the ':' syntax, unless necessary".
The day some code need it, it's very easy to add a ':' and indent some
code with our favorite editor.

Regards,
Nicolas
Jul 19 '05 #12
Nicolas Fleury <ni*****@yahoo.com> wrote:
It's important to note that nobody is against the PEP syntax. We are
only talking about adding things to it


In think the above is a contradiction in terms.
Jul 19 '05 #13
Nicolas Fleury wrote:
Since the current syntax would be there, the no-indentation syntax can
be explained in terms of the indentation syntax:

"""
To avoid over-indentation, a with-statement can avoid defining a new
indentation block. In that case, the end of the with block is the end
of the current indentation block.

with EXPR as VAR
REST OF BLOCK

is equivalent to

with EXPR as VAR:
BLOCK
"""

What do you think? I fail to see the complexity...


I guess my only real qualm about this is that I think it makes it harder
to see where __exit__() methods are called. When I compare:

def func(arg, baz):
foo = bar(arg)
with x as foo(baz)
x.frobble()
with y as x.bop()
return frabble(x, y)

with:

def func(arg, baz):
foo = bar(arg)
with x as foo(baz):
x.frobble()
with y as x.bop():
return frabble(x, y)

I find it much easier to identify in the second one that __exit__()
methods will be called right before the function returns (after the
return statement). YMMV.

BTW, if you really like the optional-indentation idea, you should post
it to the Wiki page (http://wiki.python.org/moin/WithStatement) --
Guido's been pretty quick to respond to any comments made there, so you
could get some feedback much more useful than I can give you. ;)

STeVe
Jul 19 '05 #14

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

Similar topics

0
by: Carlos Ribeiro | last post by:
I thought about this problem over the weekend, after long hours of hacking some metaclasses to allow me to express some real case data structures as Python classes. I think that this is something...
2
by: Ron Adam | last post by:
After taking a break from following PEP 343 and it's associated PEPs, I wanted to look at it again because it still seemed a bit hard to get my mind around. ...
0
by: falcon | last post by:
I know I came after the battle. And I have just another sight on context managment. Simple Context Managment may look in Python 2.4.1 like this: Synhronized example: def...
0
by: Robert | last post by:
After failing on a yield/iterator-continuation problem in Python (see below) I tried the Ruby (1.8.2) language first time on that construct: The example tries to convert a block callback interface...
1
by: neokosmos | last post by:
I've seen various generator-based microthread implementations online, but I've been wondering: has anyone used microthreads in this manner in a game environment? Note, I am emphatically *not*...
2
by: Julio C. Hernandez Castro | last post by:
Dear all, We have just developped a new block cipher called Raiden, following a Feistel Network structure by means of genetic programming. Our intention now consists on getting as much feedback...
16
by: aralsky | last post by:
I am looking for a fake consumer review generator that could generate realistic looking reviews for any products, kind of like on amazon.com but generated by Artificial Intelligence. Is there a...
2
by: Adam Atlas | last post by:
I'm trying to emulate the Python 2.5 behaviour (PEP 342) of generator functions where the `yield` statement is in a `try/finally` block. Basically, where the `finally` block is guaranteed to run...
5
by: james | last post by:
To give an example of what I mean I have already altered the code: def output_random_lesson_of_type(self, type=None): """Output a lesson of a specific type. If no type is passed in then output...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
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...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
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:
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
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

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.