Basic Object Types¶
Note:
There are readingcomprehension exercises included throughout the text. These are meant to help you put your reading to practice. Solutions for the exercises are included at the bottom of this page.
You will see the term “object” be used frequently throughout this text. In Python, the term “object” is quite the catchall; including numbers, strings of characters, lists, functions  a Python object is essentially anything that you can assign to a variable. That being said, there are different types of objects: Python treats integers as a different type of object than a string, for instance.
The different object types have manifestly different purposes and thus have different builtin functions available to them. Here, we will review some of the basic types that are built into Python, as a natural entry point to writing code. We will cover:
numbers (integers, floatingpoint numbers, and complex numbers)
booleans
the “null” type
strings
lists
The builtin function isinstance
will allow us to check if an object is of a given type. You can also use the builtin type
function to check an object’s type. For example, the following code checks if an object is an integer:
# assign the variable `x` to the integer 1
>>> x = 1
# checking the type of `x`
>>> type(x)
int
# verifying that `x` is an integertype object
>>> isinstance(x, int)
True
In a later module, you will learn “objectoriented” programming, which will allow you to create your own, customized objects!
Number Types¶
Python has three basic types of numbers: integers, “floatingpoint” numbers, and complex numbers. Familiar mathematical symbols can be used to perform arithmetic on all of these numbers (comparison operators like “greater than” are not defined for complex numbers):
Operation 
Description 


Sum of two numbers 

Difference of two numbers 

Product of two numbers 

Quotient of two numbers 

Quotient of two numbers, returned as an integer 





A negated number 

The absolute value of a number 

Check if two numbers have the same value 

Check if two numbers have different values 

Check if 

Check if 

Check if 

