Back to Python
With the surge of AI, Python is the defacto language. This means for me its time to get back to basics with Python. Having used it in the past it is an easy language to adopt and use, but in saying that it will be good to do a full refresher of the Syntax, Control Flows, Functions, Data Manipulation, File Handling, General OOP in Python and revist the Standard Library. So lets jump in.
Initial requirements:
- Python: https://python.org
- IDE Pycharm Community Edition: https://www.jetbrains.com/pycharm/download
- Or we can use VSCode with Python Plugin and Python Linting Pylint Plugin (Should be default in Python plugin)
- Create Project in IDE (Base Interpreter to python3.*)
- Read about Python Enhancement Proposals (PEP) specifically PEP 8 for styling
Basics
Python files have the extension .py.
Create a simple app.py within the project
Comments
- Used with a
#
# This is a comment in python
Output
print("Alan J. Fitzpatrick") # print is very simple
print('*' * 10) # We can even use expressions within print functions
Variables
In Python it is common to split words using an _ for variable names.
age = 36 # Assignment is simple in Python, no keyword is required to initiate
age = 37 # Variables are mutable
name = 'Alan J. Fitzpatrick'
is_happy = True
- Strings can be declared in 3 ways,
single quotes,double quotesandtriple quotemulti lines. - Strings are indexible and can use negative indexes to reverser through a String
- We can also get sub strings using index range
first_name = 'Alan'
last_name = "Fitzpatrick"
address = '''
1 Main Street
Dublin
Ireland
'''
print('First Initial', first_name[0]) # Example of String index
print('Second Name Short', last_name[0:4]) # Example of Sub String index range
print('Second Name Remainder, last_name[4:]) # We can return from fourth character to the end of the string
print('Copy Last Name', last_name[:]) # Here we use a range with no defined index to make a copy of the whole string
print('Copy no end charsr, last_name[1, -1]) # We can also see we can use a range with negative indexes
Input
- Python has a built in input function
- This function awaits the response before continuing the program
name = input('What is your name?')
print('Hi ' + name)
Casting
Python has built in functions for casting strings to other values int() float() bool()
age = input('Current age: ')
print(type(age))
age_in_ten_years = age + 10
print('In 10 years you will be', age_in_ten_years)
Formatted Strings
Formatted Strings allow us to create template literal strings
first_name = 'Alan'
last_name = 'Fitzpatrick'
full_name = f'{first_name} J. {last_name}'
String Methods
name = 'Alan J. Fitzpatrick'
print(len(name)) # Built in function for calculating length (this is a general purpose function for strings, lists, etc...)
print(name.upper()) # Convert string to all uppercase
print(name.lower()) # Convert all to lowercase
print(name.find('F')) # Returns the index of the given character or sequence of characters
print(name.replace('J.', 'Jack')) # Replace sequence of string
print('J' in name) # We can use an expression to check if a sequence of chars exists in a string
Arithmetic Operators
In python we have Integers and FLoating point types of numbers
Operator precedence is the same in python parenthesis ⭢ exponentiation ⭢ multiply / divide ⭢ add / subtract
print(10 + 10)
print(10 - 10)
print(10 * 10)
print(10 / 3) # Returns a floating point number
print(10 // 3) # Returns an integer
print(10 % 3)
print(10 ** 3) # Powers
age = 36
print(age += 1) # Augmentated assignment operator
Module Importing
Standard import syntax and then methods are available to the file scope
import math
print(math.ceil(3.14))
Built in Functions
There are some built in functions that do not require the math module of Python
print(round(3.14))
print(abs(-3.14))
If Statements
Conditional flow control
is_happy = True
is_studying = True
if is_happy:
print('Today is a great day')
elif:
print('Take a break and relax')
else:
print('Studying may help')
Logical Operators
In Python logical operators are simpler than other languages, instead of special character sequence we can just use the words
is_happy = True
is_studying = True
if is_happy and is_studying: # and
print('Keep Going')
if is_happy or is_studying:
print('Something is going right') # or
if is_studying and not is_happy: # not
print('Time to take a break')
Comparison Operators
temp = 30
if temperature > 30:
print('Its a hot day')
elif temperature == 30: # Equality in Python is double equals
print('Its a nice day')
elif temperature < 30 and temperature >= 10:
print('You may need a jumper')
else
print('Its very cold')
Loops
While Loops
Here we create the usual Guessing game with a while loop
secret_number = 5
guess_count = 0
while guess_count < 3:
guess = input('Guess: ')
guess_count += 1
if int(guess) == secret_number:
print('You Won!')
break
else: # In Python while loops that dont break can have an else block
print('You lost!')
For Loops
Simple for loops for running over lists
for item in 'Alan J. Fitzpatrick': # Using the in keyword to do our loop
print(item)
for name in ['Alan', 'Natasha', 'Phoebe'] # We can easily create lists in Python to loop over
print(name)
for num in range(100): # range allows us to generate a list of numbers
print(num)
for num in range(5, 10, 2): # range also allows us to set a start, end and step value
print(num)
Nested Loops
Great for matrix coords like on a chess board
for x in range(10):
for y in range(10):
print(f'{x} {y}')
Example Nested Application
numbers = [5, 2, 5, 2, 2]
for num in numbers:
output = ''
for i in range(0, num): # 0 is not needed here but it is used as an example
output = output + '*'
print(output)
Lists
Initial Look
names = ['Alan', 'Natasha', 'Phoebe'] # Declaration
names[0] = 'Alan J.' # Reassignment
print(names[0]) # Index return
print(names[-3]) # Reverse Index return
print(names[0:2]) # Range selection
print(names[0:]) # Range selection from location
List iteration
numbers = [10, 3, 6, 2, 8, 4]
max = numbers[0]
for i in range(1, len(numbers)):
if numbers[i] > max:
max = numbers[i]
print(max)
2D Lists
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
matrix[1][1] = 20
for row in matrix:
for value in row:
print(value)
List Methods
numbers = [2, 55, 34, 10]
numbers.append(54) # Append to the end of the list
numbers.insert(0, 56) # Insert at a given location
numbers.remove(55) # Remove a specific given value
numbers.clear() # Empties the list
numbers.pop() # Removes the last item in the list
numbers.index(34) # Will find the index of the given value
print(50 in numbers) # Another check for existence
print(numbers.count(10)) # Counts all occurrences of the number 10
numbers.sort() # Sorts the numbers in place
numbers.reverse() # Reverse list
numbers2 = numbers.copy() # Creates a copy of the list with different pointers
Example of getting a list of only unique numbers
numbers = [2, 2, 4, 6, 3, 4, 6, 1]
uniques = []
for number in numbers:
if number not in uniques:
uniques.append(number)
Tuples
- Tuples are immutable
- Tuples are defined with parens
- We can not remove values
numbers = (1, 2, 3) # Set like this
numbers.count() # Only 2 methods available
numbers.index(2) # Count and index
numbers[0] # Accessed the same way as lists
- Tuples also allow us to destructure to variables
coordinates = (1, 2, 3)
x, y, z = coordinates
Dictionaries
- Dictionaires allow us to keep lists of key value pairs
- All keys must be unique
customer = { # Declared with curly brackets
"name": "Alan" # Keys must be strings
"is_verified: True
}
print(customer["name"]) # Access with square brackets, will throw an error if the value does not exist
print(customer.get("name")) # The get method will not throw and error is the value does not exist
print(customer.get("is_over_18", False)) # The get value also takes a second param for the default value
customer["name"] = "Alan J." # We can easily update values
customer["age"] = 37 # We can also easily add new keys
Emoji Converter
message = input(">")
words = message.split(' ')
emojis = {
":)": "😀",
":(": "😥"
}
output = ""
for word in words:
output += emojis.get(word, word) + " "
print(output)
Functions
- Allows smaller more manageable code
Function Definitions
def greet_user(): # def is short for Define Function
print('Hi there!)
print('Welcome Aboard')
Parameters
- If a parameter is required it must be passed by the caller
def greet_given_user(name): # Here we give the parameter name
print(f'Hi {name}!')
greet_given_user("Alan") # Here we pass the arguments required
Keyword Arguments
- Allows us to not worry about argument position
- Can make the calling code more obvious as to what it is doing
- positional arguments should always be used first
def greet_user(first_name, last_name): # Here we have multiple parameters
print(f'Hi {first_name} {last_name}')
print(last_name="Fitzpatrick", first_name="Alan") # Here we define the arguments with keywords
Return Statements
- Using for return values from a function flow
- By default python returns the value
None
def square(number):
return number * number # Very simple just the return keyword
print(square(3))
Emoji Function
def emoji_converter(message):
words = message.split(' ')
emojis = {
":)": "😀",
":(": "😥"
}
output = ""
for word in words:
output += emojis.get(word, word) + " "
return output
print(emoji_converter('Greetings :)'))
Exceptions
- Exit codes allow us to determine if a program succeeded
- Zero is a success and anything else is a failure
- We use
try exceptto catch errors
Named Exceptions
try: # Start of try block
age = int(input('Age: '))
income = 20000
risk = income / age
print(age)
except ZeroDivisionError: # Named Exception
print('Age can not be 0')
except ValueError: # Another named Exception
print('Invalid value')
Unknown Exceptions
- Should only be on the outskirts of an application to gracefully close and capture errors
try:
age = int(input('Age: '))
print(age)
except Exception as e: # This is to catch all
logging.error(traceback.format_exc()) # Logs the error appropriately.
Classes
- Used to define new Types
- Model new concepts
- Classes use Pascal Class
- This is the only part of Python that uses Pascal Class
Basic Class Setup
class Point: # Class creation
def move(self):
print('move')
def draw(self):
print('draw')
point1 = Point() # Instantiation of a Class
point1.draw()
Constructors
- Constructors are called at the time of instantiation
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def move(self):
print('move')
def draw(self):
print('draw')
point = Point(11, 22)
print(point.x)
Inheritance
- Reuse Class Logic by extending existing Classes
class Mammal: # We declare the reusable class
def walk(self):
print('walk')
class Dog(Mammal): # We then extend the class by passing it as an argument
pass # Python must have something defined in a class we can use the `pass` keyword to allow an empty class
class Cat(Mammal):
def scratch(self): # Here we have already extended and added additional functionality
print('scratch')
dog = Dog()
dog.walk() # Our dog variable then has the abilities of a Mammal
cat = Cat()
cat.walk()
cat.scratch() # Here we have a new ability along with the existing extended ability
Modules
- Each file in Python is a module
- Modules allow us to better structure code
- Modules are used to store variables, classes and funcitons
Module Definition
- Just a normal file with defined methods
- The file name will become the object name in the importing file, so name wisely
converters.py
def lbs_to_kg(weight):
return weight * 0.45
def kg_to_lbs(weight):
return weight / 0.45
Module Use
- Imported at the top of the file
app.py
import converters # Here we import everything from a module
from converters import lbs_to_kg # Here we import only one specific method from the module
import converters as lib # Here we can change the object name (usually for bad file names, or clashing file names)
from converters import * # This will add all methods, variables, and classes to the global scope of this file
print(converters.kg_to_lbs(70))
print(lbs_to_kg(150))
print(lib.kg_to_lbs(70))
Packages
- Another way to organise code
- Packages are usually stored in different folders
Create Package Directory
- All package directories must have an
__init__.pyfile, this tells python it is a package ecommerce/__init__.pyecommerce/shipping.py
def shipping_cost():
print('shipping_cost')
Consuming Package
app.py
import ecommerce.shipping
ecommerce.shipping.shipping_cost()
Package Index
Random Number Generation
- Python has many built in modules
- These modules can be see in the Python Module Index
Using built-in Random Module
import random
random.random() # Generates random value between 0 and 1
random.randint(10, 20) # Generates value between range
members = ['John', 'Mary', 'Bob', 'Alan']
random.choice(members) # Picks a random item from the given list
Random Dice Class
import random
class Dice:
def randomDiceSide(self):
return random.randint(1, 6)
def roll(self):
return (self.randomDiceSide(), self.randomDiceSide())
dice = Dice()
print(dice.roll()
Files and Directories
- There is Relative and absolute paths to files
- We use the built in Path module when working with paths
Path Module Example
from pathlib import Path # Here we import the Path class from pathlib
path = Path("ecommerce") # We create an instance of Path with a directory
print(path.exists()) # This method allows us to check if it exists
path2 = Path("emails")
print(path2.exists()) # Here we are checking a none existent path
path2.mkdir() # We can then make the path
print(path2.exists())
path2.rmdir() # We are now removing the new directory
path3 = Path() # Using Path with no given directory just points to the current directory
print(path3.glob('*.*')) # Glob allows us to gather all files on a given any syntax, this just gets all files in current directory
for file in path3.glob('*.py') # We can then iterate over the files
print(file)