Return value of an assignment statement?

Steve Holden steve at holdenweb.com
Fri Feb 22 11:52:00 EST 2008


Carl Banks wrote:
> On Feb 21, 6:52 pm, Steve Holden <st... at holdenweb.com> wrote:
>> mrstephengross wrote:
>>>> What you can't do (that I really miss) is have a tree of assign-and-test
>>>> expressions:
>>>>         import re
>>>>         pat = re.compile('some pattern')
>>>>         if m = pat.match(some_string):
>>>>             do_something(m)
>>> Yep, this is exactly what I am (was) trying to do. Oh well.... Any
>>> clever ideas on this front?
>> The syntax is the way it is precisely to discourage that kind of clever
>> idea.
> 
> Don't be ridiculous.  Assignment operators are maybe one of the worst
> things in existence, but this particular use case (running a sequence
> of tests like the above) is perfectly useful and good.
> 
> Some Pythonistas will swear to their grave and back that should be
> done by factoring out the tests into a list and iterating over it, and
> NO OTHER WAY WHATSOEVER, but I don't buy it.  That's a lot of
> boilerplate--the very thing Python is normally so good at minimizing--
> when it might not be needed.  It would be the right thing for a
> complex, pluggable, customizable input filter; but is rarely a better
> solution for a simple text processing script.
> 
> Quick, at a glance, which code snippet will you understand faster
> (pretend you know Perl):
> 
> 
> if (/name=(.*)/) {
>     $name = chop(\1);
> } elsif (/id=(.*)/) {
>     $id = chop(\1);
> } elsif (/phone=(.*)/) {
>     $phone = chop(\1);
> }
> 
> 
> vs.
> 
> 
> def set_phone_number(m):
>     phone = m.group(1).strip()
> 
> def set_id(m):
>     id = m.group(1).strip()
> 
> def set_name(m):
>     name = m.group(1).strip()
> 
> _line_tests = [
>     (r"phone=(.*)", set_phone_number),
>     (r"name=(.*)", set_name),
>     (r"id=(.*)", set_id),
>     ]
> 
> for pattern,func in _line_tests:
>     m = re.match(pattern,line)
>     if m:
>         func(m)
> 
> 
> At this small scale, and probably at much larger scales too, the Perl
> example blows the Python example out of the water in terms of
> readability.  And that's counting Perl's inherent unreadableness.
> 
I'm supposed to overlook the fact that your example in Python omits the 
"untested" it clearly deserves, I take it? I'm not sure what you are 
trying to do with the assignments inside the function body.

The brevity of the Perl has something to commend it, but I am always 
suspicious about whether algorithms like that should really be data 
driven. It's all too easy to add further tests as new field 
possibilities are added. It's also unpleasant in that it leaves two 
variables in an undetermined state.

Let's assume that your Python functions were correctly assigning to 
attributes of some object that was being passed in or global, at least 
then it would be possible to add an else condition to each iteration to 
set the attribute's default value somehow.

So I think your example is perhaps not the best one you could have 
chosen to make your case.

I will admit that idiomatic usages are acceptable ways to perform common 
tasks, but I still think that Guido's decision to eschew assignments as 
expression terms is a sound one, and one that encourages better program 
construction.

Hey, call me (or my assertions) ridiculous if you want. It remains that 
allowing such terms will inevitably lead to hard-to-debug confusion 
between assignment and equality testing once the difference becomes a 
single equals sign.

> If it were a priority, Python could support this set-and-test idiom,
> and without an assignment operator.  (Notice Perl doesn't use
> assignment operator here.)  For example, a syntax like this (where the
> scope of m is local to the if-condition and the body of the if-
> statement:
> 
> if m where m = re.match(r"name=(.*)",line):
>     name = m.group(1).strip()
> elif m where m = re.match(r"id=(.*)",line):
>     id = m.group(1).strip()
> elif m where m = re.match(r"phone=(.*)",line):
>     phone = m.group(1).strip()
> 
[I'll presume you've already established default values for name, id and 
phone just to quiet the alarms ringing in the background]. Still looks 
to me like it might be better data-driven with a setattr() in there 
somewhere. As far as I can see all this would achieve would be to limit 
the scope of the assignment,  and I don't really see what advantage that 
provides.
> 
> This won't happen because the set-and-test idiom is relatively minor
> and not deemed worthy of syntax support.  But if it were there,
> there'd really be nothing clever about it.
> 
Note also that I'm not saying an experienced programmer can't get these 
things right. But at any given time half the programmers in the world 
are newbies, and Python tries to help them by steering them in safer 
directions.

Maybe we could allow it if you had a digital certificate asserting that 
you'd passed your metaclass abuse test ... <0.75 wink>

regards
  Steve
-- 
Steve Holden        +1 571 484 6266   +1 800 494 3119
Holden Web LLC              http://www.holdenweb.com/




More information about the Python-list mailing list