This post follows on from my earlier post Coding 101, and is my responses and learnings from the highly-recommended Python programming book and course by Charles Severance (see References below).
Jargon:
I’m working on a glossary here, but still very unstructured and massively incomplete so I suggest staying with Google for now .
Some necessary concepts:
Programming consists of sentences or statements, which may include reserved words, which tell Python what we want it to do, but will also include some values in both numerical and text formats. These take the form of either constants, whose values don’t change, and variables, which have values that can change. Both constants and variables can have values which are numbers (numeric) or text (string).
Variables will have a name or identifier – effectively a label so the programmer and computer know what it is and remember the variable value it contains at any given time. The value is the content placed into the variable. This can be achieved in various ways: using a data input query, or making it the subject of some mathematical or other algorithmic calculation within the program. Here we use an assignment statement to put the value into the variable, e.g. x = 27 or y = 63. At any time, the program can overwrite the value held in a variable, to become any new value: this happens sequentially within the program.
A variable can be given any name as long as it meets certain rules: it cannot be a restricted word, must start with a letter or underscore (not prefixed with numbers or special characters), is case sensitive. Good practice is to generally retain all lower case and not use _ prefix for naming, and to choose a variable name related to what the variable will do within the program.
Getting expressive:
We can write any assignment statement to given a variable a value, and modify this with an expression to create some kind of mathematical or other algorithm to define how the value within the variable should change. A very simple expression would look like x = x + 9. That is, if x started out as 27, then after performing the expression x = x + 9, the new value of x (27 + 9) becomes 36. The expressions possible needn’t be so simple, and can reach any level of complexity.
Mathematical operators:
Python uses the following mathematical operators: + (add), – (subtract), * (multiply), / (divide), ** (raise to power). This last one differs to Excel (which most business users would be familiar with, which uses ^) and % (called the modulo operator).
Note that Python conducts truncated (integer) division, meaning it returns only the integer value of a division calculation. For example, 10 / 4 returns 2 (not 2.5). The modulo operator returns the remainder left after any division calculation. For example, 10 % 4 (we say “10 modulo 4”) returns 2 (i.e. 10 divided by 4 is 2 remainder 2). To overcome, include decimal places within all values (operands), e.g. 10.0 / 4.0 returns 2.5 (floating point division). Alternatively, if one of the operands is a floating point value, both will be converted to floating point then calculation performed as floating point, e.g. 10 / 4.0 returns 2.5. (Note this conversion from integer to floating point occurs for all operations, not just division.)
Rules for operator precedence are the same as in maths: parentheses (brackets) first; then powers (**), then multiply or divide or remainder, and finally add or subtract. Other than the operator order just listed, the convention will be to read and calculate from left to right.
Good programming style suggests to keep mathematical expressions simple where possible, break them up into constituent parts, and use brackets where possible to break up complex expressions, making them easier to read.
What’s my type?
In Python a type is a kind of classification, so an integer value will be one type and a floating point value will be a different type. The type then defines what kind of function (calculation) Python performs. Similarly, numbers are a type and text strings are a different type, so the function Python performs on each will differ. For example: print 2 + 3 returns 5 (the operator + performs the function of mathematical addition), whereas print ‘hello’ + ‘world’ returns the text string “helloworld” (in this case + performs the function of concatenation). (Note that * applied to strings has the effect of multiple concatenation, e.g. print ‘go’ * 3 returns “gogogo”
An attempt to add a number and a text string together will return a Traceback TypeError since Python is unable to add/concatenate together an integer and a string. To find out the type of any given variable, use the following:
>>> type(‘textstring’)
OR
>>> type(63)
OR
>>> type(27.72)
OR
>>> type(variablename)
These will return, respectively, ‘str’ (string), ‘int’ (integer), ‘float’ (floating decimal) or the variable type (may be either integer, floating decimal or string).
At any time you can force Python to convert the type, e.g. from an integer to a floating decimal by specifying:
>>> float(value)
OR
>>> x = 10
>>> fx = float(x)
>>> y = fx / 4
>>> print y
2.5
Alternatively, force conversion from text string (say, where numbers are entered but stored as a string) to integer using:
>>> val = ‘321’
>>> type(val)
<type’str’>
>>> vali = int(val)
Note: this only works where the value in the text string was numerical characters.
Raw data input:
The raw_input function in Python allows the program to pause and receive data into a named variable, as input by a user in the form of human-readable text, before continuing the program. The function includes a prompt to advise the user what input is required. Note, the input type is expected to be a text string.
Example:
>>> firstname = raw_input(‘Enter first name’)
Enter first name: Wonderwoman
>>> print “Hello”,firstname
Hello Wonderwoman
In a previous example, we used the + operator to concatenate text string outputs; they will not contain a comma unless we add a space into one of the strings. Here we output a series of values separated by a comma; on printing, a space is automatically added between the values being output.
Programming style:
We already saw above how we can name a variable whatever we want. Often good style dictates we should name variables in accordance with what they relate to or what they do in the program. Although it’s not necessary, and we could just use algebraic x, y, z etc., using relevant variable names helps us (and others) read and understand the code more easily.
Another example of good coding style is to add comments to aid human readers’ understanding of the code. For example, comments about who wrote the program and when, and what it does, or comments describing which individual sections (or lines) of the code do. It can also be used while testing code, to ‘turn off’ one line of code temporarily (but not delete it), while debugging a program.
Comment lines begin with a hash # and indicates to Python that it should disregard everything on that line after the #. As we develop a program, a good way of using the # is to deactivate certain lines of code by placing a # in front (turning it into a comment line), in order to test other sections of a program – this saves us deleting and rekeying if we later want to reinstate that part of the program.
Iterative development:
A key component of good programming is Iterative Development, which is building up a more complex program step by step, developing small sub-sections and testing them as you go along. I do this automatically even as I’m learning programming from scratch. In fact, it’s something I’ve always done.
For example, when building up complex models in Excel I would build up in sections and test that each section gives me the answer I expected (using simple test data if needed), before moving on to the next section. I’d use the same process when developing complex spreadsheets with multiple, nested conditional and lookup functions.
So as I study this Python Programming beginners course, and naturally and automatically fall into good programming practice, it make me feel confident in myself. It allows me to feel certain that I made the right choice to pursue this new avenue. (Just a shame it was 30 years late.)
(Although, actually it’s never too late!)
Will she, won’t she (adding conditionality):
We saw in our introduction to Python that programs might consist of sequential lines of code (statements or commands which the computer actions one after another) or conditional commands (statements the computer actions only if certain conditions are met) or iterative commands (statements the computer actions over and over again until some condition is met which forces it to stop).
Here we take a look at the second of those two: conditional commands. We flag a conditional command by using the reserved word if. When developing a complex conditional sequence, a flowchart can be used to good effect to map out the required steps, conditions and branches before converting into code, e.g. if {some condition} = YES then {do some command} x, if {some condition} = NO then {do some command} y.
Conditional expressions and operators
We saw above the conditionality which is termed as a YES/NO question (in programming terms, the YES/NO answers will be expressed as TRUE/FALSE). This is a Boolean Expression, a logical statement that compares two similar types of variables and confirms whether or not they meet certain criteria, as denoted by one of several Conditional Operators. These are given below, including how they’re expressed in Python:
> Greater Than
>= Greater Than or Equal To
< Less Than
<= Less Than or Equal To
== Equal To
!= Not Equal To
Note that the Conditional Operator “Equal To” is denoted in Python by two equals signs (==) to differentiate it from the single equals sign (=) which is an Assignment Operator (assign some value to a variable).
Indentation:
Coding style replicates the flowchart by using indentation, where the indented command is the conditional command (it’s execution being dependent on the preceding conditional if statement being met or not). Note that a colon (:) is included at the end of the if statement.
if condition = TRUE :
- print x
if condition = FALSE :
- print y
We can continue to use the indentation for any number of steps we require the program to execute subject to the conditional statement. Programming convention is to indent by 4 blank spaces, but as long as the indentation always lines up (is at the same level within each grouping of conditional steps) Python will read it accordingly as the steps to execute if the preceding condition statement is met. Any new line of code NOT indented, i.e. lining up with the preceding if statement, will not form part of the conditional sequence, and will continue to be executed as normal.
Indentation rules:
Note that in Python indentation is syntactically significant, that is, it forms a part of the structure of the program which Python will read and try to understand. Hence in Python it is important to get the indentation correct; it’s not just there for the benefit of humans to make the code easier to read (as is the case in many other programming languages).
Any statement ending in a colon (:) – including if and for – the block coming after it should be indented. This indicates the scope of the block of commands which are dependent on the preceding if or for statement. Remove the indent after the conditional block has ended, decreasing the indentation back in line with the preceding if/for statement.
Some text editors can be set to turn tabs into spaces. If you continue using tabs in a text editor and have too many tabs (which may just look like spaces to you) Python can go nuts and return indentation errors, because it reads the tabs (indentations) syntactically. Better just to set text editor to turn off the tabs function.
Note that you can still use comment lines within an intended block (lines starting with #), and these will not affect execution of the code. Likewise blank lines within the indented block will not affect it’s execution. (Both # comment lines and blank lines help humans to read the code more easily.)
One-way decisions (IF):
The following example illustrates the indentation style in a One-Way Decision. Here the steps following the conditional statement may or may not be executed, followed by another command which is executed, regardless of whether the conditional steps were executed or not.
if condition = TRUE :
- print x
- print “again”
- print “one last time”
print “print this regardless”
Nested decisions (nested IF):
Nested Decisions include a conditional block indented within another conditional block, e.g. if {condition 1} is YES then do [ if {condition 2) is YES then do {some command} ]
if condition1 = TRUE :
- print “condition 1 is met”
- if condition2 = TRUE :
- print “both conditions are met”
- print “both conditions are still met”
- print “condition 1 is still met”
Two-way decisions (IF – ELSE):
Two-Way Decisions use the reserved words if and else, and allow us to ask a conditional YES/NO (TRUE/FALSE) statement and do one of two things, dependent on whether the answer was YES or NO, e.g. if {condition 1} is YES then do {some command) otherwise do {some other command}. Note the second branch of the two-way decision using else, appears in line with the original if statement, and is followed by a colon.
if condition = TRUE :
- print “true”
else :
- print “false”
print “print this regardless”
Many-way decisions (IF – ELIF – ELSE):
We can also ask conditional YES/NO statements which have multiple branches, using the reserved words if, elif and else. This is an extension of the two-way decision, e.g. if {condition 1} is YES then do {some command} otherwise [ if {condition 2} is YES do {some other command} otherwise do {a third command} ]. Note that only one outcome is possible: either condition 1 is met OR condition 2 is met OR neither are met.
if condition1 = TRUE :
- print “condition 1 is met”
elif condition2 = TRUE :
- print “condition 1 is NOT met but condition 2 IS met”
else :
- print “neither condition 1 NOR condition 2 are met”
print “print this regardless”
Note that IF – ELIF constructs can be made with multiple elif conditional statements. In this case, the program will run through all conditional statements in turn: if condition 1 is not met, it will go on to check condition 2; if condition 2 is not met it will go on to check condition 3, and so on. This is particularly useful if you want to do some kind of sorting and grading exercise on a particular variable. Note that, for this to work correctly, the sequence of the grading/sorting needs to move either up or down sequentially; they cannot be out of sequence otherwise the out-of-sequence elements will not execute (due to the fact that if – elif will return only one possible outcome).
Conditional IF or IF – ELIF sequences can also be run with no final else statement. In this case, nothing will happen if ALL conditions (1, 2, 3, etc.) are NOT met; it will simply go on to execute the next line of the program.
A more complex conditional structure (TRY – EXCEPT):
The try – except structure allows a break to be written into a program to deal with a possible problem in the program. The program is told to try a particular command and, if it can execute it without problem it does so and then carries on with the normal sequence of code. If the program cannot execute that problem command, then the program jumps to the except clause in the code and runs that instead. This is very useful where user inputs are required but may contain possible input errors which would otherwise cause the program to crash out.
A simple example below takes a text input. In the first instance, it can’t convert x into an integer, so uses the except clause to set the integer value to -1 (you can use some other suitable error integer instead) and prints out the value -1. In the second instance, the input for x was a text string which can be converted to a numerical integer, so the except clause was not needed and the program printed out x1 as the value 321.
x = ‘Joe Blogs’
try:
- x1 = int(x)
except:
- x1 = -1
print x1
x = ‘321’
try:
- x1 = int(x)
except:
- x1 = -1
print x1
print “the end”
It is possible to include more than one line of code in the try clause, but good programming style dictates that as little code as possible should be included there, and that the most important problem command should be run first. This is because any lines of code which can be run successfully during the try clause will run, and, only once the problem/test command is reached and falls over, will the program skip to the except clause. The commands in the test clause which have already executed within the try clause will not be undone by the program skipping over to the execute clause.
Example – testing user input:
The following simple example tests for user input to ensure it’s numerical (hence can be converted to an integer), and if not returns an error message.
x = raw_input(‘Enter a number:’)
try:
- x1 = int(x)
except:
- x1 = -1
if x1 > 1 :
- print “Number entered correctly”
else :
- print “You did not enter a number”
References
Book: Programming for Informatics – Exploring Information by Charles Severance
Course: Programming for Everybody (Getting Started with Python) by Univ. of Michigan. Part of the Python for Everybody specialisation.