Programming for Geographical Information Analysis: Core Skills Basic Syntax and Single Value Variables
Programs for geographical information analysis are written in text files with the .py extension for Python, containing statements that direct the computer on what to do. The syntax involves delimiters, keywords, identifiers, literals, and operators that form the atomic components of a statement. This lecture covers basic syntax, delimiters, keywords, variables for storing single values, and operators. It emphasizes the structure of statements, use of comments, and compound statements in different programming languages like Python. The importance of correct indentation for control flow and readability is highlighted.
Download Presentation

Please find below an Image/Link to download the presentation.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.
You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.
E N D
Presentation Transcript
Programming for Geographical Information Analysis: Core Skills Basic Syntax and Single Value Variables
Review Programs are written in text files with the .py extension (for Python) They contain statements, usually one per line, telling the computer what to do. Statements are formed to some syntax (~grammar) and out of symbols and words. In imperative, stateful, programming, data is held in variables. We use control flow statements to direct the program down different paths. One type of control flow is procedures - a separated off bit of code you can run by calling it.
Statement atoms The 'atomic' components of a statement are: delimiters (indents, semicolons, etc.); keywords (built into the language); identifiers (names of variables etc.); literals (values like 2 or "hello world") operators (maths symbols that do stuff).
This lecture Basic syntax Delimiters Keywords Variables: storing single values Operators We'll come on to variables for storing multiple values next time.
Basic syntax Each statement is generally a single line (statements can be stacked on a line with semicolons but this is unusual). Standard 'inline' comments (text for humans) start # # This is an inline comment. 'Block' comments across multiple lines start """ and end """, or ''' and end ''' """ This is a block comment. """ You can have as many blank lines as you like to structure code.
Compound statements In many languages, lines have some kind of end of line marker (e.g. a semi- colon) and code is divided into control flow sections by braces/curly brackets: if (a < 10) { alert (a); } alert("done"); // JavaScript But this allows errors (a missing bracket or semicolon can change the meaning), and requires coders to indent code inside the sections to make it clear where the control flow is.
Compound statements In Python, lines are generally one statement per line and are grouped in blocks by indenting and dedenting. You can use spaces or tabs, and as many as you like of either, but be consistent. We recommend using 4 spaces. In theory, this means formatting and syntax are one. In practice, the interpreter basically looks at whether indenting is more or less than previous lines, this works in some versions of Python: if a < 10 : print (a) # Using a mix of tabs and spaces print ("done") But it isn't good practice. Align blocks at the same flow control: if a < 10 : print (a) print ("done")
Compound statements Overall, this causes less bugs, but you need to make sure your indenting is correct or the control flow changes. This: if a < 10 : print (a) print ("done") Is completely different to this: if a < 10 : print (a) print ("done")
Delimiters Newlines and indenting/dedenting at the start of a line are special kinds of delimiter-ish things, as are ' " # \ Others (some of which also act as operators): ( ) [ ] { } , : . ; @ = -> += -= *= /= //= %= @= &= |= ^= >>= <<= **=
Enclosing delimiters Python especially uses three style of enclosing delimiters. These are what the Python documentation calls them: {} braces [] brackets () parentheses # Sometimes called curly brackets elsewhere. # Sometimes called square brackets elsewhere. # Sometimes called curved brackets elsewhere.
Line breaks Lines can be joined together into a single line with a backslash, \ provided this isn't part of a piece of non-comment text or followed by a comment. Lines inside {} () [] can also be split (and commented); though non-comment text needs quotemarks around each line. Triple quoted text may be split across lines, but the formatting (spaces; linebreaks) will be kept in the text when used (i.e. if it's not a comment). print \ (""" Daisy, Daisy, Give me your answer, do... """)
Keywords The following are reserved for special uses and can t be used for anything else: False class finally is return None continue for lambda try True def from nonlocal while and del global not with as elif if or yield assert else import pass break except in raise
Example: import Import adds libraries of code (modules in Python) so we can use them. Usually at the top of the file we add: import module_name For example: import builtins From then on we can use code inside the library. We'll come back to imports when we look at the standard library.
Identifiers These are labels stuck on things. The main use of identifiers is in constructing variables. But they are also used for naming, for example, procedures, or as Python calls them functions.
Builtins As well as keywords, there are some functions (like print()) built into the standard distribution. These are in a module called builtins. The shell loads this up automatically, but hides it with the name __builtins__ . This double-underscore notation is used in Python to hide things so they aren't accidentally altered. It is called 'dunder' notation It's easier to deal with if you import it normally. To see what's inside, enter: >>> import builtins >>> dir(builtins) dir() is one of the builtin functions. Used with a module name it tells you what functions and variables are available inside the module. Used on its own, it tells you what identifiers are currently being used.
This lecture Basic syntax Delimiters Keywords Variables: storing single values Operators We'll come on to variables for storing multiple values next time.
The what of variables Variables are the combination of an identifying label and a value, often a literal like 2 or "hello world". The label/identifier is attached to the value thus: >>> a = 10 This is called variable assignment. Once assigned, when you use the label, you get the value: >>> a 10 Note that this is not the same as: >>> print("a") a
The what of variables They are called 'variables' as you can change the value: >>> a = 10 >>> print (a) 10 >>> a = 20 >>> print (a) 20
NB: Shell interaction Note that at the shell prompt, you don't actually need the print command, you can just type the name of the variable or an expression and it will display the value >>> a 20 >>> 2+2 4 We'll drop the print, when we're dealing with the shell prompt, but keep it for code that's displayed as if it is in a script.
The what of variables The label is just pointing to the value, which is stored somewhere in the computer memory. To show that it is just a label, there's nothing to stop you attaching more than one label to the same value. >>> a = 10 >>> b = a >>> b 10 b a 10 Note that this is not the same as: a b >>> a = 10 >>> b = 10 10 10 Which creates a second "10" and attaches it to b only.
The what of variables For text and numbers, if you change a variable, it is essentially created anew. >>> a = 10 >>> b = a >>> b 10 >>> b = 20 >>> a # Changing b has no effect on a, even though 10 # they were once attached to the same value, >>> b # because b is a new "b". 20
When a value has no label attached to it, it is useless, as we can't talk about it. Values >>> a = 10 >>> b = 20 >>> a = b The initial 10 is now without a label, so we can never talk about it again. How would we? For instance, this creates a new 10 rather than attaching to the old one: >>> a = 10 >>> b = 20 >>> a = b >>> a = 10 You can also remove labels from values by pointing them at the special "null object" None, which denotes a label not attached to anything (else): a = None Or entirely with del(label_name) or del label_name: del(a)
Garbage collection When all the labels pointing at something are removed from it, the object is unreachable. At some point when it can, the Python virtual machine will then do garbage collection and delete it from memory. We don't want very big variables containing whole files hanging around using up memory. If you want to force this, you can with: import gc gc.collect() But unless you're dealing with massive files and marginal memory space, its better to let the virtual machine deal with it.
Variable identifiers Names can be any continuous word/s, but must start with a letter or underscores. There is no relationship between a variable's value or use and its name. In the last simple examples, a and b were fine, but generally you should name variables so you can tell what they are used for: radius = 10 is more meaningful than a = 10 or bob = 10 In general, the more meaningful your names, the easier it will be to understand the code, when you come back to it, and the less likely you are to use the wrong variable. In geography, x, y , and z are obviously used a lot for coordinates. You will also see i, j, k used a lot for counting things, for historical reasons.
Name style Style conventions aren't syntax, but allow all coders to recognise what an element is. There's a styleguide for Python at: https://www.python.org/dev/peps/pep-0008/ But it goes out of its way to avoid talking about variable names. The community preference seems to be for lowercase words to be joined with underscores; what is called (coincidentally) snake_case: perimeter_of_a_square Though where Python is working with C or other code, the more conventional camelCase is sometimes used: perimeterOfASquare Either way, start with a lowercase letter, as other things start uppercase.
The what of variables You may see variables described as containers for values, but this isn't true and isn't helpful. Think of them as labels and values. As we'll see later on, it is quite easy to get confused about what a variable is referring to, and thinking about them as a identifier/label and value helps.
The why of variables Variables are generally used to hold the result of calculations and user inputs. These are things we can't predict before the code is run. Some things we can predict the value of, for example, the 4 in: perimeter = 4 * length_of_side # perimeter of a square Such literals are hardwired in. Even such literals are often better put in a variable at the top of the file, as changing the variable instantly allows us to change the value throughout: number_of_sides = 4 perimeter = number_of_sides * length_of_side This now works for any regular shape if we change number_of_sides.
Values What kinds of things can we attached to variable labels? Everything! Literals like 1, 1.1, "a", "hello world". But also whole chunks of code. All the code and values in the computer is held in the form of binary data. We don't usually see this, but it is. It has to be: computers are just very complicated sets of on and off switches. If values are just spaces in memory with something in them, and all code and values is binary, if we can attach a label to a value in memory, we can attach it to code in memory. This is the basis of object oriented computing.
Objects Objects are chunks of code that are wrapped up in a particular way. One thing this format enables is the attaching of labels to them to create variables. Objects can have their own functions and variables, so you can have variables inside other variables. Objects generally do some particular job. Here's an example
import tkinter Example def run(): pass root = tkinter.Tk() menu = tkinter.Menu(root) root.config(menu=menu) model_menu = tkinter.Menu(menu) menu.add_cascade(label="Model", menu=model_menu) model_menu.add_command(label="Run model", command=run) tkinter.mainloop()
import tkinter Example def run(): pass The dot operator is used to say look inside this object and find this code (in this case a procedure). root = tkinter.Tk() menu = tkinter.Menu(root) root.config(menu=menu) model_menu = tkinter.Menu(menu) menu.add_cascade(label="Model", menu=model_menu) model_menu.add_command(label="Run model", command=run) tkinter.mainloop() Pythonis a third generation, imperative, procedural, object oriented language.
Values Don't worry about how we make objects for the moment; we'll look at this a bit later. But, for example, in Python (but not all other languages), functions themselves are objects that can be given labels: >>> a = print >>> a("hello world") hello world This makes it incredibly powerful: for example, we can pass one function into another (the core of functional programming). >>> dir(a)
Values How does the computer know what a variable is? For Python, it works it out. This takes it a little time, but means it is much more flexible.
Static vs dynamic languages Dynamic languages calculate on the fly what static languages do at compilation time. This traditionally makes them more flexible but less efficient. For example, with many static languages, variables are associated with a single data type. This is quite often associated with manifest typing: you have to say what kind of variables you re going to use before/when you first use them. This is sometimes called the variable declaration or description. This: a) b) means the system can check you re using the type of variable you think you are. Here s a Java declaration and assignment: allows the system to set aside memory for the value; int a = 20; Dynamically languages allow a variety of types to be associated with a variable. These are therefore often associated with implicit typing, where you don t have to define the type, and frequent type inference, where the system works out which type is being used.
Type inference In general, for type inference languages, the computer will work out the type of the variable. This is a little less efficient but allows any type to be assigned to an identifier, which make code easier for beginners. However, it does mean that you need to keep track of what kind of thing is in the variable. For example, Python will often also allow different types of value to be used with a function call, but there are limits. Python will generally warn you if you misuse a variable, but this isn't always the case, which is one reason very critical systems are more likely to use manifest typing languages.
Assignment order When we assign an expression, the expression on the right is generally calculated first and assigned the label on the left: a = 2 + 2 This means this is fine: a = 2 a = a + 2 Note that for functions, there is a difference between a = dir a() # Use "a" as an alias for "dir" # which we can then call. and a = dir() print(a) # Run "dir" and get some result back from it, # assigning the result to "a" we can then print.
Augmented assignment Instead, Python has the augmented assignment operators: x += 1 # same as x -= 1 # same as x = x + 1 x = x - 1 As we'll see, you can create some quite complicated assignment statements, but these assignment operators can only be used in very simple ways like these.
Primitives Many languages have primitives: core data types built into the language with a definite space set aside for each type in memory. These are usually simple literal holders. Python has core types, but these are not primitives: they're object types with their own functions and variables for storing the literals; you just don't have to know that to set them up.
Built in types Integrals: int : Integers whole numbers. bool: True and False ; evaluate to 1 and 0 respectively, except when printed. Other numbers: float: Floating point numbers decimal numbers (sometimes called doubles in other languages because of how they are stored) complex: For imaginary numbers (actually two floats: one real, one imaginary) Basic sequences: str: Strings text. bytes: Byte binary.
Built in types as objects To see that these are stored as objects, look at this code: >>> a = "hello world" >>> b = a.upper() >>> a hello world >>> b HELLO WORLD >>> c = "hello world".upper() >>> c HELLO WORLD Notice that in the case of "hello world".upper() we haven't even made a variable label; from the start, the string literal is wrapped in an object. Try typing >>> 2. And then hitting the tab key to see what functions and variables are available when numerical literals are wrapped (or use dir(2)).
Ints Ints may look like: 1000000 or 1_000_000 but can't have leading zeros. # 3.6 onwards for the underscores. Since Python 3, the size of int you can have is only limited by the computer memory, and is, therefore, for all practical purposes, unlimited.
Floats Floats may look like: 3.14 10. .001 1e100 3.14E-10 0e0 3.14_15_93 Floats are limited, but to a very large (system dependent) number. You can find it with: >>> import sys >>> sys.float_info For a 32 bit machine picked at random it was ~1.75e308 to -2.22e308. In the unlikely event you need bigger numbers you can construct them from two ints! Floats have two special values: a = float("inf") a = float("nan") # Representing infinity. # Representing the result of a calculation a computer can't do # for example, dividing by zero.
Floats: warning You might think that floats are more exact than ints, because you can have decimal places. However, you'd be wrong: computers are very poor at representing decimal numbers. So poor, it regularly kills people. Ints, on the other hand, are exact. Python matches the IEEE 754 double-precision number standard, but still has issues. If you intend to use Python for critical systems, especially navigation systems, you need to read up on floating point calculations. A good starting point is: https://docs.python.org/3/tutorial/floatingpoint.html We'll mention this again later in the course, looking at the Fractions and Decimal libraries which try to make them more exact, and flag when they're not.
Imaginary numbers Imaginary numbers are floats followed by capital or lowercase "J". 3.14j 10.j 10J .001J 1e100j 3.14e-10j 3.14_15_93j These are joined to real floats with the "+" operator (not addition when there's a "J") to form complex numbers: >>> a = 3.2+2.4J >>> a (3.2+2.4J) We won't deal in detail on complex/imaginary numbers here, but if you're interested then a good starting point is: https://docs.python.org/3/library/cmath.html
Type To find the type of a variable (for example, one you've not back from a function), use type(variableName): >>> a = 10 >>> type(a) <class 'int'>
This lecture Basic syntax Delimiters Keywords Variables: storing single values Operators We'll come on to variables for storing multiple values next time.
Operators - + - / * ** // % @ Unitary - negates a number, e.g. in a = -1. Add; subtract; divide. Multiply. Power, e.g. a**b == ab. Floor divide, i.e. give the result as next lowest integer. Modulus, i.e. remainder of integer division; but note, used sometimes to format strings. Unused in core, but reserved for matrix operations in libraries.
Comparison operators == != < > <= >= is not is Equal to; not equal to Less than; greater than; less than or equal to; greater than or equal to. For checking whether objects are the same. These result in two special Boolean values: True False In common with many languages, these also evaluate to numbers, False being zero and True being one, but also, numbers can evaluate to Booleans, with zero being False and any other number (including negatives) being True. # Note capital letter
Bitshift operators >> << Bitshifts, e.g. 1 >> 1 == 0 (00000001 >> 1 == 00000000) 1 << 1 == 2 (00000001 << 1 == 00000010) & ^ | Bitwise AND, XOR, OR 00000001 & 00000011 == 00000001 00000001 | 00000010 == 00000011 00000001 ^ 00000011 == 00000010 ~ Bitwise inversion ~00000001 == 11111110
Useful functions abs(x) Returns the absolute positive value, or the magnitude for a complex number. round(number, ndigits) Rounds number to (optional) ndigits decimal points and returns it. If ndigits not there or None, returns nearest int. Watch out for values where a ".5" or equivalent at other magnitudes is being rounded: rounding can be up or down because of storage precision issues.