3.2.2. Common Python commands

We’ve now learnt how to make and use a virtual environment, and have written some simple Python programs.

Part 1 of the notes introduced a wide range of fundamental programming concepts, often giving examples using Python code. We’ve already seen some of these concepts, such as functions. In this part of the Lab we’ll take a look at some of the others.

3.2.2.1. Variables

  1. Make a new Python file with any suitable name. Make sure you save it in your Lab C folder.

  2. Enter the commands below into this file:

    # %% Define variables of different types
    num = 2
    pi_ish = 3.1415
    name = "alex"
    check = True
    blank = None
    

    These were the first examples of variables we introduced in Part 1 of the notes.

  3. A hash # in Python indicates the start of a comment. # %% is a special type of comment that indicates the start of a code cell in some Python editors, such as Visual Studio Code. This is exactly the same as the cells we encountered in Lab B. We can run each cell independently. This is useful for testing small sections of code without having to run the entire program.

    Click on Run Cell which appears above the # %%.

    Running a Python cell in VSCode

    Screenshot of VSCode, software from Microsoft. See course copyright statement.

    This will start an interactive session, and once the code has finished running it will display the values of the variables in the Jupyter variable explorer.

    Variables in VSCode

    Screenshot of VSCode, software from Microsoft. See course copyright statement.

  4. Add the code below to your file.

    # %% Simple variable combinations
    five_ish = num + pi_ish
    full_name = name + " casson"
    
    logical_and = check and False
    logical_and2 = check and True
    logical_or = check or False
    logical_or2 = check or True
    

    Run the cell and view the results in the variable explorer, which should look like the below.

    Operations in Python

    Screenshot of VSCode, software from Microsoft. See course copyright statement.

    The operator + does different things depending on the data type of the data given to it.

    • When given two numbers, num and pi_ish, it adds them together. If you look closely at the variable explorer, you’ll see that five_ish is a float data type, because one of the inputs was a float. num is an integer data type, but an int can be automatically converted to a float when needed. (Remember that an int can’t store numbers with decimal places.)

    • When given two strings, name and " casson", it concatenates (joins) them together. You get one longer string, "alex casson" here.

    The operators and and or are logical operators that operate on boolean data types. They work in exactly the same way as the logic gates that you’ve learnt about in your digital electronic course.

  5. Add code to your Python file to work out the output q of the digital circuit below when a = 0, b = 1, c = 1 and d = 0.

    Digital logic circuit

3.2.2.2. Objects

  1. In your Python file, make a list by adding the code:

    # %% Lists
    my_list = [0, 4.5, "hello"]
    

    A list is a data structure that can hold multiple values. The values in a list can be of any data type, and can even be other lists.

    A list storing items is also an object. There are a number of built-in methods that can be apply to the list. This may tell us information about it, or help us to add or remove data, or so on.

    We’ll learn about making our own objects in Lab G. For now, we just want to remember that pretty much everything we enter into Python is actually an object and has built-in methods that we can use with it.

  2. In VSCode, enter the below, but don’t try to run the code yet.

    # %% Lists
    my_list = [0, 4.5, "hello"]
    my_list.
    

    You should see that the auto-complete appears and displays a list of the available methods for this object called my_list. For example there are methods to add items to the list, or to change the order of items in the list.

    Autocomplete in VSCode showing the methods available for an item

    Screenshot of VSCode, software from Microsoft. See course copyright statement.

  3. Now enter the code

    # %% Lists
    my_list = [0, 4.5, "hello"]
    my_list.append(5)
    my_list.reverse()
    

    Run it, and see the results in the variable explorer. Check the contents of my_list match what you expect.

  4. There’s much more that you can do, and likely will need to do, with objects. The aim here is just a brief introduction. Remember that pretty much everything in Python is an object, and has methods that you can use with it.

    From earlier in the lab, your code file should contain a variable called five_ish. This is a variable, which is actually stored as an object and so has methods associated with it. Enter:

    five_ish.
    

    to let the autocomplete show the methods that are available for manipulating this data. Experiment with a few before moving on.

3.2.2.3. Conditionals

