Variable assignment Dr Andy Evans [Fullscreen] 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: >>> print(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 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 Note that this is not the same as: >>> a = 10 >>> b = 10 Which creates a second "10" and attaches it to b only. In fact, what is going on is slightly more complicated. Literals are sometimes reused for multiple values in some languages. For example, in many languages, text is reused where possible, because it uses up a lot of space, so in: a = "hello world" b = "hello world" chances are, it'll be the same "hello world" until it is altered to b = "hello globe" and then it'll be a different literal. This helps keep memory efficiently used. 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 they were once attached to the same value, 10 >>> 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. >>> 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 either a = 10 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. We tend to use i, j, and k for counters because in the first third generation language, FORTRAN, letters had to be used for certain variables, and certain types of number could only be assigned to certain letters. Integer values (whole numbers) could only be assigned to the letters from i (for integer) onwards. For this reason, people still use i, j, k for counting things (but not lowercase "L" -- it looks too much like a one). 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... Example import tkinter 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() Note how little code it takes, and how (with the exception maybe of add_cascade) you can kind of understand what it does without really knowing too much about how it does it. These are two key reasons people like Object Orientated programming languages. Example import tkinter 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() The "dot operator" (" . ") is used to say "look inside this object and find this code (in this case a procedure). Every time you see the dot operator, it is object orientation working. 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. Dynamic languages calculate on the fly what static languages do at compilation time. Makes them more flexible but less efficient. Static languages: variables associated with a single data type. Often associated with manifest typing: saying what kind of variables you're going to use before/when you first use them. Sometimes called the variable declaration or description. This: allows the system to set aside memory for the value; means the system can check you're using the type of variable you think you are. Here's a Java declaration and assignment: int a = 20; Dynamically languages allow a variety of types to be associated with a variable. Often associated with implicit typing: you don't have to define the type, and frequent type inference: the system works out which type is being used. A nice clear discussion of this is https://pythonconquerstheuniverse.wordpress.com/2009/10/03/static-vs-dynamic-typing-of-programming-languages/ 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. One efficient solution, for example, is to work out the type when the variable is first used and store the type with the label. Sometimes, this involves making a new label (not that you need to know this): a = 10 # First "a" label. a = 20 # New "a" label. a = "hello world" # Another new "a" label. One way some languages deal with a function taking in a variety of types of variable is to compile several different versions of the function for different uses, for example. 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 + 4 This means this is fine: a = 2 a = a + 4 Note that for functions, there is a difference between: a = dir # Use "a" as an alias for "dir" a() # which we can then call. and a = dir() # Run "dir" and get some # result back from it, print(a) # assigning the result to "a" #we can then print. Augmented assignment Instead, Python has the augmented assignment operators: x += 1 # same as x = x + 1 x -= 1 # same as 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. For the record, specifically they can't use the expansion operators * or ** and they can't be used to assign to lists etc. We'll what these mean later in the course.