[Python-ideas] Combining test and assignment, quantifications, and tuple patterns (original) (raw)

Alexander Heger python at 2sn.net
Sun Jan 22 06:33:23 CET 2012


I think one could use the same new construct I proposed for one of the recent lengthy discussions. For your convenience, I copy this below, in disregards of quoting style as it provides an overarching reply to this thread.

You could use

sample as x: # do something with x break else: # do something else

here the generator expression would be "spam()"

sample y for y in (spam(),) if cond(y) as x: (...)

or allow a short form

sample y for spam() if cond(y) as x: (...)

I really think this expressions could add a lot to Python's expressiveness.

As an important note, in the case below, the difference to just a "for loop" or "generator" would be that is re-evaluated from scratch every time the loop returns to the sample statement. This is what I think would set it apart besides providing extra uses otherwise.

Admittedly, it is a very complicated construct. Longer than most good English sentences. (for which those above are not good examples)

-Alexander

-------- Original Message -------- Subject: Re: [Python-ideas] Fwd: quantifications, and tuple patterns Date: Mon, 16 Jan 2012 22:00:52 -0600 From: Alexander Heger <python at 2sn.net> To: python-ideas at python.org

Dear Tom,

I'm wondering if would make sense to add an "as" clause to the while and if statements, similar to the as clause in the with statement. It would essentially retrieve the value field from the witness object described above.

This would let one write the main loop in a topological sort (a classic workset algorithm) as:

 while any(v for v in vertices if v.incoming_count == 0) as v1:
     result.append(v)
     for v2 in v1.outgoing:
         v2.incoming_count -= 1

I had the same thought going through the thread, but I think the problem here would be that any is a function that returns a Boolean value. You could add a key parameter to return something else, say a tuple of a truth value and a sample ( any( ..., sample = True) ) but that could break because

  1. "any" could be another function in the context,

  2. while would need to deal with special return values in this case

A suggestion to replace the "while any" case is

sample as x: # do something with x

("sample" may not be the best keyword choice) From the discussion so far I do not see how to easily avoid having a new keyword

specifically, your example would become

sample v for v in vertices if v.incoming_count == 0 as v1: # do things with v1

In case you only want one sample, you could add the break statement

sample db.query(page_name=page_name) as page: render_template(page) break else: error404()

-Alexander

On 01/21/2012 10:51 PM, Steven D'Aprano wrote:

Nick Coghlan wrote:

This suggestion (i.e. embedded assignment in while and if headers) has been made several times, and always come to a grinding halt on one simple problem: it isn't expressive enough. [...] The obvious escalation of the suggestion is to adopt "(EXPR as NAME)" as a general purpose embedded assignment expression. However, this idea has problems of its own:

I dislike assignment as an expression, and am glad that Python doesn't have it. Even though the form "expr as name" avoids the common C gotcha, I am -1 on adding it to Python. I believe it is an unnatural way of writing that obscures the code rather than simplifies it. (Sometimes, shorter is not better.) For example, when writing code, I might start off by thinking: if spam() != 'ham': frobulate(spam()) Then I would apply DRY and factor out the call to spam: x = spam() if x != 'ham': frobulate(x) This matches my thought processes and corresponds to how you might naturally describe the algorithm in English: Let x equal spam(). If x != 'ham', then frobulate(x). The important thing is that you name the thing you care about before using it. I think this is a very natural way of writing: first you give the thing you care about a name, then you refer to it by name. Assignment as an expression feels unnatural to me: if spam() as x != 'ham': frobulate(x) doesn't really correspond to any natural English order. The assignment is dropped in the middle of another clause: If -- let x = spam() -- x != 'ham', then frobulate(x). It saves a line, but is not a natural way of writing for me. I would not like to read code written that way. Assignment as an expression also lends itself to writing buggy code like this: while spam() as x and ham() as y: frobulate(x) glommify(y) which is wrong, because y won't be defined if x has a true value. The alternative would require defeating the short-circuit nature of "and", which would be bad. Perhaps the only thing going for it is that it would allow list comprehensions to not repeat themselves: # instead of this [frobulate(x) for x in seq if frobulate(x)> 0] # you could have this [y for x in seq if frobulate(x) as y> 0] Although I prefer to use an inner map: [y for y in map(frobulate, seq) if y> 0] # use itertools.imap in Python2



More information about the Python-ideas mailing list