Getting Started with Spyder 4

This guide is obsolete. Please see my updated guide:

Spyder is a Python Integrating Development Environment (IDE) which has a similar user interface to Matrix Laboratory (MATLAB) which is a Commercial product commonly used in the physical sciences and engineering fields. Python and the Spyder IDE are open-source and can be freely downloaded using the Anaconda Python Distribution.

This particular guide examines the core concepts behind the Python programming language using the Spyder IDE. Additional guides examine the numeric python library (numpy), the plotting library (matplotlib) and the Python and data analysis library (pandas). Python with these common data science libraries can be used to replace the commercial product MATLAB for most applications. This guide is geared at beginners who want to learn scientific computing and those that are transferring from MATLAB.

Video

Installation

If you haven't already installed Python and Spyder 4 using the Anaconda Installation see.

Using the Console

We can use the Spyder Console like an ordinary calculator. The Console allows us to type in lines of code one by one.

In this case I am going to type in the value.

1

In order to execute the line of code press return .

The console will display what was input In [line number] and what was output Out [line number]. In both cases the value shown is the very basic 1.

To access the previously used command we can use the up arrow key . We can then scroll up and down through all the previously typed in commands.

Variable Assignment

Python is an object orientated programming language. In python the = sign is the assignment operator. The value to be assigned is on the right hand side of the assignment operator while the object name is on the left hand side of the assignment operator.

obj_name=1

Object names or variable names are usually always in lower case letters. Numbers can be used alongside the underscore (instead of a space) however the object name should not begin with these.

Note the difference between Line 2 and Line 1. Line 1 shows an output because no object or variable name was assigned. Line 2 on the other hand just assigns the value to the variable name obj_name.

Variable Explorer

Once an object or variable is assigned, it is created and details about it are shown on the variable explorer.

In this case we can see that the Name is obj_name and the Value is 1 as expected. The Type is an int which is an abbreviation for an integer (whole number) and the Size is 1 meaning it is a scalar.

Variable Reassignment

We can reassign the value of an object name. For example:

obj_name=obj_name+1.5

Where the . represents a decimal point.

The code above may be confusing on first glance however it is commonly used. The expression on the right hand side happens first before the assignment occurs. In this case the original value of obj_name is 1 and so the value 1+1.5 is calculated which gives 2.5. This new value of 2.5 is assigned to obj_name using the assignment operator =.

If you are observant, you will have noticed that when obj_name=1 that it was an int however now that it is updated to 2.5 and contains a decimal point it is now a float. float is an abbreviation for a floating point number which is essentially a decimal number. Under the hood the difference between these is more substantial, due to the way a computer stores values in its memory. However in practice a float and an int can be interacted with one another and the result in most cases will be a float.

Scripts

Opposed to individually executing each line one by one in the Console we can create a script of multiple commands.

By default it won't be saved which can be seen by the file name on the tab ending in a * and the fact that it is called untitled3.py

Select File→Save As:

Select your folder in this case I will select a Python folder within documents. Then name your script file, in this case I will label the file example. The .py extension will automatically be added when the file is saved.

You can see the folder and location of the script file.

Once saved, we can now run the script. Information will be given in the console stating the script file has been run.

The print Function

To the left hand side of the script file are line numbers. Note that on line 1, the code.

1

Displays nothing in the console when the script file is ran and because it is not assigned to a variable name, it does not show up on the variable explorer. Therefore as a user we have no idea whether this code was executed or not.

Code in the script file is not printed to the console by default. If we want it to display we can explicitly use the function print.

Note: In MATLAB every line is printed by default in a script. MATLAB syntax requires a line to be manually suppressed using the semi-colon. Python syntax isntead requires a line to be explicitly expressed using the print function.

print

The value to be printed is enclosed in parenthesis. In this case the value to be printed is the solo positional input argument (we will cover input arguments in more detail in a moment).

Strings

So far we have only looked at numerical data (int and float) however in other cases we may want text. The datatype str is an abbreviation for a string of characters. As variable names are also strings of characters we need to differentiate text input from variable name. To do this we enclose the text in quotations. Note the Spyder IDE highlights strings in green so we can easily identify them.

obj_name1='obj_name1'

