Spot any errors? let me know, but Unleash your pedant politely please.

Tuesday 15 July 2014

PEP 20 > PEP 8

While trying to become a better Pythoneer, I'm struggling a little with PEP 8. I'm isolated, so I kind of don't care, but at some point I may have to learn to play well with others, so I should. I got a reminder of PEP 8 during a brief attempt to use PyCharm. I've only very briefly used an IDE with any success. That was with Eclipse and Java. That was only with help from people and online tutorials. PyCharm pointed out the myriad ways I was breaking PEP 8. It didn't tell me the ways I was conforming to PEP 20. Some code from PEP 8:
class Rectangle(Blob):

    def __init__(self, width, height,
                 color='black', emphasis=None, highlight=0):
        if (width == 0 and height == 0 and
                color == 'red' and emphasis == 'strong' or
                highlight > 100):
            raise ValueError("sorry, you lose")
        if width == 0 and height == 0 and (color == 'red' or
                                           emphasis is None):
            raise ValueError("I don't think so -- values are %s, %s" %
                             (width, height))
        Blob.__init__(self, width, height,
                      color, emphasis, highlight)
 
And this is how I'd probably write it:
class Rectangle(Blob):

    def __init__(self,
                 width,
                 height,
                 color     = 'black',
                 emphasis  = None,
                 highlight = 0):
                 
        if  0 == width == height \
        and color == 'red'       \
        and emphasis == 'strong' \
        or  highlight > 100:
            raise ValueError("sorry, you lose")

        if  0 == width == height \
        and (color == 'red' or emphasis is None):
            raise ValueError("I don't think so -- values are %s, %s" %
                             (width, height))

        Blob.__init__(self      = self,
                      width     = width,
                      height    = height,
                      color     = color,
                      emphasis  = emphasis,
                      highlight = highlight)
From PEP 20, my intention is to hit the following:
Beautiful is better than ugly. Explicit is better than implicit. Readability counts.
And from PEP 8, I'm playing the trump card:
When in doubt, use your best judgment.
Some preferences, like extra spaces here and there, are obviously subjective. Objectively, my experience of writing and maintaining code in Ada and Pascal tells me to always be explicit about using named actual parameters. It's probably even more important in a dynamically typed language. If Python didn't allow me to do this, I'd likely have rejected the language. That is has this feature in common with Ada and the indented scope of Occam (No braces, Yay!) made it a no-brainer for me. The main problem would appear to be that it's longer. Less code fits on-screen at once. I've never found that to be a problem even when I was editing in eve on VMS from a VT220. This wouldn't bother me much, even though I think it's less readable:
        Blob.__init__(self=self,
                      width=width,
                      height=height,
                      color=color,
                      emphasis=emphasis,
                      highlight=highlight)
But this drives me insane:
        Blob.__init__(self,
                      height,
                      width,
                      color,
                      emphasis,
                      highlight)
If you don't understand why, the deliberate mistake should be enough to persuade you that in the majority of cases, you really want to be be explicit about those parameter names. I'd only an the exception for functions that only take one parameter. Look, this is still fine even though the order deviated from the formal parameter list:
        Blob.__init__(self      = self,
                      height    = height,
                      width     = width,
                      color     = color,
                      emphasis  = emphasis,
                      highlight = highlight)
And this is impossible to do sober unless it's deliberate. It's also easy to spot in a review or when debugging:
        Blob.__init__(self      = self,
                      width     = height,
                      height    = width,
                      color     = color,
                      emphasis  = emphasis,
                      highlight = highlight)

Wednesday 9 July 2014

Idiotic Python

One of the problems of learning a programming language is that sometimes things one has written even relatively recently look idiotic.

Sometimes this is due to some bad advice on teh internets. Or perhaps misunderstanding an explanation.

I'd consider that I'm getting reasonably proficient in Python these days. I've had no formal teaching though, and I'm working in isolation, so I don't get feedback from colleagues or a mentor. I'm a lurker at the edge of the Python community.

I'm trying to improve.  I bought Writing Idiomatic Python by Jeff Knupp.  I read through it, skimming for things both do already and don't do/never knew about.  Things I already do were pat-on-the-back affirming, and I think confirmed I'm essentially on the right track.  The rest is a learning opportunity.

When there's a lull at work, which isn't often, I open the book, and pick something to check against in my current project. Yesterday I looked at Avoid comparing directly to True, False, or None and started searching for ==True==False==None; !=True; !=False; !=Nonethinking there'd be a few to fix.  I found far more than I though would be there.  Most disappointingly, quite a few !=False and ==True.

I fixed a lot of this.  Sometimes it seems less readable, so not in all places yet.

A significant penny dropped though, even though I've read this section a few times and nodded to myself as though I understood.  It's the use of is not None to check whether optional parameters have been set.  Sadly, my code is riddled with well meaning but potentially harmful attempts to check optional parameters.

Another penny is teetering on the edge.  In trying to go from harmful to idiomatic, I've made a significant number of minor changes. Some of these alter the order of an if statement to remove negation from the condition:
if not weekend:
    work()
else:
    relax()
if weekend:
    relax()
else:
    work()

None of the changes are difficult, but there's risk of human error here which will be very difficult to find without adequate unit tests.  I don't have unit tests.  I've certainly tested as I've developed, but those tests were transient, not part of a test suite.

In a quick search on Python unit testing, I stumbled across a nice little intro from Jeff Knupp (again).

Sigh. I fear that retro-fitting unit tests is going to expose some unpleasant coupling.


Saturday 5 July 2014

Football is the World Game

I'm not an Association Football fan. I much prefer Rugby football.

I used to play for fun/exercise in my 20s. Not to any standard, but enough to be able to appreciate the game a little.  I watch Match of The Day sometimes, and usually get sucked in to The World Cup, because the standard is usually pretty high.

In the Internet age, this means that every four years, I get exposed to Americans belittling soccer.

http://daringfireball.net/thetalkshow/2014/06/16/ep-085

The real reason for this is indoctrination in a sport other than football.  It's simply cultural bias. It's why I prefer Rugby, why Texans prefer Gridiron, why Canadians prefer Hockey, or the Swiss prefer Tennis.

It's important to understand that football is the world game.  I suspect it's popular for two reasons. The rules are really pretty simple, so it can be grasped easily. The only equipment needed is a field, or a street or a car park; a football, volleyball, tennis ball, tin can, or even a stone. And, of course, jumpers for goalposts.  It's a game all almost all children, all over the world can play for free.  In unsupervised children's games, the only vaguely complex rule, offside, is discarded in favour of simply ridiculing goal-hangers.  Offside is enforced by peer pressure.

A common theme in disparaging football is that the one thing that separates us from animals is our hands, and hands aren't allowed.  I find this puzzling. The main thing that separates us from animals is our brains.  Other animals have hands, can use tools, are bipedal etc.  None can understand and play football.

I'd add something about baseball fielders needing catchers' mitts, which seems laughable to someone who's played cricket, but that would just be wallowing in the ignorance of my own cultural bias.

I switched from Markdown Pro to Macdown

The main reason: Unlike MarkDown Pro,  syntax highlighting is built in to MacDown .

MacDown is also free, although I'm perfectly happy to pay for good software I find useful.

The markup for code in MacDown is very simple:



This is a lazy stop-gap. I ought to be generating documentation from embedded docstrings automatically …but that's for another day.