<html>
<head>
<style>
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
FONT-SIZE: 10pt;
FONT-FAMILY:Tahoma
}
</style>
</head>
<body class='hmmessage'><div style="text-align: left;">I'm sure you've heard most/all of this before but..it..just..seems..so..true...<br><br>Finally this week I've "written" (ported from sh) a bunch of Perl, 2000 sparse lines.<br>While it sure beats Perl, it has some glaring flaws, more glaring due to<br>its overall goodness.<br><br>I feel compelled to voice my opinion, as if we don't live in a benevolent dictatorship :),<br>and as if the weight of existing code was zero.<br>Much of what I dislike cannot be changed without massive breakage.<br><br>Below is what i get from:<br><br>jbook:/dev2/cm3/scripts/python/flaws jay$ ls -l<br>total 72<br>-rw-r--r--&nbsp;&nbsp; 1 jay&nbsp; admin&nbsp; 834 Dec 29 16:02 1_not_lexically_scoped.py<br>-rw-r--r--&nbsp;&nbsp; 1 jay&nbsp; admin&nbsp; 238 Dec 29 16:02 2_reads_scoped_writes_not.py<br>-rw-r--r--&nbsp;&nbsp; 1 jay&nbsp; admin&nbsp; 593 Dec 29 16:02 3_lambda_is_neutered.py<br>-rw-r--r--&nbsp;&nbsp; 1 jay&nbsp; admin&nbsp; 377 Dec 29 16:03 4_assignment_is_not_expression.py<br>-rw-r--r--&nbsp;&nbsp; 1 jay&nbsp; admin&nbsp; 760 Dec 29 16:02 5_for_loop_off_by_one.py<br>-rw-r--r--&nbsp;&nbsp; 1 jay&nbsp; admin&nbsp; 412 Dec 29 16:01 6_docs_good_but_a_complaint.txt<br>-rw-r--r--&nbsp;&nbsp; 1 jay&nbsp; admin&nbsp; 254 Dec 29 16:02 7_print_is_wierd.py<br>-rw-r--r--&nbsp;&nbsp; 1 jay&nbsp; admin&nbsp; 286 Dec 29 16:06 8_eval_vs_exec.py<br>-rw-r--r--&nbsp;&nbsp; 1 jay&nbsp; admin&nbsp; 824 Dec 29 16:14 9_typo_on_read_error_but_write_ok.py<br><br>jbook:/dev2/cm3/scripts/python/flaws jay$ cat * &gt; all.txt<br><br>jbook:/dev2/cm3/scripts/python/flaws jay$ edit all.txt<br><br>Each "---" seperates a file and they are executable Python.<br><br>&nbsp;- Jay<br><br><br>#----------------------------------------------------------<br># flaw #1<br># not lexically scopied<br># Functions have their own locals, but other blocks do not.<br># This is true both for "normal" variables and lexically nested functions.<br>#<br><br>#<br># This is probably largely an outcome of not declaring variables?<br>#<br><br>A = "A1:global"<br><br>def F1():<br>&nbsp;&nbsp;&nbsp; A = "A1:in first F1"<br>&nbsp;&nbsp;&nbsp; print "F1:global"<br><br>if True:<br>&nbsp;&nbsp;&nbsp; A = "A1:in if"<br>&nbsp;&nbsp;&nbsp; def F1():<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A = "A1:in if.F1" # This does the right thing.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print "F1:in if"<br>&nbsp;&nbsp;&nbsp; F1() # This does the right thing.<br><br># This should go to "global" but it goes to "in if"<br>F1()<br><br>def F2():<br>&nbsp;&nbsp;&nbsp; A = "A1:in F2"<br>&nbsp;&nbsp;&nbsp; def F1():<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A = "A1:in F2.F1"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print "F1:in F2"<br><br># Given how if behaved, you'd expect this to go to F2.F1 but it does not.<br>F1()<br><br># This should be "global" but is "in if".<br>print("A is " + A)<br><br>#----------------------------------------------------------<br># flaw #2<br>#<br># In functions, reads are scoped. Writes are not.<br>#<br><br>A = "1"<br><br>def F1():<br>&nbsp;&nbsp;&nbsp; A = "2" # not an error<br><br>def F2():<br>&nbsp;&nbsp;&nbsp; #B = A # error<br>&nbsp;&nbsp;&nbsp; A = "3"<br>&nbsp;&nbsp; &nbsp;<br>F1()<br>F2()<br>print(A)<br><br>#----------------------------------------------------------<br># flaw #3:<br>#&nbsp; lambda is neutered<br>#&nbsp; It allows just one expression, and no statements<br>#<br><br># This should work:<br><br>import os<br><br>#os.path.walk(<br>#&nbsp;&nbsp;&nbsp; "..",<br>#&nbsp;&nbsp;&nbsp; lambda(a, b, c):<br>#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(b)<br>#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(b)<br>#&nbsp;&nbsp;&nbsp; None)<br><br># Instead I must say:<br><br>def Callback(a, b, c):<br>&nbsp;&nbsp;&nbsp; print(b)<br>&nbsp;&nbsp;&nbsp; print(b)<br>&nbsp;&nbsp; &nbsp;<br>os.path.walk(<br>&nbsp;&nbsp;&nbsp; "..",<br>&nbsp;&nbsp;&nbsp; Callback,<br>&nbsp;&nbsp;&nbsp; None)<br><br>#<br># Moving callbacks away from their point of use hurts readability.<br># This is probably mitigated by lexical scoping of functions, but<br># notice that other blocks are not lexically scoped.<br>#<br><br>#----------------------------------------------------------<br># flaw #4:<br>#&nbsp;&nbsp; assignment is not an expression<br>#<br><br># This should work (seen in Perl code, nice idiom):<br><br>#A = [1,2]<br>#while (B = A.pop()):<br>#&nbsp;&nbsp;&nbsp; print(B)<br><br># instead I must say:<br><br>A = [1,2]<br>while (A):<br>&nbsp;&nbsp;&nbsp; B = A.pop()<br>&nbsp;&nbsp;&nbsp; print(B)<br><br># Even if you reject popping an empty list, ok<br># there are PLENTY of applications of this.<br><br>#----------------------------------------------------------<br># flaw #5<br>#<br># for loops suck<br>#<br># It should be easy to iterate from 0 to n, not 0 to n - 1,<br># thereby knowing why the loop terminated<br>#<br><br>#This should work:<br><br># print the first even number, if there are any<br><br>A = [1, 3]<br>for i in range(0, len(A)):<br>&nbsp;&nbsp;&nbsp; if ((A[i] % 2) == 0):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("even number found")<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>if (i == len(A)):<br>&nbsp;&nbsp;&nbsp; print("no even numbers found")<br>&nbsp;<br># instead I must write:<br><br>i = 0<br>while (i != len(A)):<br>&nbsp;&nbsp;&nbsp; if ((A[i] % 2) == 0):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("even number found")<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp; i += 1<br>if (i == len(A)):<br>&nbsp;&nbsp;&nbsp; print("no even numbers found")<br><br># with the attendent problem of not being able to "continue" ever, since<br># the end of the loop body must be run in order to proceed<br><br>Flaw #6<br><br>The docs are very good.<br><br>However the reference doesn't give much in the way<br>of semantic description.<br><br>It is surprising that an experienced programmer MUST<br>depend on the tutorial or any examples or semantics.<br>Light on examples, ok for reference.<br><br>The language reference is little more than the grammar in parts.<br><br>There needs to be links from the reference back to the tutorial.<br><br>Perhaps merge the indices for Tutorial, Language Reference, Library Reference.<br>Or maybe that's what search is for.<br><br>On the other hand, way better than Perl.<br><br>#----------------------------------------------------------<br># Flaw #7<br>#<br># This is a compatibility issue.<br># print is both a statement and a function, or something.<br>#<br><br>print() # should print just a newline, but prints two parens<br><br># workaround:<br><br>print("")<br><br>#----------------------------------------------------------<br># flaw #8<br>#<br># Having to eval expressions but exec statements feels wrong.<br># There should just be eval.<br>#<br><br># eval("print(1)") # error<br>exec("print(1)") # not an error<br><br>exec("1 + 2") # not an error?<br>eval("1 + 2") # not an error<br><br>#----------------------------------------------------------<br># flaw #9<br>#<br># Python protects me, via early checking, from typos<br># when I read, but not when I write. It should do both.<br># That is, I should declare variables.<br>#<br><br>Correct = 1<br># proposed typo is Corect<br><br>#A = Corect # error, good<br>Corect = 1 # no error, bad<br><br># For classes, by default, same thing:<br><br>class Foo(object):<br>&nbsp;&nbsp;&nbsp; def __init__(self):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.Correct =1<br><br>F = Foo()<br># print(F.Corect) # error, good<br>F.Corect = 1 # no error, bad<br><br># __slots__ fixes this, but is not the default<br><br>class Bar(object):<br>&nbsp;&nbsp;&nbsp; __slots__ = ["Correct"]<br>&nbsp;&nbsp;&nbsp; def __init__(self):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.Correct =1<br><br>B = Bar()<br># print(B.Corect) # error, good<br>#B.Corect = 1 # error, good<br><br># __slots__ should be the default and then some other syntax<br># for "expandable" types, like __slots__ = [ "*" ]<br><br></div><br /><hr />Get the power of Windows + Web with the new Windows Live. <a href='http://www.windowslive.com?ocid=TXT_TAGHM_Wave2_powerofwindows_122007' target='_new'>Get it now!</a></body>
</html>