Conditionals let us change the flow of a program based on the values of variables and objects.

  1. Add the code below to your Python file and run it. What value of c do you get, and is it what you would expect?

    # %% Conditionals
    a = 0
    b = 3
    if b == a:
        c = 7
    elif a > b:
        c = -7
    elif a < b:
        c = 0
    else:
        raise Exception("Something must have gone wrong!")
    

    There are a few points to note with this example.

    1. There are four different branches here, comparing the values of a and b. Only one branch will execute, the first one which is matched.

    2. To check whether a and b are equal, we need to use two equals signs ==. A single equals sign = is used to assign a value to a variable, not to compare two values. Try changing the line to if b = a: and see what happens when you run the code.

    3. We’ll cover error handling in Lab H. In general, we would recommend using if and elif to cover every case you might be interested in, and then else to catch any unexpected cases and raise an error.

    4. Note that in the solution to the digital logic circuit above, we already used variables names a, b, c. There they were used to store True or False rather than numbers. Remember that Python is dynamically typed, we can change what’s stored in our variables at any time. However, this can lead to confusing code - if you later write a block of code that is still expecting a, b, c to store logic values, and they now store numbers, you might get strange behavior. Either give your variables unique names, or ensure variables with the same name are in different scopes so they don’t interfer with one another.

  2. The example above compares numbers, but you can compare lots of different things. Add the code below to your script and run it:

    if name == "alex":
        print("True")
    
  3. By searching the Internet or otherwise, add an if statement to your code that displays Also true if name contains an x.

  4. You can also use logical statements such as and, or, and not to build up more complicated comparison cases. Add the code below to your script and run it. (This assumes that the result from your digital logic example above is stored in a variable called q).

    if name == "alex" and num == 2:
       print("Both true")
    elif name == "alex" or num == 2:
       print("One true")
    elif not q:
       print("q is 0")
    

    Note that the elif statements are only checked if the previous if or elif statement was not true. Only one of these outputs will ever be displayed.

  5. When you have lots of comparisons to do, using lots of if and elif statements can be quite cumbersome. Python provides a match syntax to allow some cases to be written more simply. For example, add the code below to your code and run it. Does it do what you expect?

    from datetime import datetime
    
    day = datetime.now().strftime("%A")
    
    match day:
        case "Saturday" | "Sunday":
            print(f"{day} is a weekend.")
        case "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday":
            print(f"{day} is a weekday.")
        case _:  # default case, runs if no others match
            raise Exception("Something must have gone wrong!")
    

3.2.2.4. Loops

Loops let us perform the same operation multiple times. This is very common in programming, with a common aim being to automate repetitive tasks.

  1. Add the code below to your Python file and run it.

    # %% For loops
    countdown = range(10,-1,-1)
    for i in countdown:
        print(f"{i}")
    print("Blast off")
    

    This is a fairly simple loop. countdown contains the numbers from 10 to 0. The for loop iterates through each of these in turn, gets the current number and puts it in a variable called i, and prints out the number.

    The in syntax can be a little confusing at first, as some of the operation is hidden behind the scenes. For any data type that stores multiple values Python has a rule for iterating over these multiple values. For a list, or range, or series of numbers or similar, this rule is built in and you don’t see it. The iterator simply says, get the first entry, e.g. countdown[0], then countdown[1], then countdown[2], and so on. Essentially, Python just knows that it needs to go through each item in the list or range in turn. This is in contrast to some other programming languages (particularly C/C++) where you need to tell the program explicitly what to do differently on each loop, which element to get, and so on.

    You can make your own custom iterators if you want different behavior, or are working with your own data types, but we won’t cover those here.

  2. Make a for loop that displays the numbers 0 to 10 going upwards. That is, displays, 0, 1, … 10.

  3. For a more complicated loop, copy and paste the code below into your file and run it.

    marks = {"a": 100, "b": 100, "c": 75, "d": 10}
    
    for student in marks:
        if marks[student] < 40:
            pass_status = "failed"
        elif marks[student] > 40:
            pass_status = "passed"
        else:
            raise Exception("Something must have gone wrong!")
    
        print(f"{student} has {pass_status} with {marks[student]} marks.")
        return pass_status
    

    The for loop iterates through each student, and the if statements check whether they passed or failed the course, changing the message that is displayed as appropriate.

    This uses a dictionary to store student names (here "a", "b", etc.) and their marks. The name is the key, and the mark is the data stored associated with that key. The iteration rule for a dictionary is to go through each key in turn.

    Make sure that you understand this code before moving on.

  4. The code above contains a logic error. There is no bug in the code, it will do exactly what it is told to do, but there is a mistake in what we’ve asked it to do. It can be hard for our debugging tools to spot such issues, because the issue is more with us rather than with the code. Identify this issue and fix it.

