Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #63006 > unrolled thread
| Started by | John Allsup <pydev@allsup.co> |
|---|---|
| First post | 2014-01-02 21:44 +0000 |
| Last post | 2014-01-03 16:35 +1100 |
| Articles | 6 — 4 participants |
Back to article view | Back to comp.lang.python
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: Ifs and assignments John Allsup <pydev@allsup.co> - 2014-01-02 21:44 +0000
Re: Ifs and assignments Roy Smith <roy@panix.com> - 2014-01-02 18:36 -0500
Re: Ifs and assignments Chris Angelico <rosuav@gmail.com> - 2014-01-03 11:07 +1100
Re: Ifs and assignments Chris Angelico <rosuav@gmail.com> - 2014-01-03 11:06 +1100
Re: Ifs and assignments Ethan Furman <ethan@stoneleaf.us> - 2014-01-02 20:16 -0800
Re: Ifs and assignments Chris Angelico <rosuav@gmail.com> - 2014-01-03 16:35 +1100
| From | John Allsup <pydev@allsup.co> |
|---|---|
| Date | 2014-01-02 21:44 +0000 |
| Subject | Re: Ifs and assignments |
| Message-ID | <mailman.4811.1388704420.18130.python-list@python.org> |
The point of my original post was that, whilst C's
if( x = 2 ) { do something }
and
if( x == 2 ) { do something }
are easy to confuse, and a source of bugs, having a construct like follows:
if x == 2:
do something # what happens at present
if testFunc() as x:
do something with x
using the 'as' syntax that appears with 'with' and 'except', would allow
for the advantages of C style assignments in conditionals but without
the easy confusion, since here the syntax is significantly different
between assignment and equality testing (rather than a character apart
as happens with C).
This occurs further down in my original post (past the point where you
inserted your reply).
Another post suggested a workaround by defining a 'pocket' class, for
which I am grateful.
John
On 02/01/2014 19:27, Gary Herron wrote:
> On 01/02/2014 09:20 AM, John Allsup wrote:
>> Hi,
>>
>> This is my debut on this list.
>>
>> In many languages, such as C, one can use assignments in conditionals
>> and expressions. The most common, and useful case turns up when you
>> have if/else if/else if/else constructs. Consider the following
>> non-working pseudoPython.
>>
>> import re
>> r1 = re.compile("hello (\d)")
>> r2 = re.compile("world([!?])")
>>
>> w = "hello world!"
>>
>> if m = r1.search(w):
>
> This kind of thing in C/C+ has always been the source of much confusion
> and potential errors, because the construct is so similar to an "=="
> test. Python does not replicate this potential for confusion. Instead,
> we use two lines of code, an assignment and then the test. If you find
> that extra line of code inconvenient than at least you can take comfort
> in the fact that it is clearer code. If you are still not convinced,
> ... then sorry, that's just the way Python is.
>
> Gary Herron
>
>
>> handleMatch1(m)
>> elif m = r2.search(w):
>> handleMatch2(m)
>> else:
>> print("No match")
>>
>> If the regular expressions are complex, running them multiple times
>> (once to test, another to capture groups) isn't ideal. On the other
>> hand, at present, one has to either do:
>>
>> m = r1.search(w)
>> if m:
>> handleMatch1(m)
>> else:
>> m = r2.search(w)
>> if m:
>> handleMatch2(m)
>> else:
>> print("No match")
>>
>> if not running unnecessary matches, yet capturing groups in the event
>> of a successful match, is what is desired.
>>
>> If there are multiple tests, the indentation gets silly. This arises
>> because having removed the ability to assign in an expression, there
>> is no way to save the result of a function call that is used in a
>> conditional at all.
>>
>> I am aware that this facility in C is a source of bugs, = being only a
>> typo away from the more common ==. With exceptions and contexts, we
>> have:
>>
>> with open("file") as f:
>> doSomethingWith(f)
>>
>> try:
>> trySomething()
>> except SomethingRandomGoingWrong as e:
>> lookAtException(e)
>>
>> What I am wondering is why not use a similar syntax with if, so that
>> one could do
>>
>> if r1.search(w) as m:
>> g = m.groups()
>> print(g[1])
>>
>> This would remove the risk of errors by typos since the syntax for
>> equality testing (if x == y:) is completely different from that for
>> assigning in a conditional (which would look like 'if y as x:'
>>
>> Related would be to have Nonetype work with contexts such that
>>
>> with None as x:
>> doStuff(x)
>>
>> would do nothing. This would allow things like:
>>
>> with maybeGetSomething as x:
>> doStuff(x)
>>
>> to call doStuff(x) within a context of maybeGetSomething returns
>> something, or do nothing if nothing is returned. (Adding an else-like
>> keyword to with, or possibly using else in that context, would allow
>> one to process a non-None object if returned, or else do something in
>> response to a None object being returned by the maybeGetSomething.)
>>
>> Just a thought.
>>
>> Or what is the current 'Pythonic' way to do something like:
>>
>> if x = func1():
>> do1(x)
>> elif x = func2():
>> do2(x)
>> elif x = func3():
>> do3(x)
>> elif x = func4():
>> do4(x)
>> else:
>> do5()
>>
>> where each of func1,func2,func3,func4 have side effects so that func2
>> is tested if and only if func1 returns a false value, func1 must be
>> called only once, and what is returned from func1 must be available to
>> the code inside the if block?
>>
>>
>> John
>>
>
[toc] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2014-01-02 18:36 -0500 |
| Message-ID | <roy-8601CA.18361502012014@news.panix.com> |
| In reply to | #63006 |
In article <mailman.4811.1388704420.18130.python-list@python.org>,
John Allsup <pydev@allsup.co> wrote:
> if testFunc() as x:
> do something with x
+1
The most common place I wish for an atomic "test and assign" is with
regexes, as in your examples. This would be so much nicer than what we
have to do now:
if re.match(string) as m:
print m.group(0)
The analogy to
except SomeError as ex:
is very clear. They are both "Perform some action, capture the result,
do some test on it, and then make that captured value available bound to
a name".
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-01-03 11:07 +1100 |
| Message-ID | <mailman.4813.1388707688.18130.python-list@python.org> |
| In reply to | #63007 |
On Fri, Jan 3, 2014 at 11:06 AM, Chris Angelico <rosuav@gmail.com> wrote: > Pass any object through truth() and it'll either stay the same (if > it's true) or become this object (if it's false). You can then carry > on with other method calls, and they'll all happily return false. > > result = ( > truth(re1.match(string)).group(0) or > truth(re2.match(string)).group(0) or > truth(re3.match(string)).group(0) or > default_value > ) Oh, just thought of a possible snag. Since an empty string comes up as false, this exact notation would fail if the re can match nothing. But you probably know if it's possible for that to happen, so don't use this simple short-hand. :) ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-01-03 11:06 +1100 |
| Message-ID | <mailman.4814.1388708064.18130.python-list@python.org> |
| In reply to | #63007 |
On Fri, Jan 3, 2014 at 10:36 AM, Roy Smith <roy@panix.com> wrote:
> The most common place I wish for an atomic "test and assign" is with
> regexes, as in your examples. This would be so much nicer than what we
> have to do now:
>
> if re.match(string) as m:
> print m.group(0)
Here's a crazy idea. Suppose we have a "sticky falseness" that can
quietly propagate through an expression the way a NaN can... then we
could just float that right through the .group() call.
class truth:
def __new__(cls, x):
if x: return x
return object.__new__(cls)
def __bool__(self):
return False
def __getattr__(self, name):
return self
def __call__(self, *args, **kwargs):
return self
def __repr__(self):
return repr(False)
Pass any object through truth() and it'll either stay the same (if
it's true) or become this object (if it's false). You can then carry
on with other method calls, and they'll all happily return false.
result = (
truth(re1.match(string)).group(0) or
truth(re2.match(string)).group(0) or
truth(re3.match(string)).group(0) or
default_value
)
(I'm not sure if I'm using __new__ correctly; I've never actually done
it in production code, and the info I found online was mainly Py2
examples. Should that be done with super(), or is that applicable only
once there's an actual instance with a real MRO?)
I've given the class a lower-case first letter as I'm basically using
this as a function. If this were ever to be considered for the
standard library I would expect to see that aspect of it heavily
bikeshedded, so I'm not too concerned about the details.
In a spirit of full disclosure, I must confess that the idea came from
Pike, where there's a variant member-lookup operator that will happily
return false from false rather than throwing an exception. :)
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Ethan Furman <ethan@stoneleaf.us> |
|---|---|
| Date | 2014-01-02 20:16 -0800 |
| Message-ID | <mailman.4831.1388724082.18130.python-list@python.org> |
| In reply to | #63007 |
On 01/02/2014 04:06 PM, Chris Angelico wrote: > > Here's a crazy idea. Suppose we have a "sticky falseness" that can > quietly propagate through an expression the way a NaN can... then we > could just float that right through the .group() call. > > class truth: > def __new__(cls, x): > if x: return x > return object.__new__(cls) > def __bool__(self): > return False > def __getattr__(self, name): > return self > def __call__(self, *args, **kwargs): > return self > def __repr__(self): > return repr(False) > > Pass any object through truth() and it'll either stay the same (if > it's true) or become this object (if it's false). You can then carry > on with other method calls, and they'll all happily return false. An interesting idea. You'd need to add (at least) __getitem__, and I'll probably call it `maybe`, myself. ;) > (I'm not sure if I'm using __new__ correctly; I've never actually done > it in production code, and the info I found online was mainly Py2 > examples. Should that be done with super(), or is that applicable only > once there's an actual instance with a real MRO?) I haven't tested it, but your __new__ looks fine. The only thing you lose by not calling super() is the inability for cooperative multiple inheritance, except as the ultimate base class. -- ~Ethan~
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-01-03 16:35 +1100 |
| Message-ID | <mailman.4834.1388727330.18130.python-list@python.org> |
| In reply to | #63007 |
On Fri, Jan 3, 2014 at 3:16 PM, Ethan Furman <ethan@stoneleaf.us> wrote: > On 01/02/2014 04:06 PM, Chris Angelico wrote: >> >> >> Here's a crazy idea. Suppose we have a "sticky falseness" that can >> quietly propagate through an expression the way a NaN can... then we >> could just float that right through the .group() call. >> >> class truth: > > An interesting idea. You'd need to add (at least) __getitem__, and I'll > probably call it `maybe`, myself. ;) I was going for something like bool(). If you pass something through bool(), you get either True or False; if you pass something through this, you get either itself or something that acts like False. >> (I'm not sure if I'm using __new__ correctly; I've never actually done >> it in production code, and the info I found online was mainly Py2 >> examples. Should that be done with super(), or is that applicable only >> once there's an actual instance with a real MRO?) > > I haven't tested it, but your __new__ looks fine. The only thing you lose > by not calling super() is the inability for cooperative multiple > inheritance, except as the ultimate base class. Is it possible to have multiple inheritance at this point, though? I get a class argument, not an instance, because there isn't an instance. ChrisA
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web