As we can see on the variable explorer. The Name is obj_name1, the Type is str and the value is obj_name1 (the variable explorer doesn't display the quotations).

It is possible to either use single or double quotes to enclose a string however double quotes should be used if the string contains a single quote within it:

"Philip's"

Or alternatively single quotes should be used if it contains a double quotation within it.

obj_name3='She said "this"'

In some cases the str may contain both single and double quotes, in which case we need to use the special character \ in front of the quotation to indicate that it is part of the string.

obj_name4='Philip\'s \"amazing\" guide'

Note this character also works with other characters \n will give a new line, \t will give a tab and \\ will give \.

The string can be placed as the positional input argument within the print function.

print('amazing')

Input Arguments

If you call a recognized function with open parenthesis, a pop-up balloon will display giving information about its input arguments.

Input arguments are contained within the parenthesis and typed one by one using a comma to separate one from the other.

function(value1,value2)

There are two types of input arguments positional and keyword input arguments.

Positional input arguments must be called at the start, in the order given for example:

function(value1,value2)

And keyword arguments can optionally be called once the positional input arguments are all listed.

function(value1,value2,kw3=value3)

To do this the name of the keyword input argument must be specified and then the assignment operator will be used to set it to a desired value. If the keyword argument is not specified the default value will be taken.

If we look at print. We can see we have a solo positional keyword input argument and we have the optional keyword input arguments sep, end, file and flush.

This image has an empty alt attribute; its file name is image-183.png

Let's demonstrate this. We will print the value 'amazing' three times however in the second time, we will change the end to '\n\t' which will give a new line and a tab opposed to just a new line.

print('amazing')
print('amazing',end='\n\t')
print('amazing')

This is seen in the Console.

Getting Help

We can use the ? to get help about an object such as the function print.

? print

This will display all the help in the console.

There is also a help tab however and it has a search box at the top.

We can also highlight the function and press [Ctrl] + [i] which will automatically inspect the currently highlighted text and look up it's help documentation. For instance if we change the code to:

print('amazing')
print('amazing',end='\n\t')
len('amazing')

Then we get information about the len function (an abbreviation for length).

The len Function

If we run this code we see nothing and this is once again because we haven't assigned the output to a variable name or enclosed it within a print statement.

Let's print the value:

print('amazing')
print('amazing',end='\n\t')
print(len('amazing'))

Note that we have a function as an input argument for a function. In order to show the coder what's going on Spyder automatically highlights the matching bracket. Here you can see the two outer parenthesis belong to the function print and the two inner parenthesis belong to the function print.

Many functions have a return statement. If len is assigned to a variable, it will return the value of the number of characters in the string (length) however if print is assigned an output it will return a different class NoneType (which essentially means the variable name is assigned to something that doesn't exist).

a=print('amazing')
b=len('amazing')

The input Function

We may in some cases need to gather input from a user and we can do this with the input function. This takes a string as a single positional input argument which prints as a prompt to the console.

We can demonstrate this using the following:

name=input('What is your name?')
print(f'Hi {name}, welcome')

Within the print statement we are using a formatted string. This strings begin with f (f for formatted) and the variable name is enclosed in {} as a place holder within the formatted string. When executed the value of the variable will be used in its place.

If we execute this code, it hangs on a prompt until the user inputs their string of text (no quotations are required because input always expects a string of text) and presses .

Once the user does this the formatted string will continue.

Note in the above there is no space after the question mark of the prompt. It is easier to read if there is, a full stop can also be added to the formatted string.

name=input('What is your name? ')
print(f'Hi {name}, welcome.')

We can now try and do some basic arthritic with a print statement.

number=input('Input a number. ')
number2=number+2
print('Your number plus 2 is {number2}')

However when we run this code we get a TypeError: can only concatenate str (not "int") to str.

What essentially happened here is:

line 1 returned number='5'

So line 2 tried to perform an addition of '5'+2. i.e. addition of a str and an int number because these are different data types the addition method does not make sense and the error above was given. We can use the classes int, float and str to convert an object to an int, float or str respectively (at this stage you can just think of these classes as conversion functions).

Note how the result is a float because it has a decimal point.

The del Function

The del function can be used to delete a variable for example let's delete the variable a

del(a)

As you can see it is now removed from the variable explorer.

Clearing the Console

To clear the console, you can either right click it and select clear console.

Or if your mouse is clicked into the console the keyboard shortcut [Ctrl] + [L] will clear the console. Note the line number will still be current (in this case 25 as it was 24 before and the keyboard shortcut was taken as an additional command).

[Ctrl], [Alt] and [R] can be used to remove all variables.

Restarting the Kernal

If we want to instead start completely fresh by removing any variables created, clearing the console and beginning at line 1 we can go to Console and Restart the Kernal.

Note the script file will be uninfluenced. It can be closed and a new untitled script file will display.

This has a shortcut key [Ctrl] + [.] which you can use if clicked into the Console.

Errors

In the following code we are trying to print the variable a, but we have not defined the variable a.

print(a)

As a result there is a red x on the script highlighting something is wrong.

We get the NameError: name 'a' is not defined when running the code:

Likewise if we forget to close a bracket we get another warning.

a=1
print(a
print(a)

We get a SyntaxError: invalid syntax when we try and run the code.

Comments

Lines of code beginning with a # are comments and ignored by Python. A comment can also in some cases be placed at the end of a line.

If you want to comment out or uncomment out multiple lines of code you can highlight them and go to Edit and then select Comemnt/Uncomment. This also has the shortcut key [Ctrl]+[1].

Cell Breaks

To start a section break (or new cell) use.

# %%

For example:

# %% Section 1 - Create Variables
a=1
b=2
# %% Section 2 - Print Variables
print(a)
print(b)

Note that the currently selected cell is highlighted in yellow.

You then have the option of running the entire script, running the current cell, running the current cell and then proceeding to select the next cell.

Zero Order Indexing

We can use the function len to look at the number of characters in a str (length of a string).

a='amazing'
print(len(a))

The value returned is 7 as there are 7 characters.

When we count we use the decimal system, which is based on the fact that we have 10 fingers. However in normal every day use we don't proscribe the 10 digits to our 10 fingers, taking the first finger as 1 and going up with the tenth finger being proscribed double digits.

In computer science we often use zero order indexing opposed to first order indexing, meaning we count from 0 and as a result we count up to but don't include the value. For instance counting from 0 to 10 gives us 0,1,2,3,4,5,6,7,8,9.

Note: MATLAB is one of the few programming languages that use first order indexing which gives a disadvantage when it comes to programming for example looping.

Returning to the string. We can index an individual letter from it using square brackets.

a='amazing'

For instance if we want the 0th and 6th Index (6 is the last index, as we go up to the length in integer steps of 1 but don't include the last value of 7).

a='amazing'
print(a[0])
print(a[6])

We can also index using slices. For this we use the colon. The colon uses zero order indexing, so the index to the left hand side of the colon is inclusive of the value and the index to the right hand side of the colon is exclusive of the value.

a='amazing'
print(a[0:3])
print(a[:3])
print(a[:])
print(a[5:])

a[0:3] will look at the 0th, 1st and 2nd index.

a[:3] if the lower index is not selected, then slicing will occur from the lower limit 0.

a[5:] if the higher index is not selected, then slicing will occur up to but not including the last value of length of the string len(a).

a[:] if the colon is used without any value then a copy of the string will be made.

Methods

When we assign a str to a variable name.

a='amazing'

What we are doing in short is the following.

a=str('amazing')

We are creating the object a which is an instance of the class type str. A class can be thought of as a set of blueprints for an object. The object or instance of the class will acquire a number of functions that belong to the class type. A function belonging to an object is called an object. A list of methods available from the object can be scrolled through by typing in the object a followed by a dot . and then a tab .

We can use the method upper as an example to convert the string to upper case. We can type it with open parenthesis to view the input arguments (there are none in this case).

a.upper()

We can assign it to a new variable name.

b=a.upper()

We can then use the method lower which will give the original string.

b.lower()
amazing

Or we can opt to just capitilize the 0th index using the method capitalize.

a.capitalize()
Amazing

We can look at the method count which requires a positional input argument in the form of a sub string of the string being looked at.

a.count('a')
2

Because there are 2 occurrences of 'a' in the word 'amazing'.

We can also look at the method replace, here we see that there are two positional input arguments, the old value (in the form of a sub string) and the new value (in the form of a sub string). The keyword input argument is set to -1 meaning that all occurrence of the old value will be replaced.

We can for example replace all occurrences of 'a' with 'e'.

a.replace('a','e')
'emezing'

For the string we can see that most the methods for example capitalize, lower, upper, startswith, endswith, count, find, index, replace and join are all related to text which is expected for a string.

We can now make a different class using the code.

a=1

Which is a shorthand notation for:

a=int(1)

If we type in the object name and follow it by a dot . and tab we once again see a list of methods and attributes available to the object.

For example the method conjugate finds the complex conjugate value.

a.conjugate()

Because this number has no imaginary component, it returns the same value 1.

1

An attribute can be thought of as an object that belongs to another object or better put an object that is referenced with respect to another object. The real component and the imaginary component are each numbers i.e. objects in their own right. They can be accessed using the attributes real and imag.

a.real
a.imag

This returns the values 1 and 0 respectively.

1
0

Because attributes are themselves objects, in this case both belong to the int class with the values 1 and 0. Other attributes and methods can be called from them.

For example we can call the method conjugate, to get the complex conjugate of the real component a.real.

a.real.conjugate()

Special Methods

We have seen that the class int and the class str have different methods available. We also seen earlier when we used the function input that we could not add an int to a str. This is because the + key is a method and it is defined differently for each class.

If we create two instances of the class int, a and b respectively

a=1
b=2

We can add them together.

a+b

And get 3 as expected.

Behind the scenes we are using a special method of the int class __add__ (double underscore before and after). This is hidden from the list of methods which display when we use dot . and tab however we will type it explicitly in this case with open parenthesis to see the input arguments.

Here we see that the only input argument is value and the return is self+value. In this case the method is being called from the object a so self refers to a. We can find a+b by typing in.

a.__add__(b)

And once again get 3 as expected.

Now in contrast, let's look at instances of the class str instead.

a='apple'
b='banana'

When we use the + operator we instead perform the str method __add__ which performs a concatenation (adds the characters of b to the end of a).

We will now look at these special methods for numerical data types and then for strings.

Numerical Classes (int and float)

For numerical data we can use the following notation to carry out most basic operations in a calculator.

KeyDescription
=The assignment operator
0,1,2,3,4,5,6,7,8,9the numbers
.the decimal point
+additional operator
subtraction operator
*multiplication operator
**exponentiation operator
/division – returning a float
//division – returning only a complete integer
%division – returning the remainder as an integer
()parenthesis – do the operation in the brackets first
1+2
3
1-2
-1
2*3
6
2**2
4
2/2
1.0

Note float division always returns a float, indicated by use of the decimal point.

5//2
2
5%2
1

Integer division can be used to find the total number of times a value divides into another value and an associated remainder can be found. In this case 2 remainder 1.

Parenthesis can be used to place precedence on a mathematical operation. By default multiplication and division operations are carried out before addition or subtraction. So this gives 3 times 5 plus 2 which is 17.

2+3*5
17
(2+3)*5
25

The parenthesis instead instruct in carrying out the addition first so this is 2 plus 3 which is 5 times 5 which is 25.

There are also a number of operations to perform reassignment. For example let's look at reassigning the value of a by incrementing it in integer steps of 1.

a=1
print(a)
1
a=a+1
print(a)
2

We can instead for shorthand use the += operator which in this case will increment the value of a by 1 and reassign this new value to a.

a=1
print(a)
a+=1
print(a)
1
2
+=in-place additional operator
-=in-place subtraction operator
*=in-place multiplication operator
**=in-place exponentiation operator
/=in-place division – returning a float
//=in-place division – returning only a complete integer
%=in-place division – returning the remainder as an integer

String Class (str)

It makes less sense for these numerical operators to work on strings however as we have seen earlier the + operator performs string concatenation.

A string can also be multiplied by an integer number n using the * operator and will undergo concatenation with itself n times. For example we can use the following to concatenate 'amazing' to itself 5 times.

a='amazing'
5*a

Boolean Values

Another important class is the bool class an abbreviation for Boolean. There are two values.

a=True
b=False

If we return to a basic string, this time a string containing a numeric value.

a='1'

We can use dot . and tab to access its available methods. We can see there are a number of methods beginning with is.

a.isnumeric()
a.isdecimal()
a.islower()
a.isupper()
a.isalnum()

Each of these questions return a bool, the statement is either True or False.

Now let's create two variables, one that is a string of a number and one that is a string of a letter.

a='1'
b='a'

These have a different outcome when the method isnumeric is used. This plays an important role when attempting to convert the object from an instance of the str class to an int class for instance. The value that is numeric can undergo the conversion and the value that isn't fails to undergo the conversion giving a ValueError: invalid literal for int() with base 10: 'a'

Comparison of Two Variables

There are a number of conditional logic statements that can be used to compare two variables, for instance two numbers. These statements yield a bool.

Logical OperatorDefinition
==equal to
!=not equal to
less than
<=less than or equal to
>=greater than or equal to
greater than
isis (the same object in memory)
is notis not (the same object in memory)

Supposing we create two variables.

a=1
b=2

We can use the equal to operator == to compare them.

a==b

This returns the bool value False.

Note the differences between equal to == and the assignment operator =. If we type in

a=b

Then the value of a is reassigned to b.

Now the statement.

a==b

Is True.

Now supposing we start with.

a=1
b=2.0

We can check whether a is equal to b.

a==b
False

a is not equal to b.

a!=b
True

a is greater than b.

a>b
False

a is greater than or equal to b.

a>=b
False

a is less than b.

a<b
True

a is less than or equal to b.

a<=b
True

Floats, Significant Figures, Scientific Notation and the round Function

Care should however be taken when comparing a float with another float especially when a calculation is used. The following code may seem to be very basic.

a=0.1+0.2
b=0.3

Intuitively a is equal to b should be True however the value returned is False.

a==b
False

The reason for this is rounding which can clearly be seen when we look at the variable explorer. The value of a is given to its 17th decimal place and its 17th decimal place is non-zero. This is due to the way computers store numbers. We have ten digits (decimal system) whereas the computer stores numbers using the binary system (what can be thought of as a series of on/off boolean switches).

An analogy with the decimal system is the concept of (1/3)+(2/3). The value (1/3) in decimal form is recursive 0.33333333333333333 and the value (2/3) in decimal form is also recursive 0.66666666666666666. Combining (1/3)+(2/3) together when represented in this way can give 0.99999999999999999 which is just short of 1.

For most practical purposes we do not measure values to their 17th significant figure and we can address this by using the round function, we can once again look at its input arguments by typing in the function with open parenthesis.

In this case we can reassign the value a to itself rounded to 3 decimal places.

a=0.1+0.2
a=round(a,3)
b=0.3

This makes the comparison.

a==b
True

In most cases we deal with numbers relative to each other in magnitude however sometimes we will have to deal with very large numbers and very small numbers. For example in physics the speed of light is approximately 30000000 m/s and the distance from the sun to the earth is 150000000000 m. When dealing with these numbers it is all to easy to mistype an additional 0 or mistype by missing a 0. Instead scientific notation is used which splits the number into a mantissa and exponent (power of 10).

So the speed of light would be taken to have a mantissa of 3.000 and an exponent of 8.

30000000
3000000×10
3000000×10^1
300000×100
300000×10^2
⁝
3.000×100000000
3.000×10^8

Likewise the distance from the sun to the earth would be taken to be.

150000000000
1.500×10^11

To type these in python we use e to split the mantissa and exponent.

v=3.000e8
d=1.500e11

We can use the formula time=distance/speed to calculate the time in seconds that it takes light from the sun to reach the earth.

v=3.000e8
d=1.500e11
t=d/v

We get about 500 seconds.

Now the concept of a (10 km = 10000 m = 1.0×10^4 m) run may seem a relatively large distance to us however if we compare it to the distance from the earth to the sun, it is insignificant and as we can see doesn't influence our calculation much.

v=3.000e8+1.0e4
d=1.500e11
t=d/v

In other words a larger number + a small number doesn't deviate the large number by much.

It is also possible to write a very small number in scientific notation, for example the universal gravitation constant is 0.0000000000667 m^3 kg^-1 s^-2 which once again has so many 0 that it easy to mistype. We can instead type it in scientific notation.

0.0000000000667
0.000000000667×0.1
0.000000000667×10^-1
0.00000000667×0.01
0.00000000667×10^-2
⁝
6.670×0.00000000001
6.670×10^-11

This number can be used with the mass of the earth 5.972×24 kg and radius of the earth 6371^3 m to calculate the gravity of the earth.

gcon=6.67e-11
me=5.972e24
re=6.371e6

We can use the basic formula to calculate the gravity of the earth by multiplying this gravitation constant by the mass of the earth and dividing by the radius of the earth squared.

ge=gcon*me/(re**2)

This gives 9.81 m s^-2 which is the correct gravity of the earth. This basic formula demonstrates briefly how a small number doesn't influence a large number much when added or subtracted but can be substantial when using division and or multiplication.

Conditional Code if, elif, else

We can take advantage of conditional logic and use if, elif (an abbreviation for else if) and else statements to execute code (or not) dependent on a condition. For conditional branching we use the colon : to begin a code block and each line of code belonging to the block is indented by four spaces. Since spacing is so important in the Python programming language it is helpful to enable the following settings within the Spyder IDE. Go to Tools and then Preferences.

Select Editor and then Show Indent Guides and Show Blank spaces.

We will start with an if statement. Let,s create a variable condition and set it to a boolean value. In this case True. We can now use the keyword if, to check a condition, in this case the value of the boolean of the object called condition and then a colon : to begin a new code block. Code belonging to the code block is indented by 4 spaces.

condition=True
if condition:
    print('if branch is True')

Because the condition is True we see the text within the print statement shown on the console.

Now conversely if we update the condition to False.

condition=False
if condition:
    print('if branch is True')

Then the code within the if branch is not executed and we do not see a print statement.

Now if we insert a line of code below this on line 4 and don't indent it we will see that it is outside the code block of the if statement and executed irrespective of the if statement.

condition=False
if condition:
    print('if branch is True')
print('I will run regardless of the condition')

We can follow the if branch with an else branch. The else branch begins with else and then a colon : to begin a code block. There is no condition following else (as by definition it is ran if the if condition is False and all other conditions are False).

condition=False
if condition:
    print('if branch is True')
else:
    print('else branch all conditions are False')
print('I will run regardless of the condition')

Now we can add an elif (else if) branch.

condition=False
if condition:
    print('if branch is True')
elif condition==False:
    print('elif branch is True')
else:
    print('else branch all conditions are False')
print('I will run regardless of the condition')

Here instead of specifying a variable that is a boolean we can use a conditional logic statement to compare the variable with a value. In this case the code in the elif branch is ran.

You can have multiple elif branches however one thing to note is that if an earlier condition is met, the code in its branch will be executed and the script won't bother looking at the conditions of later branches.

condition=False
if condition:
    print('if branch is True')
elif condition==False:
    print('elif branch is True')
elif condition==False:
    print('elif2 branch is True')
else:
    print('else branch all conditions are False')
print('I will run regardless of the condition')

In this case the second elif branch is ignored because the condition of the first elif branch was True and code belonging to this branch was accepted.

Now we can look at the following code.

value=4
if value>5:
    print('if branch is True')
elif value>4:
    print('elif branch is True')
elif value>=4:
    print('elif2 branch is True')
else:
    print('else branch all conditions are False')
print('I will run regardless of the condition')

Here we can see the if condition is False, the 1st elif condition is False and the 2nd elif condition is True (using the subtle differences between greater than or equal to versus greater than). As a result the code in the second elif branch is ran.

Now if we update the value to 6. Then if condition is True. Although all the conditions in the elif branches are also True because the if condition is True and is the top branch, only the code executed within it is ran.

value=6
if value>5:
    print('if branch is True')
elif value>4:
    print('elif branch is True')
elif value>=4:
    print('elif2 branch is True')
else:
    print('else branch all conditions are False')
print('I will run regardless of the condition')

It is also possible to created nested conditional branches.

value=6
if value>5:
    print('if branch is True')
    if value==5:
        print('value is 5')
    elif value==6:
        print('value is 6')
    else:
        print("I don't know the value")
elif value>4:
    print('elif branch is True')
elif value>=4:
    print('elif2 branch is True')
else:
    print('else branch all conditions are False')
print('I will run regardless of the condition')

Pay particular attention to the indent guides, line 2 begins a code block as it ends in a colon. The code belonging to it (line 3 and line 4) is indented by 4 spaces. Line 4 then begins a nested code block as it ends in a colon. The code in line 5 belongs to it and is indented an additional 4 spaces. As it is a nested within an additional if statement this means the total number of spaces before the line is 8.

The code highlighted in blue all belongs to a sub-branch of the outer if statement.

The arrows can be clicked to collapse each branch, this makes it more obvious that the other if, elif, elif and else branch are all together in the outer branch.

Looping for and while Loops

Sometimes we will want to do the same operation multiple times.

a='amazing'
print(a)
print(a)
print(a)
print(a)

We can automate the above using a for loop. To do this we need to create a loop variable, in this case we can create the loop variable i.

a='amazing'
for i

Now obviously in order to loop we need to increment this variable so want this variable to be within an object of multiple integers. We can get this by using the function range. If we call range with open parenthesis we can see that we can specify three positional input arguments a start integer, a stop integer and a step integer or if we only specify two input arguments the step is taken to have a value of 1 and if we only specify a single input argument the start is taken to have a value of 0.

When using a for loop, we once again begin a code block using a colon. The code belonging to the loop is indented by 4 spaces.

a='amazing'
for i in range(4):
    print(a)

In this case we see that we get the same output and that we have the loop variable i on the variable explorer.

The loop variable i has a value of 3 because once again we are using zero order indexing, which means we count up to 4 but don't include 4, with the integer value before 4 being 3. We can print the loop variable within the loop.

a='amazing'
for i in range(4):
    print(a)

Recall that we can use the function len to find out the length of a string and that we can index a letter into a string using square brackets. We can modify the loop to individually print the index number and the letter from the word.

a='amazing'
for idx in range(len(a)):
    print(idx)
    print(a[idx])

This is a bit cumbersome and for short hand we can loop using the string directly. In this case the loop variable l will automatically be assigned to letter as the loop steps through every letter in the string.

a='amazing'
for l in a:
    print(l)

The function enumerate can be used to get two loop variables the index and the letter respectively.

a='amazing'
for i,l in enumerate(a):
    print(i)
    print(l)

The for loop has a predefined number of iterations. The while loop on the other hand runs dependent on a condition. This makes it possible to setup infinite loops.

while True:
    print('Spam my Console')

To escape an infinite while loop use [Ctrl] + [c] while clicked into the Console. This will give a keyboard interrupt KeyboardInterrupt.

We can use a while loop to print every letter in a string however we will need to create a variable before beginning the loop (preallocate a variable) and then look at a condition involving the loop variable that is initially True so the loop begins. We then will need to alter the variable within the loop so it eventually changes making the condition False and the loop is broken out of. In this case we can create a variable i that is assigned to 0 and type in code so that it increments in steps of 1. We can use the function len to get the length of the string and have the condition so the value of i is less than this.

a='amazing'
i=0
while i<len(a):
    print(i)
    print(a[i])
    i+=1

How a Computer Stores Data

Computers store data in bits, which can be thought of as essentially binary switches. They have only two values 0 (False) and 1 (True).

0
1

We use the decimal system as mentioned earlier as we have 10 fingers (so arbitrarily created 10 characters to correspond to these).

0
1
2
3
4
5
6
7
8
9

When we run out of digits we add another digit.

10
11
12
⁝

In binary as there are only 2 digits this happens at the number we would consider 2.

0
1
10

We can use the function bin to convert a decimal integer to binary. For convenience we will use a for loop to see the first 12 numbers in binary. Here we convert both i and bin(i) to strings using the function str and use them as variables within a formatted string.

for i in range(12):
    print(f'{str(i)} : {str(bin(i))}')

The ob prefix indicates binary notation as you can see the decimal equivalent of 2 is 0b10.

This means we need 4 digits (which are referred to as bits in computer science) for the number 8. The more bits we use to represent a number means the more memory we use on a computer. It is common to group numbers over 8 bits (which is called a byte) because this gives us combinations on the order of 100 (actually 256 configurations, 0-255 in decimal).

This number set is called unsigned (because all are positive), 8 bit (because 8 bits are used) integers (because they are all integers).

The basic American Standard Code for Information Interchange (ASCII) maps these binary number configurations to what we recognize in the English as a character (number, letter, upper and lower cases and punctuation marks).

We can modify our for loop to use the function chr opposed to bin to see the character each binary configuration corresponds to.

for i in range(256):
    print(f'{str(i)} : {str(chr(i))}')

The first 32 commands are not necessary commands we would recognize but the hidden punctuation marks such as new line, new tab and carriage return when are used to communicate with devices.

The ord function can instead be used to calculate the numeric value which corresponds to a character.

These 256 levels are also used to control brightness of a Light Emitting Diode (LED) with 0 corresponding to a LED being fully turned off and 255 with the LED being a full brightness. Each pixel in a (black and white) computer screen can be thought of as a white LED.

Because the number 256 is 16 squared, it can also be presented as two digits with 16 characters. As our decimal system only uses ten 10, we need an additional six 6 characters so we take the letters a to f. This is known as hexadecimal notation. We can use the function hex to view each of these numbers in hexadecimal form.

for i in range(256):
    print(f'{str(i)} : {str(hex(i))}')

The ox prefix indicates hexadecimal notation as you can see the decimal equivalent of 250 is 0bxa.

To see color in electronics we utilize red, green and blue which correspond to the three primary colors our brain recognizes. The brain makes all other colors by mapping the relative intensity ratios of these three colors. Observe the three equally bright (to our brain) LEDs below. When all three overlap we see white (the light sensors in our eyes are saturated), when none are on we see nothing (black, the absence of light). A mixture of only red and blue creates magenta, a mixture of blue and green makes cyan and a mixture of red and green make yellow.

We use the hexadecimal notation with 2 characters corresponding to each primary color #ffffff to represent the three colors.

In some applications we want negative numbers also. If we use the same number of bits, we will half the magnitude of values as half the binary values will correspond to the positive numbers and half the binary values will correspond to the negative numbers. 8 bit unsigned therefore corresponds from -128 to +128 (up to but not including).

Floats are represented using a binary version of scientific notation. In 16 bit (half precision) float notation the first bit corresponds to the sign, the next 5 bits correspond to the exponent and the next 10 bits correspond to the mantissa. 11.5 (decimal) in 16 bit (half precision) float binary notation is.

Let's look at this in more detail. In +11.5 because the sign is positive, the first bit is 1.

Let's look at the integer part 11 next.

Let's look at powers of 2.

2**4=16
2**3=8
2**2=4
2**1=2
2**0=1
11//16=0
11%16=11
0b0xxxx
11//8=1
11%8=3
0b01xxx
3//4=0
3%4=3
0b010xx
3//2=1
3%2=1
0b0101x
1//1=1
0b01011

Let's look at the decimal part 0.5 next.

Let's look at powers of 2.

2**-1=0.5
0.5//0.5=1
0b0.1

Combining these together gives the following in binary notation:

0b01011.1

We now need to have the highest 1 in front of the decimal point. This gives the following in decimal scientific notation.

0b01011.1
0b0101.11×2^(0b1)
0b010.111×2^(0b10)
0b01.0111×2^(0b11)
0b1.0111×2^(0b11)

Because every binary value in float notation will begin with a 1 and the float notation wants to get the highest dynamic range from the number of bits available we don't want to waste a bit that will always have the same value. The 1 before the decimal point therefore is ignored so only the numbers after the decimal point are included in the mantissa. 0b1.0111

The float notation above is designed to get the most out the number of bits available and for this reason the sign takes up a separate bit by itself. The exponent on the other hand does not have such a large range of numbers and a result does not have a bit corresponding to the sign.

2**5=32

The 32 combinations are as a result split to give 14 corresponding to negative powers, a 0, 15 combination corresponding to positive powers and a combination corresponding to infinity. Moreover the exponents are adjusted to always be positive. As a result of this 0 is at position 15, giving a 15 offset. In this notation we must always specify the exponent as a positive number so an offset of 15 is applied. We had the power of 11 which is 3. If we add this offset it gives 18 which is.

bin(18)
0b10010

Giving.

This image has an empty alt attribute; its file name is binary.png

Float 32 gives a single bit for a sign, 8 bits for the exponent and 23 bits for the mantissa. The exponent has a zero order offset of 127.

This would make the exponent 127+3.

bin(130)
'0b10000010'

The mantissa would just have higher precision.

11.5 was selected as it was a nice number in binary notation. The numbers 0.2 and 0.1 are recurring which is why we got the rounding issue before.

0.2 in Binary
0.1 in Binary

In both cases the last digit is rounded up to 1 opposed to continuously recurring. This gives the discrepancy seen earlier where 0.1+0.2==0.3 is False.

It is not necessary to carry out conversions by hand routinely however it helps to do it once just to have an understanding and to avoid fairly common rounding errors.

Collections

So far we have only looked at scalar data types. Individual objects that are numbers (int, float), text (str) or boolean (bool). It is possible to group a series of these values into a collection. There are different types of collections.

The list

The most commonly used collection is called a list. This relates to a list used in every day life.

  • apples
  • bananas
  • grapes
  • oranges
  • pears

In python a list is enclosed in square brackets.

empty_list=[]

We can open double click the list in the variable explorer to open up in a separate window.

We can add a string to this list.

shop_list=['apples']

This list has a single item. We can see that this has an Index of 0, a Type of str, a Size of 1 (we will look at this in more detail later) and a Value of apples.

To add the next item to our list we need to separate it out from the first, to do this we need to use a separator (or delimiter) and we use the comma , to do this.

shop_list=['apples','bananas']

We can see that this has an entry at index 0 and an entry at index 1. We can add entries until we completely add all the items we want within the list.

shop_list=['apples','bananas','grapes','oranges','pears']

Within the script, the list can become hard to read if the list is very long. This would require quite a bit of scrolling to the right, so it is also possible to wrap the list up over multiple lines. In this case the script uses the opening [ and closing ] and knows that everything between these two belongs in the list. We can press after each comma , to begin a new line.

shop_list=['apples',
           'bananas',
           'grapes',
           'oranges',
           'pears']

Note that the Spyder IDE will automatically align each item in the list.

It is also possible to enter multiple lines in the console. To do this type in [Ctrl]+[↵].

Line wrapping should automatically continue when [↵] is pressed until the bracket is closed. Once the bracket is close [↵] will launch the code.

However [Ctrl]+[↵] can be used to always ensure that the line wrapping continues and pressing [Shift]+[↵] will stop the line wrapping and execute the code.

Indexing within a Collection

We can index by typing in the name of the list followed by the index enclosed in square brackets. With the list opened within the variable explorer, we can see the index. Index 2 is of type str with value grapes.

shop_list[2]

We can also index using a for loop. To get the index, we can use the function len with shop_list as an input argument to get the length of the list. We can then use the function range to get an index idx to loop over.

shop_list=['apples',
           'bananas',
           'grapes',
           'oranges',
           'pears']

for idx in range(len(shop_list)):
    print(idx)
    print(shop_list[idx])

However it is possible just to loop using the list to get the value val.

shop_list=['apples',
           'bananas',
           'grapes',
           'oranges',
           'pears']

for val in shop_list:
    print(val)

We can also use the enumerate function to get the index idx and value val.

shop_list=['apples',
           'bananas',
           'grapes',
           'oranges',
           'pears']

for idx,val in enumerate(shop_list):
    print(idx)
    print(val)

The last value of a list also has the index -1.

shop_list[-1]

And we can index in steps of -1 to the negative length of the list.

shop_list[-len(shop_list)]

We can use three input arguments for range: the start, stop and step so that we can look at indexing in reverse order.

shop_list=['apples',
           'bananas',
           'grapes',
           'oranges',
           'pears']

for idx in range(-1,-len(shop_list),-1):
    print(idx)
    print(shop_list[idx])

Like we saw earlier with a str, a colon : can be used to create a slice of a list. Recall that the lower bound is inclusive and the top bound is exclusive due to zero order indexing.

shop_list[0:2]

In the example below the lower bound 'apples' is included but the upper bound 'grapes' is not.

Like in the case of a str omitting a lower bound will assume slicing from the beginning 0 and omitting the upper bound will assume slicing to the end of the list. Indexing only using a colon : will therefore create a copy of the entire list.

shop_list[:]

We can also select every nth item in a list by indexing using a double colon followed by n. For example if we want every 2nd item.

shop_list[::2]

If we index every ::-1 item in the list, we get a reversed list.

shop_list[::-1]

Note because every index is a str. We can index into the list and then index into the str.

shop_list[2][::-1]

In the following example we select the second index from the list which gives the str 'grapes' and then index every negative 1 value of the str to reverse it giving 'separg'.

Nesting a collection

So far we have just looked at a list of the type str. however it is possible to create a list of multiple differing data types. For example.

random_list=['pie',3.14,3,True]

As you can see the Type differs for each item in the list and all are of size 1. It is also possible to nest a list within a list. Let's nest the list we created before as the last index.

shop_list=['apples',
           'bananas',
           'grapes',
           'oranges',
           'pears']

random_list=['pie',3.14,3,True,shop_list]

Note how the last index has a Type of list and Size of 5.

We can double click into this last index to get into the nested list.

We can index into the 4th index of shop_list, then we can index into the 3rd index of the nested list and finally we can index every negative 1 value to reverse the str.

random_list[4][3][::-1]

Concatenation of a list

The special methods defined in list class act in a similar way to those defined in the str class. The + operator performs concatenation and it is possible to duplicate the list n time using the * operator with a scalar n.

shop_list=['apples',
           'bananas',
           'grapes']

shop_list2=['oranges',
           'pears']

combined_list=shop_list+shop_list2

We can multiply shop_list2 three times using.

3*shop_list2

list methods

We can access a number of list methods by typing in the list name followed by a dot . and then tab .

Let's have a look at copy, this has no input arguments.

If we type the following into the console, the output value will be displayed.

shop_list2.copy()

We can also use the method index which takes a value as an input argument and returns the index if it is present in the list. Additional keyword input arguments start and stop are available to select a lower and upper index to define a subset of the list (although the documentation displays these as keyword input arguments, Python only works with these as positional input arguments).

For example we can use this to determine the index of the str 'pears'. This returns 1. If we instead search for the value 0, we get a ValueError: 0 is not in list.

shop_list2.index('pears')

We can use the method count to return the number of times a value occurs in a list.

For example if we duplicate each value in the list and then count the number of times 'pears' shows up we get the value 2 as expected.

shop_list4=2*shop_list2
shop_list4.count('pears')

Note if we return to using index, we only get the 1st occurrence in this case only index 1 shows (other indexes can be found using conditional logic, the append method and a for loop which we will look at).

shop_list4.index('pears')

These methods do not modify the original list. Some of the other methods will modify the original list instead of returning an output for example the reverse method which reverses the list.

combined_list.reverse()

Note this method does not have an output as it performs an in place update (mutates the instance self of the class list, where self is the name of the list the method is called from) which is why nothing is printed to the console.

The method sort, will sort the list (once again performing an in place update). It has a keyword input argument reverse=False meaning by default it will sort the values in order however can be easily changed to reverse the order by using the keyword input argument and assigning it to True.

combined_list.sort()
combined_list.sort(reverse=True)

Notice once again there is no output in the console. Instead the original list has been modified (or mutated).

The append method also mutates the list (performs an in place update).

Notice once again there is no output in the console. Instead the original list has been modified (or mutated).

shop_list4.append('berries')

If we assign this to an output. The output will be of the Type NoneType.

appended=shop_list4.append('bananas')

Note that the method append will append whatever value being appended to a single index at the end so it will create a nested list if the value being appended is a separate list.

shop_list4.append(shop_list2)

Concatenation can be used to concatenate multiple lists to create a new list. However the method extend may also be used which will extend the list.

shop_list4.extend(shop_list2)

We can remove a value from the list using the method remove which takes a value as a positional input argument.

For example we can remove the value 'bananas'.

shop_list.remove('bananas')

Notice that this is once again an in place upgrade and the list is mutated.

We can also use the method pop which by default removes the last item in a list. It has a default keyword input argument index=-1.

shop_list.pop()

Note the method pop has a return statement and the value popped in this case the str 'grapes' is returned.

It is also possible to clear a list using the method clear. This will make the list an empty list.

shop_list.clear()

The method insert works in a similar manner to append with the exception to requiring an additional positional input argument index.

For example we can insert shop_list2 at index 1 of shop_list.

shop_list.insert(1,shop_list2)

Note if we didn't want to nest the list, we could easily do this using indexing and concatenation. Since indexing a single element gives a str and not a list, it needs to be enclosed in square brackets to create a list with 1 str in it.

shop_list3=[shop_list[0]]+shop_list2[:]+shop_list[2:]

Let's create the following list which has duplicates itself three times.

shop_list=['apples',
           'bananas',
           'grapes']

shop_list2=['oranges',
           'pears']

shop_list2=3*shop_list2

Supposing we want all indexes which have the value 'pears', if we use index we only get the first occurrence. However we can initialize idx to an empty list. Then construct a loop using the range of the len of the list. Then using conditional log to check if the index is 'pears' and if it is append the index to the list idx.

idx=[]
for i in range(len(shop_list2)):
    if shop_list2[i]=='pears':
        idx.append(i)

Mutability

When we looked at the list methods above, we took advantage of the fact that we could mutate the list however this is not desirable in all applications and may lead to some unwanted side effects. Supposing we type in the following code.

shop_list=['apples',
           'bananas',
           'grapes']

shop_list2=shop_list

We may have think that we are creating a copy of the list assigning the values of the original list to a new variable name.

However what we are in fact doing is creating an alias for the list (there is only a single list just with two variable names). This means when we use a method such as clear.

shop_list2.clear()

That we clear both the original list and the "copy" losing all our data.

To prevent this and similar errors we can use a similar collection to a list that is not mutable.

The tuple

A tuple is a list that is not mutable. To create a tuple we use parenthesis ( ) opposed to square brackets [ ].

empty_tuple=()

The comma , is once again used as a delimiter.

shop_list=('apples',
           'bananas',
           'grapes')

To access the tuple methods we can type in a dot . and then tab . The number of methods available for the tuple is far less than those for the list.

Parenthesis are used for emphasize to specify the order of operations in a calculation. For example.

a=(4-2)/2

Therefore we need to be careful when trying to create a tuple which has a single element as it will just be used for parenthesis.

b=(4)

If we end the single element in a comma , a tuple is instead created.

c=(4,)

In Python it is quite common to unpack each index of a tuple or list into a separate variable names.

shop_list=('apples',
           'bananas',
           'grapes')

a,b,c=shop_list

The dict

Python dictionaries work in the same manner as traditional dictionaries, in that they have a keyword or key and this is associated with a description or value. In Python dictionaries are abbreviated dict and enclosed in braces {} and each key and value pair are separated using a colon : while the comma , is used as a delimiter to move onto the next key and value pair. Like a list, the dict can be written on a single line or over multiple lines.

dictionary={'key1':'value1','key2':'value2','key2':'value3'}
dictionary={'key1':'value1',
            'key2':'value2',
            'key3':'value3'}

Key names may be of type str or a numerical type such as a int, float or bool meaning there is much more versatility in a key name than a variable name. Let's create a list of color strings, a tuple of color strings and a dict of color single letter key strings and full name value strings. In this case, each value will be placed on a separate line. We can highlight the differences in each, namely the bracket type and the use of a colon in dictionaries to separate out key and values on each line.

If we open the three of these up in the variable explorer side by side. We can see that the list and the tuple have an index while the dict has a key.

We can index a tuple or a list using the index enclosed in square brackets. For indexing square brackets are always used, even though square brackets are used in the creation of a list and parenthesis are used in the creation of a tuple. In a dict we also index using square brackets but we have no index so we use the key instead.

color_list[0]
'red'
color_tuple[0]
'red'
color_dict['r']
'red'

Note as the key is a str it must be enclosed in quotations. Recall earlier where we specified that a color could be designated by three 8 bit numbers corresponding to the brightness of the red, green and blue LED respectively and that each 8 bit character could be specified using two hexadecimal characters giving the form '#rrggbb'. These hexadecimal values may be hard to remember off hand (particularly for a custom color) however we can create a dict and prescribe the key to a string that makes sense to us.

color_dict={
        'red':'#ff0000',
        'green':'#00ff00',
        'blue':'#0000ff'
        }

We can then use the key to get the hex value.

color_dict['red']

We may also want to setup one letter abbreviations as synonyms (a key that has the same value as another key).

Note it is not possible to setup a homonym (two keys with the same name but different value).

We can get a list of methods by typing in the object name followed by a dot . and then tab .

When we looked at lists we seen the method clear, copy, pop which behave in a similar manner for the class dict as in the class list. The method pop_value returns a key:value pair opposed to just a value in the case of the method pop. The method get can be used with an input argument which is the key and returns the respective value.

The methods keys, values and items return objects of the type list.

color_dict.keys()
color_dict.values()
color_dict.items()

These can be used in order to iterate using a for loop.

color_dict={
        'red':'#ff0000',
        'r':'#ff0000',
        'green':'#00ff00',
        'g':'#00ff00',
        'blue':'#0000ff',
        'b':'#0000ff'
        }

for key in color_dict.keys():
    print(key)
    print(color_dict[key])
    

The set

Another type of collection is a set. Like a dict a set uses braces {} and uses the comma , as a delimiter but does not have matched key:value colon separated pairs. Note because both the set and the dict use curly brackets {}. When we use empty empty braces we create an empty dict and not an empty set.

empty_dict={}

To create an empty set we need to use the class set.

empty_set=set()

The classes list, set, tuple and dict can also be used to create new instances of each class in a similar manner to above. They can also be used to convert one collection to a different type for example to make a list from a tuple. For example.

shop_list=['apples',
           'bananas',
           'grapes',
           'oranges',
           'pears']

fruit_set=set(shop_list)

Or we can create a set with a single or more items using braces directly.

fruit_set={'apple',
           'banana',
           'banana',
           'grapes'}

Note although 'banana' is added twice to the set because a set cannot have duplicate values, duplicates will be automatically removed when the set is created.

Note a set does not have any index or key and cannot be indexed using square brackets.

We can get a list of methods by typing in the object name followed by a dot . and then tab . Most of the methods are used to compare different sets to one another.

try and except

If we create a basic list.

shop_list=['apples',
           'bananas',
           'grapes']

We can use the method index to find the index of a value in the list.

shop_list.index('apples')
0

Now we can look at what happens when we try and return the index of a value that is not present in the list.

shop_list.index('oranges')
ValueError: 'oranges' is not in list

We get the error message above and for more severe errors it will stop execution of the code. To get around this we can use try and except.

try is followed by a colon : to begin a code block and the code which belongs to it is indented by four spaces. After the try code block an except block is created. except is followed by a colon : to begin a code block and the code belonging to this code block is likewise indented by four spaces.

shop_list=['apples',
           'bananas',
           'grapes']

try:
    idx=shop_list.index('apples')
    print(f'apples index is {idx}')
except:
    print('apples not present in shop_list')

In the case below there are no errors within the code within the try block so the except block is ignored.

If we update the code to look for the str 'oranges', python looks at the try block, finds an error and so instead carries out the code in the except block.

shop_list=['apples',
           'bananas',
           'grapes']

try:
    idx=shop_list.index('oranges')
    print(f'oranges index is {idx}')
except:
    print('oranges not present in shop_list')

After the except and before the colon : we can also specify the error type.

shop_list=['apples',
           'bananas',
           'grapes']

try:
    print(f'oranges index is {idx}')
    idx=shop_list.index('oranges')
    print(f'oranges index is {idx}')
except ValueError:
    print('ValueError oranges not present in shop_list')
except NameError:
    print('NameError oranges not present in shop_list')

Creating a function

We have seen many examples above when it comes to using inbuilt functions however we can define our own function. We use the keyword def shorthand for definition followed by the function name which follows similar rules to variable names. The function name is then followed by parenthesis containing the positional and keyword arguments and a colon : to begin a new code block. Code belonging to the code block is then indented by 4 spaces.

def customfunction():
    print('hello')

Note when the script is ran nothing is shown on the console. This is because the function is only defined it isn't ran. We can run it like any other function by typing in the function name followed by parenthesis. If we do this in the console with open parenthesis we get the details about the function and input arguments (no detail is specified and there are no input arguments in this case).

However we can run the function just to check whether it works or not.

def customfunction():
    print('hello')

We can add documentation to the top of the function using triple quotes and creating a multi-line string.

def customfunction():
    '''This function prints the greeting
    hello to the console.'''
    print('hello')

Note that when we call the function with open parenthesis we get the help documentation.

We can add a positional input argument called text to our customfunction.

def customfunction(text):
    '''This function prints the greeting
    hello text to the console. text is a str'''
    print(f'hello, {text}')

Now when we type customfunction into the console with open parenthesis we can see we are prompted for the positional input argument text.

Let's just type in.

customfunction('Philip')
customfunction('Alison')

Instead of using a positional input argument, we can use a keyword input argument.

Now customfunction can be called without specifying the keyword input argument in which case the default value will be taken. Or we can override it with a new value by specifying it while calling the customfunction.

customfunction()
customfunction(text='Alison')
customfunction(Alison')

Notice that functions have a local workspace. This means the functions local variable text is not shown in the consoles workspace.

In the example below the variable text belongs to the local workspace and is independent to the functions local variable text. Thus we get the error message TypeError: customfunction() missing 1 required positional argument: 'text'.

We can call the function and assign it to an object name.

var1=customfunction('Alison')

customfunction doesn't have a return statement so no output exists and as a result var1 is a NoneType object. We can add a return statement.

text='Alison'
def customfunction(text):
    '''This function prints the greeting
    hello text to the console. text is a str.'''
    print(f'hello, {text}')
    return(f'hello, {text}')

Now when we call the function and assign it to an object name

var2=customfunction('Alison')

That we get the str defined within the return statement.

We only get one return statement however we can output a tuple or other type of collection.

text='Alison'
def customfunction(text):
    '''This function prints the greeting
    hello text to the console. text is a str.'''
    print(f'hello, {text}')
    return((f'{text}','Philip'))


This means the object name in this case var3 will be a tuple.

var3=customfunction('Alison')

We can also unpack the tuple.

(var4,var5)=customfunction('Alison')

Files

We can restart the Kernal and save our custom function to another script file custom.py and have it in the same folder as our example.py. We can then open the Files tab and view the files.

Because the two scripts are in the same folder and this is the folder we are working in we can easily import the function from one script file to another using from then specifying the file, then specifying import and then the function name.

from custom import customfunction
customfunction('Alison')

Plots

If we go to Tools and Preferences.

To the left select IPython Console and to the right select the Graphics tab. You either opt to change the Backend to Inline (the plot will display on the plot pane) or Automatic (the plot will display in its own interactive window).

In order to plot we need to load the pylab/pyplot module, we can have Spyder do this automatically in the background or we can import this using a line of code at the top of the file (which is usally recommended for best user practice). Changes will not be made until the kernel is restarted.

We can create a very basic script to plot some data.

import matplotlib.pyplot as plt
x=[1,2,3,4,5]
y=[1,2,3,4,5]
plt.plot(x,y)

If an automatic backend is instead used we will get.

Before looking at plots in more detail, an overview of the numeric Python (numpy) library is recommended. Data for 2D plotting is often in vector format or matrix format. Alternatively data may be in an Excel spreadsheet or dataframe format, the Python and Data Analysis Library (pandas) looks at the creation of dataframes. Once the data is in the correct format, it can be plotted in 2D using the matplotlib library (this library is based on MATLAB and shares a similar syntax).

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.