[Tutor] Anti-Patterns in Python Programming

Steven D'Aprano steve at pearwood.info
Sat Jul 12 20:14:26 CEST 2014


Hi Deb,

My answers are interleaved with your questions.



On Sat, Jul 12, 2014 at 08:43:30AM -0800, Deb Wyatt wrote:

> Some questions I have at the moment:
> 
> 1.  What is functional programming?
> 2.  What is procedural programming?
> 3.  What are data patterns?
> 4.  What are regular expression?

Good questions!

Here are some *very* simplified answers, but enough to give you a 
flavour of the answer.


1. Functional programming is based on the ideas that programming should 
(as much as possible) be like mathematics. Everything should be written 
as functions which avoid keeping state and don't have side-effects.

"State" refers to keeping values in a variable of some sort. The most 
obvious example is a global variable. Consider this simplified example:

    def say_hello():
        print "Hello, %s" % name

    name = "Steve"
    say_hello()  # prints "Hello, Steve"
    name = "Deb"
    say_hello()  # prints "Hello, Deb"


Functional programming avoids the global variable and prefers to write 
the say_hello function like this:

    def say_hello(name):
        print "Hello, %s" % name

    say_hello("Steve")  # prints "Hello, Steve"
    say_hello("Deb")  # prints "Hello, Deb"


"Side-effects" refers to functions having any effect other than 
returning a result. Now obviously having *absolutely* no side-effects at 
all would be pointless, since we normally want to print the result (a 
side-effect!), save it in a file, turn on some machinery, or whatever 
the actual purpose of the program happens to be. But *internal* 
side-effects are considered to be a bad idea. Here's the kind of thing I 
mean:

    data = [4, 2, 1, 0, 5, 3]
    data.sort()  # has a side-effect
    print data == [4, 2, 1, 0, 5, 3]  # prints False, data has changed

The sort method has had a side-effect. Instead of returning a new list 
with the sorted values, it changes the existing list. A more functional 
way of writing this would be:

    data = [4, 2, 1, 0, 5, 3]
    sorted(data)  # returns a new list
    print data == [4, 2, 1, 0, 5, 3]  # prints True


It's hard to do justice to the reasons why functional programming makes 
the choices it does in just a few words, especially at 3:30am local 
time, but at least you should now have an idea of what F.P. is.



2.  What is procedural programming?

If you cast your mind back to the 1970s and 80s when people used to 
write BASIC code like this:

10 REM I can't remember BASIC commands, so I'm going to make them up
20 X = 0
30 IF X < 10
40 PRINT X
45 X = X + 1
50 ELSE
60 GOTO 30

you might remember that this style of programming was often 
characterised as "spaghetti code", because trying to follow the program 
flow through all the GOTOs was like trying to follow a strand of 
tangled up spaghetti. 

Procedural programming is the opposite of this. Instead of having one 
giant undifferentiated lump of code where you have to try to follow it 
from the first line to the last as one giant strand of spaghetti, and 
where everything belongs to a single shared environment, the code is 
divided up into small parcels of independent code, called "procedures", 
"functions" or "sub-routines".

Unlike a chunk of BASIC code, where you could jump into the middle of it 
with a GOTO, the important thing about a procedure is that it has only a 
single entry-point: you can only start the procedure from the beginning, 
and work its way to the end, where it then automatically returns to the 
code that called it.

The other important thing about procedures is that they can have local 
variables. Consider these two procedures:

    # not Python code, just some pseudo-code I made up
    procedure do_this:
        set x = 1
        print x

   procedure do_that:
       set x = 2
       do_this()
       print x


If you called do_that(), it would print "1 2", *not* "1 1". The reason 
is that the x inside "do_this" is local to that procedure, so it doesn't 
change the x inside "do_that". What happens inside a procedure is 
isolated from the insides of other procedures.


3.  What are data patterns?

I have no idea :-)


4.  What are regular expression?

Regular expressions are a kind of mini-programming language used for 
matching patterns in text. In the regular expression, certain special 
characters have special meanings. For example:

    A      just means the letter "A"
    A*     means "any number of the letter A (including zero)", 
           e.g. A, AA, AAA, ...
    A+     means "at least one letter A" (like A* but excludes zero)
    .      means "any character at all"
    .*     means "any number of any character"
    B?     means "zero or one of the letter B"
    A|B    means "A or B"


and so on. By using regular expressions, you can search text for 
alternatives, without having to list out every single possible 
substring. A concrete example: suppose I wanted to extract out a number 
from a string. I could say:

    search for 0
    search for 1
    search for 2
    ...
    search for 1234567
    search for 1234568
    search for 1234569
    search for 1234570
    ...

but it would get pretty tedious after a while, right? Here's how I can 
do it simply with a regular expression:

py> import re
py> pattern = r'\d+'  # one or more digits
py> mo = re.search(pattern, "The number today is 924736, okay?")
py> mo.group()
'924736'



> I worked for a private company for a while where I was the only 
> programmer, then I worked for the Commonwealth of Kentucky, and then 
> University of Washington, where I created and maintained database 
> applications. I never heard of any of those things prior to the past 
> few months since I started dipping my toes back in (more like total 
> immersion, jeeze).  So maybe all this stuff has been around but I sure 
> never heard of it.

What language or languages did you program with?


> Almost every time I post a question on here, I get my hand slapped by 
> someone, and the favorite thing for you all to say to newbies is "read 
> the tutorial." 

Ouch! Well, you certainly shouldn't be getting slapped for asking 
questions. Sorry about that.

Yes, reading the tutorial is important, and we've had plenty of people 
here who don't make even the *tiniest* effort to learn on their own. But 
if you make the effort, we should do the same.


> The tutorial is over our heads in a lot of cases 
> because of the jargon, at least at first.  And so many times things 
> are explained with C++ as an example.
> 
> My favorite useless thing I have run across on the internet is 
> the answer to what does hashable mean?  From stack overflow:
> 
> "An object is hashable if it has a hash value which never changes 
> during its lifetime (it needs a __hash__() method), and can be 
> compared to other objects (it needs an __eq__() or __cmp__() 
> method). Hashable objects which compare equal must have the same 
> hash value."
> 
> what is a hash value?  What's a _hash_() method (or any of those 
> other methods)?  

You know hash browns? You take a potato, and grate it, mix it up, 
and then cook it. In programming, "hashing" does the same thing: take 
some data, slice it, dice it, grate it, mix it all together, and turn it 
into a single number. An example:

py> hash("Hello!")
-1940210404
py> hash("hello!")
853481916


Notice that changing just one letter *completely* changes the hash value 
that we get out. The hash function takes the string, separates it into 
all the individual pieces ("H", "e", ...), mixes them up, and combines 
them into a single value, a number. If you change just one of those 
pieces, by the time it's all mixed together and combined again you get 
something very different.

Why on earth would anyone need such a thing? Well, that's complicated, 
but the short answer is, hashes are used for dictionaries.

What's __hash__? Like all Double leading and trailing UNDERscore 
("dunder") names, __hash__ is used by Python. When you write your own 
classes, if you ever do (it's not compulsory), if you need to control 
how Python calculates the hash of your objects, you write a __hash__ 
method to do so. But normally you wouldn't worry about it. In 15 years 
of Python programming, I don't think I have even once written my own 
__hash__ method.


> You all take this understanding for granted, but it's not common 
> knowledge for the rest of the world. I bet if I talked knitting 
> and fiber jargon you all wouldn't understand much of what I was 
> talking about lol.

:-)




-- 
Steven


More information about the Tutor mailing list