notes_The Python Book_20240418
3.Packages and Builtin Functions
-
dir(): This function takes in an object and returns the dir() of that object giving us the attributes of the object.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15'Rob' name =
dir(name)
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__',
'__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__',
'__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__',
'__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__',
'__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith',
'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha',
'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric',
'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower',
'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust',
'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith',
'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']This code demonstrates that in Python, when you use the
dir()
function on a string object, it returns a list of all the attributes and methods of that object.dir()
is a very useful built-in function for exploring an object’s capabilities, or in other words, to see what attributes and methods are available for use on that object.
In the example you provided,name
is a string object with the value ‘Rob’. When you calldir(name)
, you get a list that contains all the methods of the string object, such asupper()
for converting the string to uppercase,lower()
for converting the string to lowercase, andsplit()
for splitting the string into substrings, among others.
Most of these methods are standard for operating on strings, while those with double underscores before and after their names, such as__add__
and__len__
, are Python’s magic methods (also known as special methods). These methods typically serve special functions; for example, the__add__
method implements the addition operator+
, allowing you to concatenate two strings using+
.
This list is very useful for understanding what can be done with Python strings, and it also shows the dynamic nature and flexibility of the Python language. With these methods, you can easily manipulate and work with text data.
4.Data Types
-
+ - * / 1
2
3
4
5
6
- real and imaginary parts of complex numbers
~~~python
>>> x.real
>>> x.imag -
Integers or floats can be converted into a boolean using the built-in function bool. This treats any value as 0 or 0.0 as False and any other value to be True.
1
2
3
4
5
6
7
8x
True
bool(0.0) y =
y
False
bool(-10) z =
z
True -
Surprisingly we can use the operators in this chapter on boolean variables. The key to note is that a value of True is evaluated as 1 and False as 0, so you can see examples of this below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33True x =
False y =
x + y
1
x - y
1
x * y
0
x / y
Traceback (most recent call last): File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero >>> x = True
True y =
x + y
2
x - y
0
x + y
2
x * y
1
x / y
1.0
False x =
False y =
x + y
0
x - y
0
x * y
0
x / y
Traceback (most recent call last):
File "<stdin>", line 1, in <module> ZeroDivisionError: division by zero -
create byte, byte arrays and memory view objects
1
2
3
4
5
6
7
8
9b"Hello World" x =
x
b'Hello World'
bytearray(6) y =
y
bytearray(b'\x00\x00\x00\x00\x00\x00')
memoryview(bytes(5)) z =
z
<memory at 0x7fdde6fea348>
5.Operators
-
define a variable, assigning the variable
-
It is a very subtle difference so you need to be careful with it. A simpler explanation is that == returns True if the variables being compared are equal, whereas is checks whether they are the same.
1
2
3
4
5
6
7
8
9
10
11
12
1 a =
is 1 a
True
1 a ==
True
a = []
b = []
is b a
False
a == b
TrueHowever, they are both lists so using the comparison statement == we return True as they are both empty lists. If we assigned a as a list and b = a we would get the following:
1
2
3
4a = []
b = a
is b a
True -
x/y #division x//y #floor division x%y #modulus x**y #exponentiation
1
2
3
4
5
6
7
8
9
10
11
12
13
## 6.**Dates**
- datetime()
~~~python
>>> from datetime import daretime timedelta date
>>> d1 = datetime(2017, 5, 16, 10, 0, 11)
>>> change = timedelta(days=1, hours=2, minutes=10)
>>> d2 = date.today()
>>> d3 = datetime.datetime.now()
7.Lists
-
pop
1
#removes the last item of the list stuff.pop()
-
append
1
9) #add an element to the end of the list stuff.append(
-
remove
1
9) # by using the attribute remove,remove 9 from the list,specify the name of the item we wanted to remove stuff.remove(
-
count
1
2
3
4
51,1,1,2,3,4,4,5,6,9,9,9] #get the count of in the list count_list = [
1) count_list.count(
3
4) count_list.count(
2 -
reverse
1
2
3#reverses the elements in a list count_list.reverse()
count_list
[9, 9, 9, 6, 5, 4, 4, 3, 2, 1, 1, 1] -
sort
1
2
3#we can only use the sort method on a list of numeric values count_list.sort()
count_list
[1, 1, 1, 2, 3, 4, 4, 5, 6, 9, 9, 9] -
len
1
len(stuff) #get the length of the list
-
used negative indexing to choose item in a list
1
1] stuff[-
-
choose element
1
2
3
4
5
61:3] #take from the element in index 1 in the list and show up to but not including element in index 3 in the list stuff[
1:] #select everything except the first element stuff[
#select everything,shows the full list stuff
1:] new_stuff = stuff[-
1] new_stuff = stuff[:-
1:8:2] stuff[ -
boolean
1
29 in stuff #If the value is in we get back a boolean value True or False.
True -
copy
1
#take a copy of the list new_stuff = stuff.copy()
-
clear
1
2
3#simply put this method clears the list of all its content stuff.clear()
stuff
[] -
select
1
range(1,7,2) x =
-
obtain the start, stop and step of the range object alongside the count and index
1
2
3
4
5
6
7
8
9
10
11
12
13
14range(7) x =
1:] x = x[
x
range(1, 7)
x.start
1
x.stop
7
x.step
1
1) x.index(
0
1) x.count(
1
8.Tuples
You access them in exactly the same way and many things we covered in lists are relevant to tuples, the big difference is tuples can’t be modified.
-
>>> numbers = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) >>> numbers (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
1
2
3
4
5
6
7
- namely count
~~~python
>>> new_numbers = (1, 2, 2, 2, 5, 5, 7, 9, 9, 10)
>>> new_numbers.count(2)
3 -
index
1
2
31, 2, 2, 2, 5, 5, 7, 9, 9, 10) new_numbers = (
2) new_numbers.index(
1
9.Dictionaries
-
definition
1
2
3
4
5
6
7personal_details = {}
"first name"] = "Rob" personal_details[
"surname"] = "Mastrodomenico" personal_details[
"gender"] = "Male" personal_details[
"favourite_food"] = "Pizza" personal_details[
personal_details
{"first name": "Rob", "favourite_food": "Pizza", "surname": "Mastrodomenico", "gender": "Male"}or
1
dict(first_name="Rob", surname="Mastrodomenico",gender="Male", favourite_food="Pizza") person_details =
or
1
"first name": "Rob", "surname": "Mastrodomenico","gender": "Male", "favourite_food": "Pizza"} personal_details = {
or
1
dict([("first name", "Rob"), ("surname", "Mastrodomenico"), ("gender", "Male"), ("favourite_food", "Pizza")]) personal_details =
or
1
2
3
4
5
6#using the fromkeys method.
'key1', 'key2', 'key3') x = (
0 y =
dict.fromkeys(x, y) res =
res
{'key1': 0, 'key2': 0, 'key3': 0} -
deal with it in a more sophisticated way: use a try except statement.
1
2
3
4
5
6
7
8
9
10
11
12dict([("first name", "Rob"), ("surname", "Mastrodomenico"), personal_details =
("gender", "Male"), ("favourite_food", "Pizza")])
personal_details
{"first name": "Rob", "surname": "Mastrodomenico", "favourite_food": "Pizza",
"gender": "Male"}
try:
"age"] age = personal_details[
except KeyError:
None age =
...
age
>>> -
pop
1
2
3
4
5
6
7
8
9
10
11personal_details
{'first name': 'Rob', 'surname': 'Mastrodomenico', 'gender': 'Male', 'favourite_food':
'Pizza'}
'gender') personal_details.pop(
'Male'
personal_details
{'first name': 'Rob', 'surname': 'Mastrodomenico', 'favourite_food': 'Pizza'}
personal_details.popitem()
('favourite_food', 'Pizza')
personal_details
{'first name': 'Rob', 'surname': 'Mastrodomenico'} -
del: we pass the dictionary name and key combination to remove that key value pair from the dictionary
1
2
3del personal_details['gender']
personal_details
{'first name': 'Rob', 'surname': 'Mastrodomenico', 'favourite_food': 'Pizza'} -
Earlier we mentioned how if we assign one list to another the changes are reflected. The same is true for dictionaries.
1
his_details = personal_details
If we want to take a copy of a dictionary and independently make changes to it we can use the copy method in a similar way that we did with lists.
1
his_details = personal_details.copy()
-
clear out all contents of dictionary using the clear method
1
2
3personal_details.clear()
personal_details
{} -
access all keys and values from a
dictionary
using the following methods1
2
3
4
5
6
7personal_details.items()
dict_items([('first name', 'Rob'), ('surname', 'Mastrodomenico'), ('gender', 'Male'),
('favourite_food', 'Pizza')])
personal_details.keys()
dict_keys(['first name', 'surname', 'gender', 'favourite_food'])
personal_details.values()
dict_values(['Rob', 'Mastrodomenico', 'Male', 'Pizza']) -
The objects that we return can be iterated over and this is covered later when we introduce loops. However if you want to access them like we would a list we can cast them as such and access the relevant index positions.
1
2
3
4
5
6list(personal_details.items())[0]
('first name', 'Rob')
list(personal_details.keys())[-1]
'favourite_food'
list(personal_details.values())[:-1]
['Rob', 'Mastrodomenico', 'Male']
10.Sets
They are also unordered and cannot be changed.
Here, we can see that the ordering of the set doesn’t resemble what we put into it.
-
create
1
2
3
4#use the curly brackets
'Tony','Peter','Natasha','Wanda', 1, 2, 3} names = {
names
{1, 2, 3, 'Wanda', 'Peter', 'Tony', 'Natasha'}or
1
2
3
4
5
6
7#use the set builtin function
set(('Tony','Peter','Natasha','Wanda', 1, 2, 3)) names =
names
{1, 2, 3, 'Wanda', 'Peter', 'Tony', 'Natasha'}
set(['Tony','Peter','Natasha','Wanda', 1, 2, 3]) names =
names
{1, 2, 3, 'Natasha', 'Peter', 'Tony', 'Wanda'}or
1
2
3
4
5
6
7
8#pass in a string using the curly brackets you retain the full string in but when passed in using set the string is split into the individual characters. Again note when the characters are split there is no ordering to them.
'Wanda'} names = {
names
{'Wanda'}
set('Wanda') names =
names
{'n', 'a', 'W', 'd'} -
notice: add
dic
,list
,tuple
andset
to theset
1
2
3'Tony','Wanda', 1, 2, (1,2,3)} my_set = {
my_set
{'Wanda', 1, 2, 'Tony', (1, 2, 3)}The reason we can include the tuple over the
dictionary
,list
andset
is that the tuple cannot be changed so is supported in a set. -
We can see if the value is in the
set
by using the following syntax:1
2'Tony' in names True
'Steve' in names False -
add
1
'Steve') names.add(
-
That aspect of not having duplicate values within the set is useful if we want to have a unique representation of values where we could have duplicates. For example, you could imagine a long
list
with lots of repeated values and you just want the unique values within it as we show below.1
2
3
4
5'Monday', 'Monday', 'Tuesday', 'Wednesday', days = [
'Sunday', 'Sunday']
set(days) days_set =
days_set
{'Monday', 'Wednesday', 'Sunday', 'Tuesday'} -
operate on multiple sets, obtain the unique value between two sets
1
2
3
4
5
6
7
8
9
10
11
12
13#use the | operator
'Tony','Peter','Natasha','Wanda'} names = {
names
{'Wanda', 'Natasha', 'Peter', 'Tony'}
'Steve', 'Peter', 'Carol', 'Wanda'} more_names = {
more_names
{'Wanda', 'Peter', 'Steve', 'Carol'}
names | more_names
{'Wanda', 'Peter', 'Tony', 'Carol', 'Steve', 'Natasha'}
#use the set method union
names.union(more_names)
{'Wanda', 'Peter', 'Tony', 'Carol', 'Steve', 'Natasha'}achieve the same result as the list is converted into a set
-
Now where we used union and the | operator if we want to find out what values are in all sets we use the
intersection
method or the&
operator.1
2
3
4
5
6'Tony','Peter','Natasha','Wanda'} names = {
'Steve', 'Peter', 'Carol', 'Wanda'} more_names = {
names & more_names
{'Wanda', 'Peter'}
names.intersection(more_names)
{'Wanda', 'Peter'}we can add non-sets into the intersection method
-
look at the differences between two or more sets, then we can use the
difference
method or the−
operator1
2
3
4names - more_names
{'Natasha', 'Tony'}
names.difference(more_names)
{'Natasha', 'Tony'}The manner in which difference is applied for more than one comparison is to work left to right so we first look at the difference between names and more_names and then look at the difference between this result and even_more_names.
-
use the symmetric_difference method or the
^
operator1
2
3
4names ^ more_names
{'Carol', 'Tony', 'Steve', 'Natasha'}
names.symmetric_difference(more_names)
{'Carol', 'Tony', 'Steve', 'Natasha'}return back the elements that are in either set but not in both, so its like the or method but doesn’t include any common values.
-
isdisjoint method
1
2
3
4
5names.isdisjoint(more_names)
False
'Steve', 'Bruce', 'Carol', 'Sue'} more_names = {
names.isdisjoint(more_names)
True -
issubset
-
issuperset
-
pop
-
remove
-
discard
-
clear
-
update
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15'Tony','Peter','Natasha','Wanda'} names = {
names
{'Wanda', 'Natasha', 'Peter', 'Tony'}
'Steve', 'Peter', 'Carol', 'Wanda'} more_names = {
more_names
{'Steve', 'Peter', 'Carol', 'Wanda'}
names | more_names
{'Carol', 'Peter', 'Steve', 'Natasha', 'Wanda', 'Tony'}
names
{'Tony', 'Peter', 'Wanda', 'Natasha'}
more_names
{'Carol', 'Peter', 'Steve', 'Wanda'}
names.update(more_names)
names
{'Carol', 'Peter', 'Steve', 'Natasha', 'Wanda', 'Tony'}The big difference here is that when you use the
|
operator you don’t change either of the sets, however using theupdate
method changes the set that you have used the method for so in this case thenames
set is now the result ofnames
|
more_names
. -
frozen set
1
2
3
4
5
6
7
8
9
10
11
12frozenset({'Tony','Peter','Natasha','Wanda'}) frozen_names =
frozen_names
frozenset({'Tony', 'Peter', 'Wanda', 'Natasha'})
frozenset(['Tony','Peter','Natasha','Wanda']) frozen_names =
frozen_names
frozenset({'Tony', 'Peter', 'Wanda', 'Natasha'})
frozenset(('Tony','Peter','Natasha','Wanda')) frozen_names =
frozen_names
frozenset({'Tony', 'Peter', 'Wanda', 'Natasha'})
frozenset('Tony') frozen_names =
frozen_names
frozenset({'T', 'y', 'n', 'o'})The frozen set is what the tuple is to a list in that it cannot be altered
11.Loops, if, Else, and While
-
if
-
else
-
elif
-
list
1
list[0][2]
-
for in
-
while
12.Strings
-
use an
escape sequence
1
2
3'string with a \' single quote' single_quote_string =
single_quote_string
"string with a ' single quote"We can get away with not using
escape sequences
if we use triple quotes. So we can rewrite the previous usingtriple quotes
as follows:1
2
3"""string with a ' single quote""" single_quote_string =
single_quote_string
"string with a ' single quote" -
typing
backslash n
gives us a carriage return in our string. But what if we want forwardslash n
in our string, we can use what is called araw string
:1
2
3r"This has a \n in it" raw_string =
raw_string
"This has a \\n in it"or
1
2
3"This has a \\n in it" not_raw_string =
not_raw_string
"This has a \\n in it"In both examples when we show the content of the string it has an extra forward slash but when it is printed this disappears. And yes if you wanted an extra slash in there just use three slashes.
1
2
3"This has a \\\n in it" not_raw_string =
not_raw_string
"This has a \\\n in it" -
select element
-
boolean
-
put a variable into our string we need only define the position in the string using curly brackets and then using the format method with the arguments passed in they get assigned to the appropriate positions.
1
2
3
4"Rob" first_name =
"Mastrodomenico" last_name =
"First name: {}, Last name: {}".format(first_name, last_name) >>> name name =
"First name: Rob, Last name: Mastrodomenico"We can also give the positions in the curly brackets to where we want the variables assigned, so we could write the following:
1
2
3
4
5"Rob" first_name =
>>> last_name = "Mastrodomenico"
>>> name = "First name: {1}, Last name: {0}".format(first_name, last_name)
>>> name
>>> "First name: Mastrodomenico, Last name: Rob"That is wrong but you get the point. We can also define each value as a variable and pass that variable name in the curly brackets.
1
2
3
4
5"Rob" first_name =
>>> last_name = "Mastrodomenico"
>>> name = "First name: {f}, Last name: {l}".format(f=first_name, l=last_name)
>>> name
"First name: Rob, Last name: Mastrodomenico" -
convert a string to all uppercase letters and then all lowercase letters
1
2
3
4name.lower()
"rob mastrodomenico"
name.upper()
"ROB MASTRODOMENICO" -
split up strings
1
2
3
4
5
6
7
8"Rob Mastrodomenico" name =
" ") name.split(
["Rob", "Mastrodomenico"]
" ") first_name, last_name = name.split(
first_name
"Rob"
last_name
"Mastrodomenico" -
a comma separated string which you may find in a
csv file
can be split into the variables it contains1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22"Manchester United,Arsenal,2,0" match_details =
match_details
"Manchester United,Arsenal,2,0"
",") match_details.split(
["Manchester United", "Arsenal", "2", "0"]
",")[0:2] home_team, away_team = match_details.split(
home_team
"Manchester United"
away_team
"Arsenal"
",")[2:4] home_goals, away_goals = match_details.split(
home_goals
"2"
away_goals
"0"
#replace all the commas with colons
"Manchester United,Arsenal,2,0" match_details =
match_details
"Manchester United,Arsenal,2,0"
",",":") match_details.replace(
"Manchester United:Arsenal:2:0" -
apply the join method on the string containing just the
comma
and it then createsa string of the values
in thelist
separated by the string that we applied the method on.This is a very useful method when it comes to creating strings from lists separated by a common value.
1
2
3
4'Manchester United', 'Arsenal', '2', '0'] details = [
','.join(details) match_details =
match_details
'Manchester United,Arsenal,2,0' -
len
13.Regular Expressions
-
package re
-
finding all the characters
1
2
3
4
5import re
'Rob Mastrodomenico' name =
"[a-m]", name) x = re.findall(
x
['b', 'a', 'd', 'm', 'e', 'i', 'c'] -
find the integer values 0–9 within a sequence
1
2
3
4'Find all numerical values like 1, 2, 3' txt =
"\d", txt) x = re.findall(
x
['1', '2', '3']1
2
3"[0-9]", txt) x = re.findall(
x
['1', '2', '3']1
2
3
4'Find all numerical values like 1, 2, 3, 3' txt =
"[0-9]", txt) x = re.findall(
x
['1', '2', '3', '3']1
2
3"\d", txt) x = re.findall(
x
['1', '2', '3', '3'] -
look for specific patterns
1 | "hello world" txt = |
- search specifically on the start of the string
1 | 'starts at the end' txt = |
- look at the last word in the string by using ending the searched string with the $ sign
1 | 'the last word is end' txt = |
- find the occurrences of ai followed by 0 or more x values
1 | "The rain in Spain falls mainly in the plain!" txt = |
- Expanding on the previous example you can find the number of instances of the string ai followed by one or more x by adding the + symbol. Applying that to the same string as before gives us the result of an empty string as we don’t have aix within it.
1 | import re |
- a specified number of characters, use curly brackets containing the number of instances we are interested in
1 | 'The cow said moo' txt = |
- use the | symbol between the two strings, to find one or another value
1 | "The Avengers are earths mightiest heroes go Avengers" txt = |
- use special sequences (returns the whitespace)
1 | "Is there whitespace" txt = |
-
There are other special sequences that we can use, they are listed as follows:
● \A: This matches if the characters defined are at the beginning of the string “\AIt”
● \b: This matches if the characters defined are at the beginning or at the end of a word
“\bain” r"ain\b"
● \B Returns a match where the specified characters are present, but NOT at the beginning
(or at the end) of a word (the “r” in the beginning is making sure that the string is being
treated as a “raw string”) r"\Bain" r"ain\B"
● \d Returns a match where the string contains digits (numbers from 0-9) “\d”
● \D Returns a match where the string DOES NOT contain digits “\D”
● \s Returns a match where the string contains a white space character “\s”
● \S Returns a match where the string DOES NOT contain a white space character “\S”
● \w Returns a match where the string contains any word characters (characters from a
to Z, digits from 0-9, and the underscore _ character) “\w”
● \W Returns a match where the string DOES NOT contain any word characters “\W”
● \Z Returns a match if the specified characters are at the end of the string -
split method
1 | "\s", txt) x = re.split( |
- specify the number of times we want the split to be done by using the maxsplit argument
1 | "\s", txt, maxsplit=1) x = re.split( |
- replace on a string
1 | "\s", "9", txt) x = re.sub( |
- combine
1 | "\s", "9", txt, 1) x = re.sub( |
- span
1 | "ai", txt) x = re.search( |
14.Dealing with Files
^
15.Functions and Classes
-
define a function called lottery: use the command def followed by the name that you want to give the function
1
def lottery(min, max):
-
Classes: can be very powerful objects which allow us to bundle together lots of functions and variables
1
2
3
4
5
6class MyClass:
10 x =
...
mc = MyClass()
mc.x
10 -
create an init method using
__init__
this initialiser1
2
3
4
5
6class Lottery:
def __init__(self, min=1, max=59, draw_length=7): self.min = min
self.max = max
self.draw_length = draw_length
def lottery(self):
#codes -
in this code, we define the class in the way we did before and call it Lottery. Next, we create an init method using init this initialiser is called when we define the class so we can pass in arguments from here that can be used within the class. Note that we can use the standard defaults but these are then assigned to the class by using the self-dot syntax which allows that value to be part of class and then allowed to be used anywhere within the class. We can create the class in the following example:
1
2
3
4
5
6l = Lottery()
l.lottery()
1,49,6) l = Lottery(
l.lottery()
8) l = Lottery(draw_length=
l.lottery() -
import the package sys and look at the sys.path list
1
2
3
4
5
6
7import sys
sys.path
['', '/Users/rob/anaconda3/lib/python37.zip',
'/Users/rob/anaconda3/lib/python3.7',
'/Users/rob/anaconda3/lib/python3.7/lib-dynload',
'/Users/rob/anaconda3/lib/python3.7/site-packages',
'/Users/rob/anaconda3/lib/python3.7/site-packages/aeosa']import the contents of the lottery.py file.
If we create a file called import_lottery.py in the same directory as the lottery.py we can run the Lottery class as follows:
1
from lottery import *