3.2.2.5. Reading and writing data to/from files

So far we’ve mainly interacted with our Python programs by typing things in. It’s very common that we also want our Python to read information from other files. For example, maybe we’ve run an experiment in the lab and saved the results. We want to load these in to Python to analyze them. Equally, it’s very common that we want to save the results generated by our Python program to a file. Later on, this lets us see the results just by opening the file, rather than by having to re-run the code.

There are lots of different file formats, for a example Word files, Excel files, and so on. Python has specialist functions for working with many of these particular types of file, and we’ll see a number of these as we work through the course.

There are also some very basic commands that let you read and write simple files, which we’ll look at here.

  1. In your Lab C files you will see that we’ve included a file called data.txt. Add the code below to your Python file and run it. The code will open the file, and read the contents into a variable called data.

    # %% Read data from a file
    filename = "data.txt"
    with open(filename, "r") as f:
        data = f.read().splitlines()
    

    View data in the variable explorer to check that it contains what you would expect.

    To go over this code:

    1. with is known as a context manager. We discussed previously that if we use a resource on a computer, when we finish we have to give it back. Otherwise we’ll keep using up system resources we don’t need. Here we’re opening a file, and so we need to close it when we’re finished with it. The context manger takes care of doing this for us. If you don’t use a context manager, you need to remember to call f.close() when you’re finished with the file.

    2. open(filename, "r") as f opens the file, and here we’ve asked to read "r" from the file. f is the name of where we’re storing the opened file to interact with it. You can call this whatever you like, but we’ve chosen f.

    3. f.read().splitlines() reads the contents of the file, and splits them into a list where each entry is one line from the file. We don’t have to use splitlines(). There are other methods such as .readlines() which return similar but slightly different results.

  2. When you run the code above, what are the contents of data[2]?

    You can convert between data types using built-in functions such as int(), float(), and str(). For example, to convert the third line of the file to an integer, you would use int(data[2]).

  3. To write data to a file, the process is very similar. Add the code below to your Python file and run it. This will write some text to a new file called output.txt.

    # %% Write data to a file
    output_filename = "output.txt"
    with open(output_filename, "w") as f:
        f.write("Hello world!")
    

    Check that the file output.txt has been created in your Lab C folder, and that it contains what you would expect.

3.2.2.6. Extending the RC circuit example

In the first part of this lab we finished by making a script that would simulate a simple RC circuit. It asked the user to enter a frequency, and then it calculated the output voltage magnitude and phase at that frequency. The code to do this is repeated below if you need it.

  1. Make a new Python file with any suitable name.

  2. Modify the code above so that instead of asking the user to enter a single frequency, it reads the information from a file.

    1. In your Lab C folder you’ll find a file called frequencies.txt which contains a frequency to start at, a frequency to end at, and a step size to take between each frequency to test. (It also contains some text indicating which number is which.) Read these values from the file.

    2. You can assume that the numbers will always be integers.

  3. For each frequency tested, have Python display the frequency, and the magnitude and phase of the output voltage. Display the frequency to 1 decimal place, and the magnitude and phase to 3 decimal places.

We’ve kept this task fairly open ended for you to think about how you want to approach it. You’ll likely need to look up some functions, on the Internet or via AI, to figure out how to carry out each step. A number of different modifications will be needed in order to achieve the functionality.

  1. Check in your code to Git before moving on. The instructions are the same as in the first part of this lab.