[Python-ideas] Python Reviewed

Simon Lovell simon58500 at bigpond.com
Mon Jan 9 06:25:45 EST 2017


Python Reviewed

Having used a lot of languages a little bit and not finding satisfactory 
answers to these in some cases often asked questions, I thought I'd join 
this group to make a post on the virtues and otherwise of python.

The Good:
     Syntactically significant new lines
     Syntactically significant indenting
     Different types of array like structures for different situations
     Mostly simple and clear structures
     Avoiding implicit structures like C++ references which add only 
negative value
     Avoiding overly complicated chaining expressions like 
"while(*d++=*s++);"
     Single syntax for block statements (well, sort of. I'm ignoring 
lines like "if a=b: c=d")
     Lack of a with statement which only obscures the code


The Bad:
     Colons at the end of if/while/for blocks. Most of the arguments in 
favour of this decision boil down to PEP 20.2 "Explicit is better than 
implicit". Well, no. if/while/for blocks are already explicit. Adding 
the colon makes it doubly explicit and therefore redundant. There is no 
reason I can see why this colon can't be made optional except for 
possibly PEP20.13 "There should be one-- and preferably only one 
--obvious way to do it". I don't agree that point is sufficient to 
require colons.


     No end required for if/while/for blocks. This is particularly a 
problem when placing code into text without fixed width fonts. It also 
is a potential problem with tab expansion tricking the programmer. This 
could be done similarly to requiring declarations in Fortran, which if 
"implicit none" was added to the top of the program, declarations are 
required. So add a "Block Close Mandatory" (or similar) keyword to 
enforce this. In practice there is usually a blank line placed at the 
end of blocks to try to signal this to someone reading the code. Makes 
the code less readable and I would refer to PEP20.7 "Readability counts"


     This code block doesn't compile, even given that function "process" 
takes one string parameter:
         f=open(file)
         endwhile=""
         while (line=f.readline())!=None:
             process(line)
         endwhile

         I note that many solutions have been proposed to this. In C, it 
is the ability to write "while(line=fgets(f))" instead of 
"while((line=fgets(f))!=NULL)" which causes the confusion. No solutions 
have been accepted to the current method which is tacky:
         f=open(file)
         endwhile=""
         endif=""
         while True:
             line=f.readline
             if line = None:
                 break
             endif
             process(line)
         endwhile


     Inadequacy of PEP249 - Python Database Specification. This only 
supports dynamic SQL but SQL and particularly select statements should 
be easier to work with in the normal cases where you don't need such 
statements. e.g:
         endselect=""
         idList = select from identities where surname = 'JONES':
                 idVar         = id
                 forenameVar    = forename
                 surnameVar    = surname
                 dobVar        = dob
         endselect

         endfor=""
         for id in idList:
             print id.forenameVar, id.dobVar
         endfor

         as opposed to what is presently required in the select case 
which is:
             curs = connection.cursor()
             curs.execute("select id, forename, surname, dob from 
identities where surname = 'JONES'")
             idList=curs.fetchall()

             endfor=""
             for id in idList:
                 print id[1], id[3]
             endfor

         I think the improvement in readibility for the first option 
should be plain to all even in the extremely simple case I've shown.

         This is the sort of thing which should be possible in any 
language which works with a database but somehow the IT industry has 
lost it in the 1990s/2000s. Similarly an upgraded syntax for the 
insert/values statement which the SQL standard has mis-specified to make 
the value being inserted too far away from the column name. Should be 
more like:
             endinsert=""
             Insert into identities:
                 id = 1
                 forename = 'John'
                 surname = 'Smith'
                 dob = '01-Jan-1970'
             endinsert

         One of the major problems with the status quo is the lack of 
named result columns. The other is that the programmer is required to 
convert the where clause into a string. The functionality of dynamic 
where/from clauses can still be provided without needing to rely on 
numbered result columns like so:
         endselect=""
         idList = select from identities where :where_clause:
             id        = id
             forename    = forename
             surname        = surname
             dob        = dob
         endselect

         Ideally, the bit after the equals sign would support all 
syntaxes allowed by the host database server which probably means it 
needs to be free text passed to the server. Where a string variable 
should be passed, the :variable syntax could be supported but this is 
not often required


     Variables never set to anything do not error until they are used, 
at least in implementations of Python 2 I have tried. e.g.
         UnlikelyCondition = False
         endif=""
         if UnlikelyCondition:
             print x
         endif

         The above code runs fine until UnlikelyCondition is set to True


     No do-while construct


     else keyword at the end of while loops is not obvious to those not 
familiar with it. Something more like whenFalse would be clearer


     Changing print from a statement to a function in Python 3 adds no 
positive value that I can see


     Upper delimiters being exclusive while lower delimiters are 
inclusive. This is very counter intuitive. e.g. range(1,4) returns 
[1,2,3]. Better to have the default base as one rather than zero IMO. Of 
course, the programmer should always be able to define the lower bound. 
This cannot be changed, of course.


     Lack of a single character in a method to refer to an attribute 
instead of a local variable, similar to C's "*" for dereferencing a pointer


     Inability to make simple chained assignments e.g. "a = b = 0"


     Conditional expression (<true-value> if <condition> else 
<false-value>) in Python is less intuitive than in C (<condition> ? 
<true-value> : <false-value>). Ref PEP308. Why BDFL chose the syntax he 
did is not at all clear.


The Ugly:
     Persisting with the crapulence from C where a non zero integer is 
true and zero is false - only ever done because C lacked a boolean data 
type. This is a flagrant violation of PEP 20.2 "Explicit is better than 
implicit" and should be removed without providing backwards compatibility.



More information about the Python-ideas mailing list