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