Re: Python is readable

Discussion in 'Python' started by Chris Angelico, Mar 15, 2012.

  1. On Thu, Mar 15, 2012 at 10:54 AM, Arnaud Delobelle <> wrote:
    > I don't know this book and there may be a pedagogical reason for the
    > implementation you quote, but pairwise_sum is probably better
    > implemented in Python 3.X as:
    >
    > def pairwise_sum(list1, list2):
    >    return [x1 + x2 for x1, x2 in zip(list1, list2)]


    Okay, here's something for debate.

    Should the readability of a language be gauged on the basis of its
    standard library, or should you be comparing actual code?

    For instance, a quine in C can be fairly complex and messy, and it can
    be unobvious what it's doing - but in HQ9+ it's easy. Is it fair to
    compare on that basis, or should you actually implement the same /
    equivalent code in each before judging?

    Of course, that's all without getting into the question of what does
    "readable" even mean. This has nothing to do with the eternal question
    of whether it's more readable to use verbose English keywords or
    cryptic symbols.

    ChrisA
     
    Chris Angelico, Mar 15, 2012
    #1
    1. Advertising

  2. Chris Angelico

    Rick Johnson Guest

    On Mar 14, 7:27 pm, Chris Angelico <> wrote:
    > Okay, here's something for debate.
    >
    > Should the readability of a language be gauged on the basis of its
    > standard library, or should you be comparing actual code?


    I think the library matters greatly. Yes, one could argue that the
    same functionality "could" be wrapped-up in the competing language,
    but then, why has it not already been wrapped?

    When comparing say, "language A" (WITHOUT a built-in print function)
    and "Language B" (WITH a built-in print function), would you cry
    unfairness when B wielded the built-in?

    > [...]
    > Of course, that's all without getting into the question of what does
    > "readable" even mean.


    One could get caught in an infinite loop of the "Chicken and the Egg"
    paradox here. However, when we are talking about the Python
    programming language "readable" simply means: "neophyte readable".
    That is, "readable to someone with little or no experience with the
    language". I think that has always been Python's philosophy from the
    beginning (even all the way back to CP4E!).

    > This has nothing to do with the eternal question
    > of whether it's more readable to use verbose English keywords or
    > cryptic symbols.


    Again, for the case of Python, cryptic symbols are frowned upon. Of
    course for the "hacker", cryptic symbols can save keystrokes and white
    space -- but at the expense of "neophyte readability"!

    > ChrisA


    Thanks for reminding me of your name. I had almost forgotten who i
    replied to ;-)
     
    Rick Johnson, Mar 15, 2012
    #2
    1. Advertising

  3. Chris Angelico

    alex23 Guest

    Rick Johnson <> wrote:
    > However, when we are talking about the Python
    > programming language "readable" simply means: "neophyte readable".
    > That is, "readable to someone with little or no experience with the
    > language".


    Nonsense. List comprehensions are not immediately obvious to new
    Python users. The functionality of 'with' requires an understanding of
    context managers. Python's readability has more to do with simplifying
    code maintenance.

    The idea that Python code has to be obvious to non-programmers is an
    incorrect and dangerous one.
     
    alex23, Mar 15, 2012
    #3
  4. On Thu, Mar 15, 2012 at 9:44 PM, Kiuhnm
    <> wrote:
    > Let's try that.
    > Show me an example of "list comprehensions" and "with" (whatever they are).


    I'll do a list comp, because they lend themselves well to one-liners.
    what_am_i = '\n'.join(["%X\t%c"%(i,i) for i in range(128)])

    Okay, that one also uses printf formatting, which may be a smidge
    obscure. Here's a simpler example:

    what_am_i = [x*x for x in range(11)]

    ChrisA
     
    Chris Angelico, Mar 15, 2012
    #4
  5. Am 15.03.2012 11:44 schrieb Kiuhnm:

    > Let's try that.
    > Show me an example of "list comprehensions" and "with" (whatever they are).


    with open("filename", "w") as f:
    f.write(stuff)


    with lock:
    do_something_exclusively()


    Thomas
     
    Thomas Rachel, Mar 15, 2012
    #5
  6. On Thu, Mar 15, 2012 at 10:27 PM, Kiuhnm
    <> wrote:
    > On 3/15/2012 11:50, Chris Angelico wrote:
    >> I'll do a list comp, because they lend themselves well to one-liners.
    >> what_am_i = '\n'.join(["%X\t%c"%(i,i) for i in range(128)])

    >
    >
    > A few conjectures:
    > 1) '\n' is an object and join one of its methods;
    > 2) [...] is a list comprehension;
    > 3) that 'for' suggests that range isn't (or doesn't return) a list but an
    > iterator;
    > 4) points 2 and 3 suggest that [...] builds a list (or array?) by querying
    > an iterator.
    > 5) "%X\t%"(i,i) is probably equivalent to the C-like Perl's
    >  sprintf("%X\t%c", i, i)
    >
    > So what_am_i is a simple ASCII table.


    Correct. Actually, there's a few differences between Python 2 and 3;
    in Py2, range() returns a list, but in Py3 an iterable object. But
    'for' will happily iterate over a list.

    >> Okay, that one also uses printf formatting, which may be a smidge
    >> obscure. Here's a simpler example:
    >>
    >> what_am_i = [x*x for x in range(11)]

    >
    > what_am_i = 0, 1, 4, 9, ..., 100


    Correct again.

    > Your first example suggests that range(n) is a sequence iterator which
    > returns, if queried n times,
    >  0,...,n-1
    > (which is a bit counterintuitive, IMHO).


    It's a little odd, perhaps, if seen in a vacuum. But everything counts
    from zero - list indices, etc - so it makes sense for range(len(lst))
    to return indices valid for lst.

    List comps are pretty readable if you know how programming languages
    work. Python need not be readable by everyone and his grandmother, and
    it does a fairly good job of being grokkable to someone who has a few
    ranks in Coding. (Yeah, I'm a D&D nerd. )

    ChrisA
     
    Chris Angelico, Mar 15, 2012
    #6
  7. On Thu, Mar 15, 2012 at 10:59 PM, Kiuhnm
    <> wrote:
    > On 3/15/2012 12:47, Chris Angelico wrote:
    >> It's a little odd, perhaps, if seen in a vacuum. But everything counts
    >> from zero - list indices, etc - so it makes sense for range(len(lst))
    >> to return indices valid for lst.

    >
    > Maybe range uses [...) intervals? So range(a,b) is a,a+1,a+2,...,b-1 and
    > range(b) is just short-hand for range(0,b)?


    Yup. It's amazing how accurate your conjectures are - it's almost like
    you've been reading the docs! :D But yeah, that's pretty logical IMHO;
    and having gotten used to [) intervals in many areas of computing,
    I've come to find [] intervals disconcerting. Bible passages are
    described as, for instance, John 14:5-7, which is a three-verse
    passage (5, 6, 7), even though 7-5=2.

    However, inclusive-inclusive intervals have the benefit that they
    don't require the element "beyond the last" to be indexable. This is
    important if you're working with something that takes up all of
    addressable memory - going back to the IBM PCs on which I learned to
    code, you could use one 64KB segment for an array, but then there's no
    way for a 16-bit integer to indicate "past the end".

    >> List comps are pretty readable if you know how programming languages
    >> work. Python need not be readable by everyone and his grandmother, and
    >> it does a fairly good job of being grokkable to someone who has a few
    >> ranks in Coding. (Yeah, I'm a D&D nerd. )

    >
    > I like what I've seen so far.


    Python has its problems, but it's a good language. I personally prefer
    to delimit blocks of code with braces than with indentation, and I
    also prefer explicit declaration of variables (yes, it's extra work,
    but you can have infinitely nested scopes and easily-caught syntax
    errors when you misspell one), but they're relatively minor. One of my
    favorite aspects of Python is that *everything* is an object. There's
    no magic syntax that gives you a piece of an object, or something
    special about variables that contain this, that, or the other. A
    literal list [like, this, one] can be used in exactly the same ways as
    the name of a variable containing a list or a function call returning
    a list - there is no difference. Oh how I yearn for that when working
    in C++ or PHP!

    ChrisA
     
    Chris Angelico, Mar 15, 2012
    #7
  8. On Fri, Mar 16, 2012 at 12:16 AM, Ben Finney <> wrote:
    > Chris Angelico <> writes:
    >
    >> On Thu, Mar 15, 2012 at 11:31 PM, Ben Finney <> wrote:
    >> > Another good reason to advocate for proper typography. "John 14:5-7"
    >> > indicates a range (because it uses U+2013 EN DASH), whereas "7-5"
    >> > indicates subtraction (because it uses U+2212 MINUS SIGN). A hyphen
    >> > ('-' U+002D) is inappropriate in either case.

    >>
    >> Heh. Yes, but when you're seeking the size of a range, you use
    >> subtraction.

    >
    > Not the size of an *inclusive* range, such as a range indicated by use
    > of an en dash :)


    Yes you do, you just have to add one to it. You still use subtraction. :)

    >> The fact that the en dash and minus sign are both often represented in
    >> ASCII with a hyphen is pure coincidence.

    >
    > Hopefully, the fact that your quoting of my text munged the characters
    > down to ASCII is also pure coincidence, and is soon to be corrected at
    > your end? Or has your client program not joined the rest of us in the
    > third millennium with Unicode?


    It's gmail, and I don't know why it folded everything down. I've told
    it to cast everything to text (to avoid the stupid look you sometimes
    get with nested replies to HTML-formatted emails), and I guess it
    decided to go ASCII. Your mail displayed just fine, it was something
    in the reply mechanism.

    ChrisA
     
    Chris Angelico, Mar 15, 2012
    #8
  9. On 15/03/2012 11:48, Kiuhnm wrote:
    > On 3/15/2012 12:14, Thomas Rachel wrote:
    >> Am 15.03.2012 11:44 schrieb Kiuhnm:
    >>
    >>> Let's try that.
    >>> Show me an example of "list comprehensions" and "with" (whatever they
    >>> are).

    >>
    >> with open("filename", "w") as f:
    >> f.write(stuff)

    >
    > Here f is created before executing the block and destroyed right after
    > leaving the block. f's destructor will probably close the file handle.
    >
    >> with lock:
    >> do_something_exclusively()

    >
    > It's clear what it does, but I don't know if that's special syntax.
    > Maybe objects can have two special methods that are called respect. on
    > entering and leaving the with-block.
    > Or, more likely, lock creates an object which keeps the lock "acquired".
    > The lock is released when we leave the block.
    > So we could inspect the lock with
    > with lock as l:
    > inspect l...
    > do_some.....
    >
    > BTW, aren't those ':' redundant?
    >
    > Kiuhnm


    Nope.

    Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit
    (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> with open("filename", "w") as f

    File "<stdin>", line 1
    with open("filename", "w") as f
    ^
    SyntaxError: invalid syntax

    --
    Cheers.

    Mark Lawrence.
     
    Mark Lawrence, Mar 15, 2012
    #9
  10. Chris Angelico

    Alec Taylor Guest

    On Fri, Mar 16, 2012 at 1:06 AM, Mark Lawrence <> wrote:
    > Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)]on
    > win32
    > Type "help", "copyright", "credits" or "license" for more information.
    >
    >>>> with open("filename", "w") as f

    >  File "<stdin>", line 1
    >
    >    with open("filename", "w") as f
    >                                  ^
    > SyntaxError: invalid syntax
    >
    > --
    > Cheers.
    >
    > Mark Lawrence.
    >


    Erred for me also; but under f:

    Python 2.7.3rc1 (default, Feb 24 2012, 21:28:59) [MSC v.1500 64 bit
    (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> with open("filename", "w") as f

    File "<stdin>", line 1
    with open("filename", "w") as f
    ^
    SyntaxError: invalid syntax
     
    Alec Taylor, Mar 15, 2012
    #10
  11. Chris Angelico

    Tim Golden Guest

    On 15/03/2012 14:19, Kiuhnm wrote:
    > On 3/15/2012 15:06, Mark Lawrence wrote:
    >> On 15/03/2012 11:48, Kiuhnm wrote:
    >>> BTW, aren't those ':' redundant?
    >>>
    >>> Kiuhnm

    >>
    >> Nope.
    >>
    >> Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit
    >> (Intel)] on win32
    >> Type "help", "copyright", "credits" or "license" for more information.
    >> >>> with open("filename", "w") as f

    >> File "<stdin>", line 1
    >> with open("filename", "w") as f
    >> ^
    >> SyntaxError: invalid syntax

    >
    > Ok, so they're mandatory, but I was mainly talking of design. Why are
    > they needed?
    >
    > Kiuhnm


    http://docs.python.org/faq/design.html#why-are-colons-required-for-the-if-while-def-class-statements

    TJG
     
    Tim Golden, Mar 15, 2012
    #11
  12. On Fri, Mar 16, 2012 at 1:16 AM, Kiuhnm
    <> wrote:
    > Don't worry. Soon you'll be using C++0x :)))


    I use gcc/g++ with most of the new features enabled. There's some
    pretty handy features in it. Frankly, though, if I'd known about
    Cython when I started the current project, I would have argued to
    write it all in Python and Cify (is that a word?) the most
    performance-critical sections afterwards, instead of writing it in
    C++. It'd be a lot of hassle to change it now, but if anyone else is
    looking at writing a large project in C "for performance", I would
    strongly recommend writing in Python or Pike first. (Some day, I'm
    going to have to actually try Cython. But I know enough of
    embedding/extending Python to know that the technique would definitely
    be viable, and Cython can only make it easier.)

    ChrisA
     
    Chris Angelico, Mar 15, 2012
    #12
  13. Chris Angelico

    Robert Kern Guest

    On 3/15/12 2:30 PM, Kiuhnm wrote:
    > On 3/15/2012 15:23, Duncan Booth wrote:
    >> Kiuhnm<kiuhnm03.4t.yahoo.it> wrote:
    >>
    >>> BTW, aren't those ':' redundant?
    >>>

    >>
    >> They are required by the grammar, but in a sense you are correct. You could
    >> modify Python's grammar to make the colons optional and still keep it
    >> unambiguous but that would make it harder for other tools (such as text
    >> editors or indeed humans) to understand.

    >
    > Sorry, but I can't see how it would make it harder for humans to understand. Are
    > there particular situations you're referring to?


    There were usability studies done on one of Python's indentation-based
    ancestors, ABC. Those studies found, empirically, that having the colons helped
    people read and understand the code faster.

    --
    Robert Kern

    "I have come to believe that the whole world is an enigma, a harmless enigma
    that is made terrible by our own mad attempt to interpret it as though it had
    an underlying truth."
    -- Umberto Eco
     
    Robert Kern, Mar 15, 2012
    #13
  14. On Fri, Mar 16, 2012 at 1:30 AM, Kiuhnm
    <> wrote:
    > Sorry, but I can't see how it would make it harder for humans to understand.
    > Are there particular situations you're referring to?


    In a trivial example, it's mostly just noise:

    if a == b # who needs the colon?
    print(c)

    But when your condition is more complicated, it's cleaner to
    explicitly mark the end of the condition. Also, Python allows you to
    put a simple body on the same line as the if, which is very handy:

    if a == b: print(c)

    Without the colon, this would be awkward to parse. And the bash style
    of using actual statement separators feels really weird, although it
    does mean that the newline is truly optional.

    ChrisA
     
    Chris Angelico, Mar 15, 2012
    #14
  15. On Fri, Mar 16, 2012 at 1:55 AM, Kiuhnm
    <> wrote:
    > By the way, the more elaborate parsing consists of looking for an
    > END_OF_LINE followed by one or more spaces. It doesn't sound that
    > complicated.


    Only in the trivial case. What if you want to break your condition
    over multiple lines? (Although you have to parenthesize or backslash,
    so that's still unambig.) It's helpful to be explicit.

    > And what about an editor which indent when you press the spacebar or tab?


    Sure, but a good editor helps out by noticing that you did something
    that begs for indentation. If I put an open brace, SciTE will indent -
    very simple rule. With Python, if there were no colon markers, it
    would be quite complicated to figure out whether or not to indent;
    with the colons, it's simply "if/while/etc" followed by text followed
    by colon, and then no further non-comment text. (This sounds involved.
    It's not. It's right enough. -- Lady Blanche)

    ChrisA
     
    Chris Angelico, Mar 15, 2012
    #15
  16. Chris Angelico

    Robert Kern Guest

    On 3/15/12 2:55 PM, Kiuhnm wrote:
    > On 3/15/2012 15:28, Tim Golden wrote:


    >> http://docs.python.org/faq/design.html#why-are-colons-required-for-the-if-while-def-class-statements

    >
    > The second one is slightly easier to read because it's syntax-highlighted. Was
    > that on purpose?


    No, it's an unintended side effect. The (automated) syntax highlighting was
    added to the FAQ much, much later than that entry was written. The syntax
    highlighting tool does not recognize the first example as Python, so it does not
    apply Python syntax highlighting to it.

    --
    Robert Kern

    "I have come to believe that the whole world is an enigma, a harmless enigma
    that is made terrible by our own mad attempt to interpret it as though it had
    an underlying truth."
    -- Umberto Eco
     
    Robert Kern, Mar 15, 2012
    #16
  17. Chris Angelico

    Roy Smith Guest

    In article <>,
    Chris Angelico <> wrote:

    > I use gcc/g++ with most of the new features enabled. There's some
    > pretty handy features in it. Frankly, though, if I'd known about
    > Cython when I started the current project, I would have argued to
    > write it all in Python and Cify (is that a word?) the most
    > performance-critical sections afterwards, instead of writing it in
    > C++.


    +1.

    With the exception of the client-side javascript, virtually 100% of the
    application code behind songza.com is python. We use django, tornado,
    and gunicorn (all pure python). The ORM layer (mongoengine) is pure
    python. Of course, there's plenty of C/C++ code in the database
    (MongoDB), HTTP proxies (nginx and haproxy), and search engine (Xapian),
    but the core application code is all python. About 80,000 lines worth.

    Every time we look at performance, we discover the same thing. The time
    spent running python code is insignificant. It's all about network I/O
    and database queries. The only time we ever see any significant time
    running python code is when we do something stupid and write some O(n^2)
    code that can be replaced by a more appropriate algorithm.

    While it's nice to know that we've got the ability to write extensions
    in C, not once have we ever felt the need. I suppose if you're running
    a CPU-bound application, that might not be the case, but surprisingly
    few applications really are compute bound these days.

    I had an interesting experience the other day. We had a job applicant
    implement one of our coding tests in Java. It's a data mining exercise
    where you need to generate some summary statistics from a 700,000 line
    log file we give you. My Python version takes under a second. His Java
    version came up with the right numbers but took 2 minutes. I looked at
    his code and didn't any any obvious problem. It turned out he used a
    regex that started with '.*', and apparently the Java regex library
    implements that badly. Eliminating the leading '.*' got his Java
    running in the same time as my Python.
     
    Roy Smith, Mar 15, 2012
    #17
  18. On Fri, Mar 16, 2012 at 2:05 AM, Kiuhnm
    <> wrote:
    > I had thought about the single-line case. What I hadn't thought about is
    > that Python strives to be as regular as possible, so having different cases
    > just for saving one keystroke isn't worth it.


    Yep. Have you read the Zen of Python?

    >>> import this

    (trimmed for brevity)
    Explicit is better than implicit.
    Readability counts.
    Special cases aren't special enough to break the rules.
    Although practicality beats purity.
    In the face of ambiguity, refuse the temptation to guess.

    Omitting the colon is definitely a not-special-enough case.

    ChrisA
     
    Chris Angelico, Mar 15, 2012
    #18
  19. On Fri, Mar 16, 2012 at 2:14 AM, Roy Smith <> wrote:
    > While it's nice to know that we've got the ability to write extensions
    > in C, not once have we ever felt the need.  I suppose if you're running
    > a CPU-bound application, that might not be the case, but surprisingly
    > few applications really are compute bound these days.


    My boss and I have these discussions now and then. A topic of
    performance comes up, and we debate whether or not, for instance, it's
    worth doing a separate check of an input file to see if it's
    properly-formed UTF-8 before parsing it (this is in PHP, or it'd be
    easy - just do a UTF-8 decode and work with Unicode). The debate
    ended, as they inevitably do, with "We're talking about a file that
    someone's uploaded to us, so it won't matter". Whatever processing we
    do is massively dwarfed by network time, and both scale linearly with
    the size of the file.

    ChrisA
     
    Chris Angelico, Mar 15, 2012
    #19
  20. Am 15.03.2012 12:48 schrieb Kiuhnm:
    > On 3/15/2012 12:14, Thomas Rachel wrote:
    >> Am 15.03.2012 11:44 schrieb Kiuhnm:
    >>
    >>> Let's try that.
    >>> Show me an example of "list comprehensions" and "with" (whatever they
    >>> are).

    >>
    >> with open("filename", "w") as f:
    >> f.write(stuff)

    >
    > Here f is created before executing the block and destroyed right after
    > leaving the block. f's destructor will probably close the file handle.


    No, that is the point here: with calls __enter__ on entry and __exit__
    on, well, exit.

    In the case of files, __enter__ doesn't probably do anything special,
    but returns the object again in order to be assigned to f. In __exit__,
    the file is closed.

    with open("/tmp/filename", "w") as f:
    print f
    print f

    <open file '/tmp/filename', mode 'w' at 0xb74e6d30>
    <closed file '/tmp/filename', mode 'w' at 0xb74e6d30>

    So after the with clause, f is actually closed, but still present as object.

    >> with lock:
    >> do_something_exclusively()


    > It's clear what it does, but I don't know if that's special syntax.


    If you call "with" special syntax, it is.

    > Maybe objects can have two special methods that are called respect. on
    > entering and leaving the with-block.


    Exactly, see above.

    Here, on entry __enter__ is called which acquires the lock.
    __exit__ releases it again.


    > Or, more likely, lock creates an object which keeps the lock "acquired".
    > The lock is released when we leave the block.
    > So we could inspect the lock with
    > with lock as l:
    > inspect l...
    > do_some.....


    Or just inspect l - I don't know if a lock's __enter__ methos returns it
    again for assignment with "as"...


    Thomas
     
    Thomas Rachel, Mar 15, 2012
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Troll
    Replies:
    4
    Views:
    378
    Irene Mettias
    Sep 23, 2003
  2. Steven D'Aprano

    Re: Python is readable

    Steven D'Aprano, Mar 16, 2012, in forum: Python
    Replies:
    3
    Views:
    342
    Prasad, Ramit
    Mar 16, 2012
  3. Chris Angelico
    Replies:
    15
    Views:
    273
    Dave Angel
    Mar 24, 2012
  4. Chris Angelico
    Replies:
    4
    Views:
    263
    Chris Angelico
    Apr 3, 2012
  5. Nathan Rice
    Replies:
    30
    Views:
    727
    Steve Howell
    Apr 4, 2012
Loading...

Share This Page