Check if 
These operations obey the familiar order of operations from your mathematics class, with parentheses available for association:
# multiplication takes precedence over addition
>>> 1 + 2 * 3
7
# grouping operations with parentheses
>>> (1 + 2) * 3
9
# finding the remainder of division between two positive numbers
>>> 11 % 5
1
# checking an inequality
>>> (2 ** 3) < (2 ** 4)
True
It should be noted that in many other programming languages, including the outdated Python 2, dividing two integers would always return an integer  even if mathematically the result should be a fraction. In Python 3, the quotient of two integers will always return a floatingpoint number (i.e. a number that includes a decimal point):
# In many other languages, 3 / 2 returns the integer 1.
# In Python 3, division always returns a floatingpoint number:
>>> 3 / 2
1.5
>>> 4 / 2
2.0
The //
operator is known as the “floordivide” operator: it performs division between two numbers and returns the result as an integer by discarding any decimalplaces for that number (thus returning the “floor” of that number). This can be used to perform the integerdivision traditionally used in other programming languages:
# floordivision
>>> 1 // 3 # 0.3333.. > 0
0
>>> 3 // 2 # 1.5 > 1
1
Reading Comprehension: Understanding the modulo operator
The modulo operator, %
, is not commonly seen in mathematics textbooks. It is, however, a very useful operation to have at our disposal. x % y
(said as x “mod” y in programmer’s jargon) returns the remainder of x / y
, when x
and `y are nonnegative numbers. For example:
\(\frac{3}{2} = 1 + \frac{1}{2}\). 2 “goes into” 3 one time, leaving a remainder of 1. Thus
3 % 2
returns1
\(\frac{9}{3} = 3\). 3 “goes into” 9 three times, and leaves no remainder. Thus
9 % 3
returns0
Given this description of the “mod” operator, simplify the following by hand, and then use the IPython console to check your work:
1 % 5
2 % 5
22 % 1
22 % 2
22 % 3
22 % 4
22 % 5
22 % 6
Now, given any integer, n
, what are the possible values that n % 2
can return? See if you can come up with a simple rule for explaining the behavior of n % 2
.
Python’s math module¶
The standard library’s math module provides us with many more mathematical functions, like logarithms and trigonometric functions. A complete listing of them can be found in the official Python documentation. This module must be imported into your code in order to use its functions:
# using the `math` module to use
# additional mathematical functions
>>> import math
>>> math.sqrt(4.)
2.0
# base10 log
>>> math.log10(10.)
1.0
# 4! = 4*3*2*1
>>> math.factorial(4)
24
Integers¶
As in traditional mathematics, an integer is any “whole” number: \(\dots, 3, 2, 1, 0, 1, 2, 3, \dots\).
Integers belong to the builtin type int
, which can be used to convert objects to integers:
>>> type(3)
int
# `1.3` is not an integertype object
>>> isinstance(1.3, int)
False
# converting a string to an integer
>>> int("10")
10
# converting a floatingpoint number to an integer
>>> int(1.3)
1
You can create as large an integer as you’d like; Python will allocate as much memory as needed (and ultimately, as is available) to store an integer’s exact value:
# you can make an integer as large as you'd like
>>> large_int = 281938481039848500192847576920
Integers have some builtin functions available to them, which are detailed in the official documentation. The utility of these will likely be quite obscure to new programmers. Just note that they are here for now.
FloatingPoint Numbers¶
A “floatingpoint” number is a number with a decimal point. Referred to as a “float” for short, this can be used to represent any number, up to a limited number of digits.
These objects belong to the builtin type float
, which can be used to convert objects to floats:
# examples of "floatingpoint" numbers
>>> 100. ** 0.5
10.0
>>> 1 / 3
0.3333333333333333
>>> 1 / 2
0.5
>>> type(2.1)
float
# the integer 10 is not a floattype object
>>> isinstance(10, float)
False
# including a decimal makes the number a float
>>> isinstance(10., float)
True
# converting a string to a floatingpoint number
>>> float("10.456")
10.456
# converting an integer to a floatingpoint number
>>> float(22)
22.0
Floats have a couple of builtin functions available to them, as detailed in the official documentation.
Scientific Notation¶
A float can also be created using familiar scientific notation. The character e
is used to represent \(\times 10\), and the proceeding number is the exponent. Here are some examples of traditional scientific notation, and their corresponding representation in Python:
\(1.38 \times 10^{4} \rightarrow\) 1.38e04
\(4.2 \times 10^{10} \rightarrow\) 4.2e10
Python will automatically display a float that possesses many digits in scientific notation:
# python will display manydigit numbers using
# scientific notation
>>> 0.0000001 # seven leadingzeros
1e07
Understanding Numerical Precision¶
Whereas a Python integer can be made to be as large as you’d like, a floatingpoint number is limited in the number of digits it can store. That is, your computer will only use a set amount of memory  8 bytes (64 bits) on most machines  to store the value of a floatingpoint number.
In effect, this means that a float can only be represented with a numerical precision of approximately 16 decimal places, when that number is written in scientific notation. The computer will not be able to reliably represent a number’s digits beyond those accounted for by the allotted 8 bytes. For instance, the following Python integer is defined with 100 digits, but when this number is converted to a float, it only retains 15 decimal places in scientific notation:
# Demonstrating the finiteprecision of a float.
# An integer with 100 digits  Python will use as
# much memory as needed to store an integer
>>> int("1"*100) # creates a string with 100 1s and makes it an int
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
# Converted to a float, it retains only
# 16 decimal places, when written in scientific
# notation. This is the precision permitted by
# 8 bytes of memory.
>>> float("1"*100) # creates a string with 100 1s and makes it a float
1.111111111111111e+99
The computer cannot keep track of those last 84 decimal places because doing so would require more than 8 bytes of memory to store the entire value of that float. If you had been diligently counting stars in the sky (perhaps across many universes, this number far exceeds the estimated number of stars in our universe), you would have just lost track of over \(1\times10^{83}\) of them simply by converting your integer count to a float!
As such, attempting to modify a floating point number in decimal places beyond its numerical precision does not have any effect:
# changing a float beyond its precision has no effect
>>> 1. + 1e16
1.0
Even in light of this discussion on float precision, you may be shocked and dismayed to see the following outcome of float arithmetic:
# the finiteprecision of floats
# result in nonobvious behavior
>>> 0.1 + 0.1 + 0.1  0.3 == 0.
False
# the effects of having finite numerical precision
>>> 0.1 + 0.1 + 0.1  0.3
5.551115123125783e17
This is not a quirk of Python; this is a wellunderstood aspect of dealing with floatingpoint numbers with limited numerical precision. To accommodate this, don’t check if two floats are “equal”. Rather, you should check if they are “close enough in value”. Let me emphasize this:
You should never check to see if two floats are exactly equal in value. Instead, you should only check that two floats are approximately equal to one another.
The math
module has a very nice function for this; math.isclose
will check if the relative difference between two numbers is less than \(1 \times 10^{9}\). You can change this tolerance value along with the type of tolerancechecking used by the function; see its documentation here. Because in the previous example we compare values that are close to 0, we will check if their absolute difference is sufficiently small:
# checking if two float values are "almost equal"
>>> import math
# check:
#  (0.1 + 0.1 + 0.1  0.3)  0  < 1x10^{9}
>>> math.isclose((0.1 + 0.1 + 0.1  0.3), 0., abs_tol=1e9)
True
If you do not heed this lesson, it is inevitable that you will end up with serious, hardtofind bugs in your code. Lastly, when doing numerical work in Python (and any other programming language), you must understand that the finite numerical precision of floatingpoint numbers is a source of error, akin to error associated with imprecision with a measuring device, and should be accounted for in your analysis (if error analysis is warranted).
Python’s decimal module can be used to define higher (or lower) precision numbers than permitted by the standard 8byte floats. Furthermore, all arithmetic involving decimal numbers from this module is guaranteed to be exact, meaning that 0.1 + 0.1 + 0.1  0.3
would be exactly 0.
. There is also a builtin fractions module, which provides tools for working with
exact representations of rational numbers. Although we will not be using them here, it is very important to keep in mind that these modules exist and that floating point numbers are not the only way around the number line in Python.
Complex Numbers¶
In mathematics, a “complex number” is a number with the form \(a + bi\), where \(a\) and \(b\) are realvalued numbers, and \(i\) is defined to be the number that satisfies the relationship \(i^2 = 1\). Because no realvalued number satisfies this relationship, \(i\) is called the “imaginary number”.
Weirdo electrical engineers use the symbol \(j\) in place of \(i\), which is why Python displays the complex number \(2 + 3i\) as 2+3j
(this is actually because \(i\) typically denotes current; we like electrical engineers too).
Along with the a + bj
syntax, builtin type complex
can be used to create complextype numbers:
# creating complex numbers
>>> 2 + 3j
(2+3j)
>>> complex(2, 3)
(2+3j)
>>> complex(0, 1)**2
(1+0j)
>>> type(2+3j)
complex
>>> isinstance(24j, complex)
True
Note that j
is not, by itself, reserved as a special placeholder for \(i\). Rather, j
must be preceded immediately with a numerical literal (i.e. you cannot use a variable) in order for the Python interpreter to treat it as a complex number.
# `j` by itself is treated like any other character
>>> j
NameError: name 'j' is not defined
# `1j` is interpreted as the imaginary number
>>> (1j) ** 2
(1+0j)
You can access a
and b
from a + bj
, the real and imaginary parts of the complex number, respectively.
# Accessing the real and imaginary parts of
# a complex number.
>>> x = complex(1.2, 3.4)
>>> x.real
1.2
>>> x.imag
3.4
The cmath
(“complex math”) module provides a collection of mathematical functions defined for complex numbers. For a complete listing of these functions, refer to the official documentation.
Reading Comprehension: Working with numbers in Python
In Python, performing an arithmetic operation, such as addition or multiplication, on two integers will return an integer, and performing an operation on two floats will return a float:
>>> 2 * 3
6
>>> 2.0 * 3.0
6.0
For which operation, among +  * / **
, does this not hold?
What type of number will be returned if you perform a mathematical operation using an integer and a floatingpoint number? Does this hold for all the arithmetic operations? Determine this by trial and error.
Given the function \(f(x) = e^{x  2}\), make use of the
math
module to compute \(f(0.2)\).Using Python’s syntax for scientific notation, write an expression that verifies that one trillion divided by one billion is equal to one thousand
Augmented Assignment Statements¶
Python provides a nice “shortcut” for updating a variable via an arithmetic operation. For example, suppose you want to increase the value of x
by 1. Currently, we would update x
as follows:
# incrementing `x` by 1
>>> x = 5
>>> x = x + 1
>>> x
6
We can make use of a special assignment operation +=
to perform this update in an abbreviated way.
# using `+=` to increment `x` by 1
>>> x = 5
>>> x += 1 # equivalent to: `x = x + 1`
>>> x
6
+=
is a type of augmented assignment statement. In general, an augmented assignment performs a mathematical operation on a variable, and then updates that variable using the result. Augmented assignment statements are available for all of the arithmetic operations. Assuming x
and n
are both types of numbers, the following summarizes the available arithmetic augmented assignment statements that we can perform on x
, using n
:
x += n
\(\rightarrow\)x = x + n
x = n
\(\rightarrow\)x = x  n
x *= n
\(\rightarrow\)x = x * n
x /= n
\(\rightarrow\)x = x / n
x //= n
\(\rightarrow\)x = x // n
x **= n
\(\rightarrow\)x = x ** n
Improving The Readability of Numbers¶
Python version 3.6 introduced the ability to include underscores between the digits of a number as a visual delimiter. This character can be used to improve the readability of long numbers in your code. For example the number 662607004
can be rewritten as 662_607_004
, using _
to delimit digits separated by orders of one thousand. Leading, trailing, or multiple underscores in a row are not allowed; otherwise this character can be included anywhere within a numerical literal.
# examples of using `_` as a visual delimiter in numbers
>>> 1_000_000 # this is nice!
1000000
# this is gross but is permitted
>>> 2_3_4.5_6_7
234.567
# underscores work with all variety of numerical literals
>>> 10_000j
10000j
Compatibility Warning
The permitted use of the underscore character, _
, in numerical literals was introduced in Python 3.6. Thus utilizing this syntax in your code will render it incompatible with Python 3.5 and earlier.
The Boolean Type¶
There are two booleantype objects: True
and False
; they belong to the builtin type bool
. We have already seen that the isinstance
function either returns True
or False
, as a given object either is or isn’t an instance of a specific type.
# the two booleanobjects: `True` and `False`
>>> type(True)
bool
# `False` is a booleantype object
>>> isinstance(False, bool)
True
True
and False
must be specified with capital letters in Python. These should not be confused with strings; note that there are no quotation marks used here.
Logic Operators¶
Python provides familiar operators for performing basic boolean logic:
Logic Operation 
Symbolic Operator 




 
# demonstrating booleanlogic operators
>>> True or False
True
>>> True and False
False
>>> not False
True
Operator symbols are available in place of the reserved words and
and or
:
# demonstrating the symbolic logic operators
>>> False  True # equivalent to: `False or True`
True
>>> False & True # equivalent to: `False and True`
False
That being said, it is generally more “Pythonic” (i.e. invogue with Python users) to favor the use of the wordoperators over the symbolic ones.
Multiple logic operators can be used in a single line and parentheses can be used to group expressions:
>>> (True or False) and True
True
Comparison statements used in basic mathematics naturally return boolean objects.
>>> 2 < 3
True
>>> 10.5 < 0
False
>>> (2 < 4) and not (4 != 1)
False
The bool
type has additional utilities, which will be discussed in the “Conditional Statements” section.
Boolean Objects are Integers¶
The two boolean objects True
and False
formally belong to the int
type in addition to bool
, and are associated with the values 1
and 0
, respectively:
>>> isinstance(True, int)
True
>>> int(True)
1
>>> isinstance(False, int)
True
>>> int(False)
0
As such, they can be used in mathematical expressions interchangeably with 1
and 0
>>> 3*True  False # equivalent to: 3*1 + 0
3
>>> True / False # equivalent to: 1 / 0

ZeroDivisionError Traceback (most recent call last)
<ipythoninput4f8487d9d0863> in <module>()
> 1 True / False
ZeroDivisionError: division by zero
The purpose of having True
and False
double as integers is beyond the scope of this section. It is simply useful to be aware of these facts so that this behavior is not completely alien to you as you begin to write code in Python.
Reading Comprehension: Boolean expressions
Assuming
x
is a an integertype, write a comparison statement that will returnTrue
ifx
is an even number, andFalse
otherwise. (Hint: recall the purpose of the%
operator)Assuming
x
andy
are both realvalued numbers (i.e. not complex numbers), write a line of code that will returnFalse
if:x
andy
are within 0.9 of one another, andx
is a positive number. (Hint: try writing the expression that will returnTrue
for this condition, and then negate it)Write an expression that returns
True
ifx
is a booleantype object or a floattype object.
The NoneType¶
There is a simple type, NoneType
that has exactly one object: None
. None
is used to represent “null”… nothing.
# `None` is the *only* object belonging to NoneType
>>> type(None)
NoneType
As such, instead of checking if an object belongs to NoneType, you should simply check if the object is None
. Python reserves is
as an operation that checks if two objects are identical. This is different than ==
, which checks if two objects are associated with the same value or state:
# Check if an object "is" None, instead
# of checking if it is of NoneType
>>> x = 22
>>> x is None
False
>>> x is not None
True
>>> y = None
>>> y is None
True
None
appears frequently, and is often used as a placeholder in code. Here is a simple example where None
could be useful; don’t worry that this code may not make perfect sense to you yet:
# Demonstrating the use of `None` as a placeholder
# In this code, we want to get the first
# item in a list that is greater than 10, and notify
# the user if there is no such number
large_num = None
for number in [1, 2, 3, 4]:
if number > 10:
large_num = number
break
if large_num is None:
print("The list did not contain any number larger than 10")
Strings¶
Introducing the string type¶
The string type is used to store written characters. A string can be formed using:
single quotes:
'Hello world'
double quotes:
"Hello world"
triple quotes:
"""Hello world"""
or'''Hello world'''
# Strings contain written characters, even those
# not found in the english alphabet!
>>> "hello, 你好, Olá, 123"
'hello, 你好, Olá, 123'
By default, Python 3 uses UTF8 unicode to represent this wide variety of characters. Don’t worry about this detail beyond making note of it, for now.
Strings belong to the builtin str
type, which can be used to convert nonstring objects into strings.
# the type `str`
>>> type("hello")
str
>>> isinstance("83", str)
True
# Using the type `str` to convert nonstring objects
# into strings.
>>> str(10.34)
'10.34'
>>> str(True)
'True'
Once a string is formed, it cannot be changed (without creating an entirely new string). Thus a given string object cannot be “mutated”  a string is an immutable object.
As the string stores a sequence of characters, Python provides a means for accessing individual characters and subsequences of characters from a string:
>>> sentence = "The cat in the hat."
>>> sentence[0]
'T'
>>> sentence[0:3]
'The'
Strings are not the only sequencetype in Python; lists and tuples are examples of sequences as well. We will reserve a separate section to learn about the common interface that Python has for all of its types that are sequential in nature, including the “indexing” and “slicing” demonstrated here.
String essentials¶
We will only scratch the surface with strings, touching on some essentials. Please refer to the official Python tutorial for a more extensive, but still informal, overview of strings.
In a string, \n
is treated as a single character. It denotes a newline in a string, and will be rendered thusly when the string is printed. Similarly, \t
will render as a tabcharacter.
# using `\n` to create a newline
>>> print("hi...\n...bye")
hi...
...bye
Using triple quotes allows you to write a blockstring, meaning that you can include text on multiple lines, and it is all still treated as one string:
# using triplequotes to write a multiline string
>>> x = """ I am a string.
I am part of the same string.
me... too!"""
>>> x
' I am a string.\nI am part of the same string.\n me... too!'
Python’s strings have a large number of fantastic, builtin functions available to them. It is very important that you familiarize yourself with these functions by looking over the official documentation. To demonstrate a few of these:
# demonstrating a few of the builtin functions for strings
>>> "hello".capitalize()
'Hello'
# join a list of strings, using "..."
>>> "...".join(["item1", "item2", "item3"])
'item1...item2...item3'
# split a string wherever ", " occurs
>>> 'item1, item2, item3'.split(", ")
['item1', 'item2', 'item3']
# does this string end with ".py"?
>>> "script.py".endswith(".py")
True
# does this string start with "sc"?
>>> "script.py".startswith("sc")
True
# insert objects into a string, in its
# "formatting" fields {}
>>> "x: {}, y: {}, z: {}".format(3.2, 8.4, 1.0)
'x: 3.2, y: 8.4, z: 1.0'
# Are the characters in the string
# numerical digits?
>>> "7".isdigit()
True
Formatting strings¶
Python provides multiple syntaxes for formatting strings; these permit us to do things like programmatically inject the values of variables into strings, align fields using whitespace, and control the number of decimal places with which numbers are displayed in a string. This section is designed to simply expose the reader to the different varieties of stringformatting.
pyformat.info is the best resource to consult to see an exhaustive (but still intuitive) treatment of stringformatting in Python. You can also refer to the official documentation here.
In Python 3, you can leverage the format
method towards this end:
# using `format` to replace placeholders with values
>>> "{name} is {age} years old".format(name="Bruce", age=80)
'Bruce is 80 years old'
# padding a string with leadingspaces so that it has at least 8 characters
>>> "{item:>8}".format(item="stew")
' stew'
Note that you may encounter the use of the cryptic %
operator to format strings to the same effect:
# using `%` to format strings (avoid this)
>>> name = "Selina"
>>> "My name is %s" % name
'My name is Selina'
this is a relic of Python 2; it is recommend that you avoid this formatting syntax.
If you are using Python 3.6 or beyond, then you have the luxury of being able to use fstrings, which provide a supremely convenient means for formatting strings. Here is an example of an fstring in action:
# an example of an 'fstring'
>>> batman = 12
>>> catwoman = 10
>>> f"Batman has {batman} apples. Catwoman has {catwoman} apples. Together, they have {batman + catwoman} apples"
'Batman has 12 apples. Catwoman has 10 apples. Together, they have 22 apples'
See that an fstring has a special syntax; an fstring is denoted by preceding the opening quotation mark with the lowercase f character:
# this is a typical empty string
>>> ""
''
# this is an empty fstring
>>> f""
''
An fstring is special because it permits us to write Python code within a string; any expression within curly brackets, {}
, will be executed as Python code, and the resulting value will be converted to a string and inserted into the fstring at that position.
>>> x = 7.9
>>> f"x is a {type(x)}number. Its value is {x}. The statement 'x is greater than 5' is {x > 5}"
"x is a <class 'float'>number. Its value is 7.9. The statement 'x is greater than 5' is True"
As seen in the preceding examples, this permits us to elegantly include variables in our strings and even do things like call functions within the string construction syntax.
fstring Compatibility:
The ‘fstring’ syntax was introduced in Python 3.6. It is not available in earlier versions of Python.
Official documentation for strings¶
It is highly recommended that you take time to read over all of the functions that are builtin to a string.
Reading Comprehension: Strings
To answer some of the following questions, you will need to peruse the documentation for the builtin functions of strings. It may take a bit of experimentation to understand the documentation’s use of squarebrackets to indicate optional inputs for a function.
Use a function that will take the string
"cat"
, and returns the string" cat "
(which has a length of 11, including the letters c, a, t). Now, change the way you call the function so that it returns"cat"
instead.Replace the first three periods of this string with a spacecharacter:
"I.am.aware.that.spaces.are.a.thing"
Remove the whitespace from both ends of:
" basket "
Create a string that will print as (the second line begins with a tabcharacter):
Hello
over there
Convert the integer
12
to the string"12"
.Only kids 13 and up are allowed to see Wayne’s World. Given the variables
name
(a string) andage
(an integer), use an fstring that will display: “NAME is old enough to watch the movie: BOOL”, where NAME is to be replaced with the kid’s name, and BOOL should beTrue
if the kid is at least 13 years old, andFalse
otherwise.
Lists¶
A list
is a type of Python object that allows us to store a sequence of other objects. One of its major utilities is that it provides us with means for updating the contents of a list later on.
A list object is created using squarebrackets, and its contents are separated by commas: [item1, item2, ..., itemN]
. Its contents need not be of the same type of object.
# a listtype object stores a sequence of other objects
>>> [3.5, None, 3.5, True, "hello"]
[3.5, None, 3.5, True, 'hello']
>>> type([1, 2, 3])
list
>>> isinstance([1, 2], list)
True
# constructing an empty list
>>> []
[]
# constructing a list with only one member
>>> ["hello"]
["hello"]
You can also include variables, equations, and other Python expressions in the list constructor; Python will simplify these expressions and construct the list with the resulting objects.
# the list constructor will simplify expressions
# and store their resulting objects
>>> x = "hello"
>>> [2 < 3, x.capitalize(), 5**2, [1, 2]]
[True, 'Hello', 25, [1, 2]]
The builtin list
type can be used to convert other types of sequences (and more generally, any iterable object, which we will discuss later) into a list:
# `list` forms a list out of the contents of other sequences
>>> list("apple")
['a', 'p', 'p', 'l', 'e']
Lists are sequences¶
Like a string, the ordering of a list’s contents matters, meaning that a list is sequential in nature.
# A list's ordering matters
>>> [1, "a", True] == [1, True, "a"]
False
Thus a list supports the same mechanism for accessing its contents, via indexing and slicing, as does a string. Indexing and slicing will be covered in detail in the next section.
# Accessing the contents of a list with indexing and slicing
>>> x = [2, 4, 6, 8, 10]
# `x` contains five items
>>> len(x)
5
# access the 0th item in the list via "indexing"
>>> x[0]
2
# access a subsequence of the list via "slicing"
>>> x[1:3]
[4, 6]
Lists can be “mutated”¶
We will encounter other types of containers in Python, what makes the list stand out is that the contents of a list can be changed after the list has already been constructed. Thus a list is an example of a mutable object.
# changing a list after it has been constructed
>>> x = [2, 4, 6, 8, 10]
>>> y = [2, 4, 6, 8, 10]
# "set" the string 'apple' into position 1 of `x`
>>> x[1] = "apple"
>>> x
[2, 'apple', 6, 8, 10]
# replace a subsequence of `y`
>>> y[1:4] = [3, 4, 5]
>>> y
[2, 3, 4, 5, 10]
The builtin listfunctions “append” and “extend” allow us to add one item and multiple items to the end of a list, respectively:
>>> x = [2, 4, 6, 8, 10]
# use `append` to add a single object to the end of a list
>>> x.append("moo")
>>> x
[2, 4, 6, 8, 10, 'moo']
# use `extend` to add a sequence of items to the end of a list
>>> x.extend([True, False, None])
>>> x
[2, 4, 6, 8, 10, 'moo', True, False, None]
The “pop” and “remove” functions allow us to remove an item from a list based on its position in the list, or by specifying the item itself, respectively.
>>> x = ["a", "b", "c", "d"]
# pop the position1 item out from a list
# `pop` will return the item that gets removed.
>>> x.pop(1)
'b'
>>> x
['a', 'c', 'd']
# remove the object "d" from the list
>>> x.remove("d")
>>> x
['a', 'c']
Official documentation for lists¶
It is highly recommended that you take time to read over all of the functions that are builtin to a list. These are all designed to allow us to either inspect or mutate the contents of a list.
Reading Comprehension: Lists
To answer some of the following questions, you will need to peruse the documentation for the builtin functions of lists.
Create a list whose sole entry is the
None
object.Assign to the variable
k
a list that contains an integer, a boolean, and a string, in that order. Then, add two more entries to the end of the list: a float and a complex number.Alphabetize the list of names:
["Jane", "Adam", "Ryan", "Bob", "Zordon", "Jack", "Jackenzie"]
.
Summary¶
The term “object” is a catchall in Python, meaning anything that we can assign to a variable. Objects behave differently from one another according to what “type” a given object is.
We reviewed several fundamental object types in Python:
int
,float
,complex
: the numerical typesbool
: the boolean type.True
andFalse
are the only booleantype objectsNoneType
: the “null” type;None
is the only object that belongs to this typestr
: the string typelist
: the list type
The builtin function type
permits us to check the type of any object:
>>> type(3.2)
float
>>> type(True)
bool
The builtin function isinstance
should be used to check if an object is of a specific type:
>>> x = 2 + 3
>>> isinstance(x, int)
True
The only exception to this is if you want to check if an object is of the type NoneType
, since this is only possible if the object is None
; thus it is “cleaner” to directly check this:
>>> x = None
>>> x is None
True
Objects of different types have different builtin functions available to them:
>>> x = "I am a farmer.. moo"
>>> x.upper()
'I AM A FARMER.. MOO'
>>> y = 0.5
>>> y.as_integer_ratio()
(1, 2)
>>> z = [1, 2]
>>> z.append(3)
>>> z
[1, 2, 3]
You should leverage the official documentation, for which links were provided throughout this section, whenever you are wondering how to best do a specific task with a given type of object.
As a final reminder, we saw that that an integer in Python is able to hold a value with arbitrarilymany digits. A floatingpoint number, on the other hand, is restricted in the number of “significant” digits it can hold. Thus, where it is perfectly fine to check if two integers are exactly equal:
# checking if two integers are equal is great!
>>> 2 + 2 == 4
True
you should never rely on two floats being exactly equal. Instead, check if they are close in value:
# checking if two floats are equal is lame!
>>> 0.1 + 0.1 + 0.1  0.3 == 0.
False
>>> abs((0.1 + 0.1 + 0.1  0.3)  0.) < 1e12
True
It is very important to remember this issue of the limited numerical precision of a floating point number.
Links to Official Documentation¶
Reading Comprehension Exercise Solutions:¶
Understanding the modulo operator: Solution
If n
is an even integer, then 2 will divide into it evenly, and thus there is no remainder. If n
is odd, then n / 2
must have a remainder of 1. Thus:
n % 2
= 0 ifn
is an even numbern % 2
= 1 ifn
is an odd number
Working with numbers in Python: Solution
The division operator,
/
, will return a floatingpoint number even if it is operating on two integertype numbers.For all of the arithmetic operations,
+  * / **
, operating on a floatingpoint number and an integer will return a floatingpoint number:
>>> 2 * 3.0
6.0
>>> 1.0 + 2
1.0
Given the function \(f(x) = e^{x  2}\), make use of the
math
module to compute \(f(0.2)\).
>>> from math import exp
>>> x = 0.2
>>> exp(abs(x  2))
9.025013499434122
Using Python’s syntax for scientific notation, write an expression that verifies that one trillion divided by one billion is equal to one thousand.
As cautioned above, we should avoid checking to see if two floating point numbers are exactly equal, and instead simply ensure that they are close in value. Keep in mind that a number written Python’s using scientific syntax will produce a float.
>>> from math import isclose
>>> isclose(1e12 / 1e9, 1e3)
True
Boolean expressions: Solutions
# 1. Write an a comparisonstatement that will return
# True if x is an even number
x%2 == 0
# 2. Write a line of code that will return False if:
# x and y are within 0.9 of one another, and x is a positive number.
not (abs(x  y) < 0.9 and 0 < x)
# alternatively,
abs(x  y) > 0.9 or 0 > x
# 3. Write an expression that returns True if
# x is a booleantype object or a floattype object
isinstance(x, bool) or isinstance(x, float)
Strings: Solutions
# 1. Use a function that will take the string "cat"
# and returns the string " cat "
>>> "cat".center(11)
' cat '
>>> "cat".center(11, "")
'cat'
# 2. Replace the first three periods of this string with
# a spacecharacter:
>>> "I.am.aware.that.spaces.are.a.thing".replace(".", " ", 3)
'I am aware that.spaces.are.a.thing'
# 3. Remove the whitespace from both ends
# of: " basket "
>>> " basket ".strip()
'basket'
# 4.
>>> print("Hello\n\tover there")
Hello
over there
# 5. Convert the integer 12 to the string "12"
>>> str(12)
'12'
Only kids 13 and up are allowed to see Wayne’s World. Given the variables name
(a string) and age
(an integer), use an fstring that will display: “NAME is old enough to watch the movie: BOOL”, where NAME is to be replaced with the kid’s name, and BOOL should be True
if the kid is at least 13 years old, and False
otherwise. Use the example name = "Alfred"
, age = 10
.
# 6. Use an fstring that will display:
# "NAME is old enough to watch the movie: BOOL",
# where NAME is to be replaced with the kid's name,
# and BOOL should be `True` if the kid is at least
# 13 years old, and `False` otherwise.
>>> name = "Alfred"
>>> age = 10
>>> f"{name} is old enough to watch the movie: {age >= 13}"
'Alfred is old enough to watch the movie: False'
Lists: Solutions
# Create a list whose sole entry is the None object.
>>> [None]
[None]
# 2. Assign the variable k to a list that contains an
# integer, a boolean, and a string, in that order.
# Then, add two more entries to the end of the
# list  a float and a complex number.
>>> k = [4, False, "moo"]
>>> k.extend([3.14, complex(9, 2)])
>>> k
[4, False, 'moo', 3.14, (92j)]
# 3. Alphabetize the list of names:
>>> names = ["Jane", "Adam", "Ryan", "Bob", "Zordon", "Jack", "Jackenzie"]
# The documentation for `sort` says that the sorting happens "inplace". This
# means that the original list is replaced by the sorted list. The alternative
# would be that `sort` returns a new, sorted list, without changing the list
# assigned to `names`.
>>> names.sort()
>>> names
['Adam', 'Bob', 'Jack', 'Jackenzie', 'Jane', 'Ryan', 'Zordon']