Python
Python, the programming language
Quick Reference
for x in range(12) :
else :while condition :
else :def nameOfIt(parameter, parameter) :
7 / 3
= 2 and7 / 3.0
= 2.33333333333 butfloat(7 / 3)
= 2.0if x == y :
""" Multi-line
comments """True
,False
,and
,or
,not
list = ["cat", 2, 3.132, 'stuff and nonsense']
print len(list)
list.append("New item")
list.insert(4,"Another item")
list.append(["Item",'thing',13])
to add more than one item
list.pop(n)
removes the nth item from the list
list.remove("Value")
removes first instance of "Value" from the list
find = list.index("Item")
list.sort()
Reversedlist = list[::-1]
using a negative stride to reverse a listdictionary = { 'Key': 'value', 'Age': 42, 'Name', "Fred" } # the keys are unique
print dictionary['Key']
dictionary['Key'] = 21
dictionary["New thing"] = "Value"
(no .insert is required)
del dictionary['Key']
(removes a key and its value)
dictionary.remove("Fred")
removes a key with the value of "Fred"
print dictionary.keys()
print dictionary.values()
dictionary.has_key("Bill")
Age in dictionary # True or False according to whether the key is in the dictionary
newList = [x for x in list if condition]
even_squares_to_50 = [x**2 for x in range(1,51) if x % 2 == 0]
- Anonymous functions:
lambda variable: expression
# normal function my_list = range(16) def by_three(x) : return x % 3 == 0 print filter(by_three,my_list) > [0, 3, 6, 9, 12, 15]
# anonymous function my_list = range(16) print filter(lambda x: x % 3 == 0, my_list) > [0, 3, 6, 9, 12, 15]
Getting help and providing help() using a docstring
To get to the description of a built-in function:
help(function)
To provide help() in a home-made function - called a 'docstring':
def area(base, height) : '''(number,number) -> number Returns the area of a triangle with dimensions base and height. ''' return base *height / 2
Finding functions with dir()
dir(_builtins__) help(abs)
A method is a function inside an object.
Classes example
# Class definition class Animal(object): """Makes cute animals.""" is_alive = True health = "good" # For initializing our instance objects def __init__(self, name, age, is_hungry): self.name = name self.age = age self.is_hungry = is_hungry # Add your method here! def description(self): print self.name, self.age # Note that self is only used in the __init__() # function definition; we don't need to pass it # to our instance objects. zebra = Animal("Jeffrey", 2, True) giraffe = Animal("Bruce" , 1, False) panda = Animal("Chad" , 7, True) hippo = Animal("Harry" , 8, True) print zebra.name , zebra.age , zebra.is_hungry print giraffe.name, giraffe.age, giraffe.is_hungry print panda.name , panda.age , panda.is_hungry hippo.description() print hippo.health, sloth.health, ocelot.health
File handling
There are four methods for reading a file:
filename = "../whatever/file.dat" file_ref = open(filename,'r') # 'w' to write and 'a' to append 1 record = file_ref.readline() # will have '\n' at the end, or null at the end of the file print(record, end='') # prevents print() from appending a newline. file_ref.close() 2 for record in file_ref : print(record, end='') 3 entire_contents = file_ref.read() # read() returns the entire file 4 record_list = file_ref.readlines() # readlines() returns all the records in the file as a list.
Writing:
import tkinter.filedialog filename = tkinter.filedialog.askopenfilename() # a graphical file prompt for a file to open filename = tkinter.filedialog.asksaveasfilename() # a graphical file prompt for a file name to write to file_ref = open(filename,'w') # 'w' to write and 'a' to append record = "Blah\n" file_ref.write(record) # write() does not append a newline file_ref.close()
Grizzles
- The use of colons with 'for' and 'if'. The are immediately followed by indentation. Python says it uses white space to determine structure, not { } or other constructs. The reality is that ':' is determining the structure and the whitespace merely an inconvenience to the programmer. Personally, I like the whitespace idea, but the ':' is an unnecessary faff. And do you know why it is there? Supposedly to allow text editors to highlight code properly - but if indenting with whitespace determines structure, then why can't the editors do the same?
- Immutable strings. There is no reason for this constraint. It was done to make memory management easier and very slightly more performance efficient, but it is a constraint that has had knock-on effects through other parts of the language definition. As a constraint to improve performance ... who the hell cares about memory manipulation in RAM time any more? That's so 1970s. There is no real reason why one cannot say
myString[7:10] = "replacement text"
. It was even possible in QuickBASIC!
- So are strings lists or not? One can treat strings as arrays using
for x in "How long" : print x
, so why notMyString[3] = "z"
?
- Version 2 or version 3? Just fork the God-damned schizophrenic language into two and get it over and done with! At least then version 3 can die in peace.
- Functions or methods? Methods or functions? Which is it to be, Python? Why can't I say
sort(myTable)
ormyString.length()
This is just sloppiness that makes it hard for newbies. I thought Python was meant to be easy for newbies, and with only one way to do things? Hmm?
- Count from 0 in indexes, except for terminators. Eh? Why is a substring
myString[2:4]
only 2 characters long? I have no trouble with counting from zero, but why is the[:y]
parameter one higher than it needs to be? It just causes confusion.
__init__()
to initialise classes/objects. What sort of name it that? What was wrong withinit()
?
Confusion
- Passing variables to functions - why bother? Since passing a variable to a function, then changing the variable, changes the global variable, this means variables in functions are not local to the function. In which case, why bother passing parameters to the function at all and not just work on the global variable, like one would in BASIC? Unless the function is going into an external library, there is rarely ever going to be any point passing in parameters. In fact, why aren't variables passed as parameters to functions treated as local variables?
- Why
del dictionary['Key']
to remove a dictionary key and its value rather thandictionary.delete('Key')
? Why have a distinctdel
command for this one activity? - In Python version 3, int + int = int. int - int = int. int * int = int. So what is int / int? Nope, it is always a float; even 4 / 2 = 2.0 rather than 2. This is inconsistent behaviour. (In Python version 2, the result of dividing an int by an int is an int.)
WTF???
- Create a table to play Noughts and Crosses:
table = [ ["."] * 3 ] * 3 >>> print(table[0],"\n",table[1],"\n",table[2]) ['.', '.', '.'] ['.', '.', '.'] ['.', '.', '.']
The formatting needs fixing, but otherwise it's looking good. We've got "." for where a "O" or a "X" can be played. So, 1st player makes a move:
>>> table[1][2] = "X" >>> print(table[0],"\n",table[1],"\n",table[2]) ['.', '.', 'X'] ['.', '.', 'X'] ['.', '.', 'X']
Eh? Why three lots of "X" in a column? Now the second player makes a move:
>>> table[2][0] = "O" >>> print(table[0],"\n",table[1],"\n",table[2]) ['O', '.', 'X'] ['O', '.', 'X'] ['O', '.', 'X']
WTF? Yep, the command table = [ ["."] * 3 ] * 3
creates a list of 3 dots, then creates three pointers to that same list. What on earth is the point of that? And why doesn't the first "[…]* 3" behave like the second "[…]* 3" and just create three pointers pointing at the first "."? This is just stupid and inconsistent and confusing.
- Assigning a variable to another variable creates a new variable:
>>> andy = "Apples" >>> pete = "Pears" >>> andy = pete >>> andy 'Pears' >>> andy = "Bananas" >>> pete 'Pears'
BUT assigning a list to another list does not create a new list:
>>> andy = ["Apples"] >>> pete = ["Pears"] >>> andy = pete >>> andy ['Pears'] >>> andy[0] = "Bananas" >>> pete ['Bananas']
Both andy
and pete
are pointing at the same place in memory; changing one changes another. This is stupid and inconsistent and confusing.
- Another example
>>> row = [1,2,3] >>> table1 = row * 3 >>> table2 = [row] * 3 >>> table3 = [row * 3] >>> table1 [1, 2, 3, 1, 2, 3, 1, 2, 3] >>> table2 [[1, 2, 3], [1, 2, 3], [1, 2, 3]] >>> table3 [[1, 2, 3, 1, 2, 3, 1, 2, 3]] >>> row[1] = 99 >>> row [1, 99, 3] >>> table1 [1, 2, 3, 1, 2, 3, 1, 2, 3] >>> table2 [[1, 99, 3], [1, 99, 3], [1, 99, 3]] >>> table3 [[1, 2, 3, 1, 2, 3, 1, 2, 3]]
So it is not just as simple as two variables pointing to the same place in memory; it is 'cleverer' than that. It actually remembers that table2
is constructed from three instances of row
. And this works both ways:
table2 [[1, 99, 3], [1, 99, 3], [1, 99, 3]] >>> row [1, 99, 3] >>> table2[0][1]=88 >>> table2 [[1, 88, 3], [1, 88, 3], [1, 88, 3]] >>> row [1, 88, 3]
So you have to remember that when assigning a list variable to another list variable, that Python behaves differently than with other variable assignments. And you have to also remember that whenever you change the contents of a list, the values in that list may be being used by another list somewhere else in the program without your knowledge. What a mess.
>>> a=[99] >>> b=[a] >>> a[0]=[b] >>> a [[[[...]]]] >>> b [[[[...]]]]
Oops. I broke Python.