Python - Cheat Sheet
Beginning - Intermediate - Expert
As much as anything, this is a place to jot down reminders to myself. But with any luck, others may find it useful, as well.
Beginning Python
Anaconda
Anaconda is the best Python distribution available. It comes pre-packaged with loads of useful libraries: Numpy, Skimage, the SciPy stack, and beautifulSoup to name just a few. I cannot begin to say how much time this has saved me.
sys.path.append
If I don't feel like installing a package into the Python path on my computer, I use the following code that serves much of the same purpose.
import sys
sys.path.append("C://path/to/your/imported/code/module.py")
import module
Eclipse with PyDev
IDE's make or break a language. I'm not going to learn Lisp anytime soon in large part because I am not going to struggle with learning Emacs any time soon. Same for Scheme and the Racket interface. I would love to crank out some test programs, but it's not worth the struggle. And seriously, why struggle when Eclipse with PyDev is around? Eclipse with PyDev a joy. Better than Idle, Ninja, or any of the other IDE's I've tried. Once I loaded Eclipse, I never looked back.
Exporting.py
From eclipse exporting a simple one file Python program is as simple as copying and pasting the appropriate file. So, if a file is designed to work on all files in it's current directory, it can be dropped down anywhere in my file system and double clicked and it will work it's magic on those files. (Individual results may vary... as with all these tricks).
str.join(iterable)
I don't expect to have much to say on the majority of basic programming syntax. This isn't an exhaustive primer. But I found it difficult to remember the syntax for "x".join(myList)
until I noticed it was lumped in with the string methods. "x".join(myList)
operates on the string "x" inserting it between every element of myList and then returning the result as a new string. So in actuality, it's a string method that has a List (or other iterable) as a parameter. Hope that clears things up.
Basid Code Design
A few guidelines a beginning programmer might find useful in evaluating whether the code they are writing is any good.
Shorter is Better
I just got done refactoring a program. By using a prebuilt library method, I was able to cut about 25 lines from my program. I don't need anyone else to review my code to know the shorter snippet of code is better.
Use Existing Libraries
I use Python because C, Fortran, Cobalt and a whole slew of others are beyond me. Luckily, they are not beyond others, who in many cases have written a Python program doing whatever it is that Fortran is good at. Find those libraries. Use those libraries.
Lock State
I do a lot of photo manipulation work. My average project is either a text-text, text-image (via matplotlib.pyplot as plt
), or an image-image program. And I tend to organize my average photo project as follows:
from skimage import io
img = io.imread(fileNameIn)
img = firstFunction(img)
img = secondFuction(img)
io.imsave(midSaveFileName, img)
img = io.imread(midSaveFileName)
img = almostDoneFunction(img)
img = finalFuction(img)
io.imsave(outFileName, img)
I find it easier to think in the smaller code chunks that this entails. I can work incrementally. And debugging is easier as I have multiple images files to review to see what's what. But perhaps more important than all that, I can count on the state of the img
variable. I know what img
looks like right after io.read(imageName)
. It's always the same. It never varies. And I've got a feeling saving often smooths out a lot of bugs (errors, inconsistencies) that would otherwise get telegraphed down through the code and enlarged (randomly) at some future point if I stuck with something more functional (such as this):
from skimage import io
img = io.imread(fileNameIn)
img = firstFunction(img)
img = secondFuction(img)
#this is where the save/load would have gone
img = almostDoneFunction(img)
img = finalFuction(img)
io.imsave(outFileName, img)
So, maybe this is another way of saying that code that is easy to debug is a side-effect that should be embraced.
And I do believe I shall call that a wrap on the basic stuff.
Intermediate Python
String Formatting
This is all I ever needed to know about formatting strings using the interpolation operator(%).
s1 = "S1 prints in the first position. "
s2 = "S2 prints in the second."
print "%s %s." % (s1, s2)
>>>S1 prints in the first position. S2 prints in the second.
I find String Formatting to be a godsend when it comes to printing out trouble shooting feedback.
print "%s imageFile\t %s shape \t %d Size \ for debugging %r" % (imageFileName, str(img.shape), img.size, img)
>>>imageFileName.png imageFile (800,800,3) shape 265560,000 size for debugging [[0,0,1,1....
%s is for strings
%f is for floating point numbers
%d is for decimal (integer) numbers (Note: this will truncate a float)
%r is for objects (implicitly calls repr(object)
)
Finally, for tuples preformat the tuple as a string and call it as a string:
myTuple = (450,600)
print "myTuple's current value is %s." % str(myTuple)
>>>myTuple's current value is (450,600).
Functions
This advice is, of course, based upon my own weaknesses.
Document The Function
The proper way to document a function (IMHO) is:
def myFunction(pV):
'''pV is a text string
text string is converted to upper, lower, then upper
returning fully converted text string
'''
pV = pV.upper()
pV = pV.lower() #TODO refactor
pV = pV.upper()
return pV
There are two comments above, so I will make two here. The first area below the function definition is the big bad boy of comment space in which one should: summarize what the function does, the values expected, and the values returned. In the body, use # to make short comments for clarity. And finally (guess I lied on that two comment thing, I'm a wordy type guy by nature), I use the keyword TODO for anything and everything I intend to fix later, so as I'm coding a keyword search for 'TODO' will take me where I need to be. And if that keyword search comes up empty, maybe I'm done?
Ah, who am I kidding? I'm never done...
One Effect Per Function
I tend to lump multiple effects together into a single function. This is a mistake. Whenever I'm stargting my second loop in a function, I should just stop, refactor, and break out whatever I am planning on doing with that second loop in a separate function; that, or I'm going to be rewriting the same code from scratch the next time I need to use something like it. Thus, even though I recommend solidifying state by saving to disc and then reloading the data (I am not Google, my computer sits idle most of the time, performance does not concern me), in theory I should be able to string my functions from end to end, load once at the beginning, and save once at the end.
#Good Clean Functions
def functionTheFirst(dataTypeX):
x = doesOneThingWellTo(dataTypeX)
return x
def functionThe Second(dataTypeY):
y = doesAnotherThingWellTo(dataTypeY)
return y
Keep Parameters Clean
The following code snippet is NOT clean and to be AVOIDED. Like many things on this page it is perhaps a note to myself more than anyone else. Your applications are different than mine. But if a function looks like this for me, it's a sure sign I'll never use it again and will wind up coding from scratch the next time I have a similar project.
def imageTransform(imageFileLocation, cS="gb", size=500x500, alpha=True):
'''This is a crappy function
It does way too many things
The input type does not match the output
(filename in, img(object) out
The comments provide no clue as to it's use
(how meta is that?)
Nor are the parameters explained
'''
img = io.imread(imageFileLocation)
img = img.resize(size)
cS = cS.lower()
if "r" in cS:
img = colorFuction("red")
if "g" in cS:
img = colorFuction("green")
if "b" in cS:
img = colorFuction("blue")
if alpha:
img = alphaFunction(True)
else:
img = alphaFunction(False)
return img
Of course, some code in any project will be project specific, but that doesn't mean it has to be ugly. The following code is both project specific and clean.
def imageTransform(imageIn, imageOut=imageIn):
'''Performs a cool transformation on the image indicated by
imageIn = an image file path relative to the current working directory
if no imageOut is provided, saves in place,
otherwise, makes a new image copy per name given
'''
img = io.imread(imageFileLocation)
img = img.resize(500,500)
img = colorFunction("green")
img = colorFunction("blue")
img = alphaFunction(True)
io.imsave(imageOut, img)
print "SUCCESS!!! imageTransform(%s, %s)" % (imageIn, imageOut)
Like everything else, individual results vary. I suppose the key here is knowing when I'm writing reusable code and knowing when I'm not. Neither of these pieces of code is particularly reusable, but at least the second one isn't wasting any time trying to be.
Slicing Lists
Slicing only really started to make any sense to me after I filled in ALL of the blanks for a while. Every slice has three variables: start, stop, and step.
newList = oldList[start:stop:step]
start is the starting index, which defaults to 0.
stop is the stopping index (or really, one before, it's a do until command), which defaults to length + 1 (or the entire list).
step is also known as stride. 1 means every value will be hit, 2 every other, and so on.
A simple slice:
a = [0,1,2,3,4,5]
n = a[:]
print n
>>>[0,1,2,3,4,5]
Note the two colons '::'
. Otherwise, this is the same as above.
n = a[::]
print n
>>>[0,1,2,3,4,5]
Another simple slice:
n = a[2:4]
print n
>>>[2,3]
Once again, this is the same as the previous only with all of the colons ('::'
).
n = a[2:4:]
print n
>>>[2,3]
This is the slice written out longhand. Most folks don't do this. But I find that it often helps to be explicit and writing it all out was essentially the key factor in learning how to slice for me.
n = a[2:4:1]
print n
>>>[2,3]
With all the syntax in place, this just isn't that hard to remember [start:stop(before):step]
n = [4:2:-1]
print n
>>>[4,3]
Note, just the one ':'
below revserses the List.
n = [:-1]
print n
>>>[0,1,2,3,4]
Finally, with two '::'
n = [::-1]
print n
>>>[5,4,3,2,1,0]
Simplicity itself. I do a lot of image processing. Image files tend to be three dimension arrays. To slice a three dimensional array, the individual dimensions are separated by commas
[s:s:s, s:s:s, s:s:s]
Does that make sense? If I only want the first slice of the third dimension (the red layer in an RGB image), the slice is [::, ::, 0:1:1]
or [::, ::, 0]
. For the second (or green layer) the slice is [::, ::, 1:2:1]
or [::, ::, 1]
.
But truthfully, slices are one of those things I confirm on the spot. I'm so prone to error, that there is no sense second guessing any of it. In fact, everything but the multidimensional stuff, I threw through the interpreter just to be sure. It's just too easy to make a mistake that will telegraph down the line and through the code, so I always print the value to output after making a slice to insure that it conforms to my expectations. For multi-dimensionals, this usually means using numpy.shape
:
b = a[::, ::, 0]
print "Shape A is %s \t Shape B is %s" % (str(a.shape), str(b.shape))
print b.shape
>>>Shape A is (500,500,3) Shape B is(500,500,1)
List Comprehensions
List Comprehensions from the piddling easy to the mindbogglingly complex (newly made easy).
A basic list comprehension:
myList = [x for x in range(0,4,1)]
print myList
>>>[0,1,2,3]
A basic iterator:
for x in range(0,4,1):
print x
>>>0
>>>1
>>>2
>>>3
Using the list as an iterator:
myList = [x for x in range(0,4,1)]
for x in myList:
print x
>>>0
>>>1
>>>2
>>>3
Since it's easy to iterate over any list, there's not much point in separating the two use cases.
Here's a basic list comprehension with a conditional clause:
myList = [x for x in range(0,4,1) if x%2 == 0]
print myList
>>>[0,2]
Using a function as the conditional clause:
def g(x):
return True
myList = [x for x in range(0,4,1) if g(x)]
print myList
>>>[0,1,2,3]
A list comprehension with simple leading expression. The parentheses are not required, but useful when learning or putting together a complex comprehension.
myList = [(x + x) for x in range(0,4,1) if g(x)]
print myList
>>>[0, 2, 4, 6]
The leading expression can be a function. And since a function can call a function f(f(f(x)))
(or whatever), the values can effectively be piped to one's heart's content.
def g(x):
if x%2 == 0:
return True
def f(x):
return x*x
myList = [f(x) for x in range(0,8,1) if g(x)]
print myList
>>>[0, 4, 16, 36]
Finally, multiple comprehensions may be nested. (Note, one can leave white space inside of brackets in Python for prettier code layout.) This comprehension returns a list of tuples. If both were numbers, it'd be great for indexing a two-dimensional array.
myList = [(x,y) for x in [1,2]
for y in ["A", "B"]]
print myList
>>>[(1, 'A'), (1, 'B'), (2, 'A'), (2, 'B')]
A nested list comprehension with conditional assignment:
def h(x,y):
return x * y
myList = [h(x,y)
for x in [0,1,0,2] if x > 0
for y in [1,5,10] if y != 5
]
print myList
>>>[1, 10, 2, 20]
The simple truth of the matter is that I don't believe it's possible to make a list comprehension more complex than this last. Oh, one can string functions together until they're not readable, but to the best of my knowledge, the syntax is locked into this format. So to understand even the ugliest of nested comprehension, it's really just a matter of indenting and adding parenthesis until it makes sense.
Also, one last final thought before I move on. (I promise this is the final, final thought) One of the great reasons to use comprehension is so one doesn't have to go back and indent and un-indent block after block because one decided to add an other if clause to their for loop. If the comprehension is made in advance of the loop, no re-indenting will ever be required... well, OK, just not as often.
def doSomething():
print "I'm done indenting no matter how much my comprehension changes"
myList = [h(x,y)
for x in [0,1,0,2] if x > 0
for y in [1,5,10] if y != 5
]
for item in myList:
doSomething()
>>>I'm done indenting no matter how much my comprehension changes
>>>I'm done indenting no matter how much my comprehension changes
>>>I'm done indenting no matter how much my comprehension changes
>>>I'm done indenting no matter how much my comprehension changes
Oh, and let me let you in on a little secret. (So, there I lied. The final-final thought wasn't actually my last...) I wrote this entry on list comprehensions as much so that I would understand them as anything else. It's amazing what writing an explanation as to how something actually works will clarify that thing for me. Or in other words, bring your list comprehensions on, my friend, bring them on...
Sample List Comprehensions -- Test Review Sample Questions
I like to think of this as a question answer review section. That, or a list of samples that I found here and there: some rather interesting to me.
result = [transform iteration filter]
result = [f(x) for x in g(x)]
result = [expression
for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
for item3 in iterable3 if condition3]
letter = [word[0] for word in listOfWords]
["a","b","c"] = [word[0] for word in ["alpha", "bravo", "charlie"]
upperCastList = [x.upper() for letter in lowerCaseList
["A", "B", "C"] = [x.upper() for x in ["a","b","c"]]
onlyTheNumbers = [n for n in someString if n.isdigit()]
[1, 2, 3] = [n for n in [1, "alpha", 2, "bravo", 3, "charlie"]
oddsSquared = [i * i for i in range(10) if i % 2 != 0]
myName = [w for w in open("myDocument.txt", "r") if "brettPaufler" in w]
#searches lines in text for word match
Conditional Assignment
Much simpler than List Comprehensions. Conditional Assignment (similar to a Ternary Operator) is a short form way to assign a variable inline using an if/else statement.
newVar = a if c else b
newVar = varIfTrue if testCondition else varIfFalse
value = "True" if True else "False"
print value
>>>True
value = "True" if False else "False"
print value
>>>False
Is equal to:
if testCondition:
newVar = varIfTrue
else:
newVar = varIfFalse
As follows is another way to do a conditional assignment; but as of yet, I have yet to find a reason to use this within a working project. And with that said, I have a sneaking suspicion it's considered bad form.
finalValue = ifTrueValue or elseValue
a = []
zed = len(a) or 25
print zed
>>>25
a = []
b = 0
c = False
d = None
zed = len(a) or b or c or d or "I never use!!!"
print zed
>>>I never use!!!
b = 0
z = 1
zed = b or b or z or b
print zed
>>>1
Blog
This is more of a personal choice, but I enjoy writing, and so writing about code seems like an extension of programming to me. And in-between programming projects I tend to do research for the next project, do some fiction writing, and/or put together some sort of webpage. I think you'll find that most of the better programmers (that I know about) write or blog at one level or another, which of course is more than a bit circular (how would I know about them if they didn't write or blog), but I think you get the idea: Blog.
Fame, Riches, and Glory Await
I've posted tons of stuff on the web (please see
Brett Words
and
www.paufler.net/takosori for verification of this statement). Between those two sites (and this one: www.Paufler.net.com), I've posted hundreds of pages comprised of thousands of documents. And I've had some degree of success I'll have you know. Just the other day (on 6-1-14 to be exact) I learned that www.Paufler.net.com was the 17,905,780th most popular site on the entire Internet. Wow!
Now, to understand the full immensity of this statement, one must consider that while
www.Paufler.net.com is rated, neither
www.paufler.net/takosori nor
Brett Words has a rating, which means they're tied will a billion other websites for last place.
Note: Takosori and Words both used to be stand alone websites until I turned them into spurs. Perhaps, the above explains why.
So, a rating means something (to me anyhow, even if it's down around 18,000,000th). So, I find it worth looking into why paufler.net got the rating and those other two sites didn't. You see, because I have entire novels posted on both of those sites (
The Suki Kamasutri: Queen of the Galactic Frontier
and
G'narsh:The Troll, The Myth, The Legend
to plug just two), but neither of those are on the radar. Nor are any of my brilliant cookery suggestions to be found at
Brett Food).
And after some searching around (i.e. doing a search on www.Alexa.com), I discovered that achieved the rating for www.Paufler.net.com was a simple how-to page exploring some trivial aspect of a relatively obscure javascript library. (I actually have the fifth page for that search term on Google, so I've got that going for me.)
Anyway, long story short (or not nearly as long as it could be -- you'll just have to trust me on that), I like to write. And in blogging about code, I find the following snippets of HTML markup to be of use.
HTML Code Markup
This is the style header info.
<style>
pre {border: solid 1px blue;
margin: 10px;
padding:10px;
background: LemonChiffon}
code {font-size:1.25em;
color: blue}
</style>
These are the tags for inline
code.
<code>Your Code Here</code>
And this is for the block codes as per this box below.
<code><pre>
<code>
Tells the parser to change the type style
<pre>
Tells the parser to honor whitespace
Returns, spaces, and tabs are preserved
And then, if you give the css more instructions (per above),
it will draw a box and so on.
</code></pre>
I was first published in:
"Letters to the Editor"
p. 3 in Heavy Metal, v. 26, no. 1 Mar. 2002).
Call no.: PN6728.H43v.26no.1
For my insightful correspondence entitled:
"Please Publish This Letter"
Yes, I am that Brett Paufler