Introduction to Learning Python
Best place to start is the documentation www.python.org
Download Python 3
Docker images for Python on Docker Hub
Run Python in Docker
We can also run python in a docker container:
cd python\introduction
docker build --target dev . -t python
docker run -it -v ${PWD}:/work python sh
/work # python --version
Python 3.9.
Our first Program
- Create a folder containing our application source code
mkdir src
- Create basic source code
In the src
folder, create a program called app.py
Paste the following content into it.
def main():
print("Hello, world.")
main()
- Run your application code
You can run your application
/work # python src/app.py
Hello, world.
The Code
In the video we cover writing functions.
It allows us to execute a block of code
You want to give your function a single purpose
Functions can have an input and return an output
Well thought out functions makes it easier to write tests
Instead of doing a boring x + y
function that adds two numbers, let's do something a little
more realistic but still basic:
# This function returns some data
# The data could be coming from a database, or a file.
# The person calling the function should not care
# how the data is retrieved.
# Since the function does not leak its Data provider
def getCustomer():
return "Marcel Dempers"
print(getCustomer())
Function inputs
As we saw, functions can return outputs, and also take inputs. Let's accept a customer ID and return a customer record with that ID:
def getCustomer(customerID):
return "CustomerID: " + customerID + ", Name: Marcel Dempers"
print(getCustomer("abc"))
Variables
To hold data in programming languages, we use variables.
Variables take up space in memory, so we want to keep it minimal.
Let's declare variables in our function:
def getCustomer(customerID):
firstName = "Marcel"
lastName = "Dempers"
fullName = firstName + " " + lastName
return fullName
#or we can return the computation instead of adding another variable!
return firstName + " " + lastName
#or we don't even need to declare variables :)
return "Marcel Dempers"
customer = getCustomer("abc")
print(customer)
Control Flows (if\else)
You can see we're not using the customerId
input in our function.
Let's use it and showcase control flows to create logic!
Control flows allow us to add "rules" to our code.
"If this is the case, then do that, else do something else".
So let's say we have a customer ID 1 coming in, we may only want to
return our customer if it matches the customerID
def getCustomer(customerID):
if customerID == "abc":
return "Marcel Dempers"
elif customerID == "def":
return "Bob Smith"
else:
return ""
customer = getCustomer("abc")
print(customer)
Let's invoke our function :
marcel = getCustomer("abc")
print(marcel)
bob = getCustomer("def")
print(bob)
Arrays
Our function can only return one customer at a time.
What if we wanted to return more than one customer.
In real world systems, we may return database records.
This is where we start looking at arrays, lists, dictionaries etc.
Let's add another function to get an array of customers!
def getCustomers():
customers = [ "Marcel Dempers", "Bob Smith" ]
return customers
customers = getCustomers()
print(customers)
You can get array values by index starting at 0
:
customers = getCustomers()
marcel = customers[0]
bob = customers[1]
print(marcel + "\n" + bob)
We can set a value in our Array.
Arrays are fixed in size, notice we cannot just access a
record :
customers[2] = "John Smith"
IndexError: list assignment index out of range
Instead we can use the append()
function of the array to add items.
def getCustomers():
customers = [ "Marcel Dempers", "Bob Smith" ]
customers.append("James Baker")
customers.append("Jonathan D")
customers.append("Aleem Janmohamed")
customers.append("Ivo Galic")
customers.append("Joel Griffiths")
customers.append("Michael Spinks")
customers.append("Victor Savkov")
return customers
We can remove items with the remove()
function.
customers.remove("Bob Smith")
Dictionaries
Dictionaries have an advantage whereby items can be found using a key.
With arrays, we have to know the index number where the item is located or else we cannot find items unless we write a loop.
With Dictionaries, we store key value pairs. So the key, may be our customer ID.
Let's replace our customer array with a dictionary
customers = {
"a": "James Baker",
"b": "Jonathan D",
"c": "Aleem Janmohamed",
"d": "Ivo Galic",
"e": "Joel Griffiths",
"f": "Michael Spinks",
"g": "Victor Savkov"
}
We can also set and access an item by key
#update or create item
customers["h"] = "Marcel Dempers"
#get an item
marcel = customers["h"]
print(marcel)
Let's update our getCustomer()
function to get customer from our dictionary
def getCustomer(customerID):
customer = getCustomers()
return customer[customerID]
def getCustomers():
customers = {
"a": "James Baker",
"b": "Jonathan D",
"c": "Aleem Janmohamed",
"d": "Ivo Galic",
"e": "Joel Griffiths",
"f": "Michael Spinks",
"g": "Victor Savkov",
"h" : "Marcel Dempers"
}
return customers
customers = getCustomers()
customer = getCustomer("h")
print(customer)
print(customers)
Loops
Loops are used to iterate over collections, lists, arrays etc.
There are two primitive loops in Python
Let's say we need to loop through our customers
While loop
While loops are simple to write by condition:
i = 0
while i < 7:
print(customers[i])
i += 1
We can also use this condition to loop arrays:
customers = [ "Marcel Dempers", "Bob Smith" ]
customers.append("James Baker")
customers.append("Jonathan D")
customers.append("Aleem Janmohamed")
customers.append("Ivo Galic")
customers.append("Joel Griffiths")
customers.append("Michael Spinks")
customers.append("Victor Savkov")
i = 0
while i <= 8:
print(customers[i])
i += 1
For loops
For looping a dictionary of list, for
loops are a little easier:
customers = getCustomers()
for customerID in customers:
print(customers[customerID])
Classes and Objects
So far so good, however, customer data is not useful as strings.
Customers can have a firstname, lastname, and more properties.
For this purpose we'd like to group some variables into a single variable.
This is what classes
allows us to do.
Let's create a class
for our customer
class Customer:
customerID = ""
firstName = ""
lastName = ""
def fullName(self):
return self.firstName + " " + self.lastName
marcel = Customer()
marcel.firstName = "Marcel"
marcel.lastName = "Dempers"
marcel.customerID = "h"
print(marcel.fullName())
Now how can we create an object with our values without having to set every value individually ? Constructors allow us to initialise our object with some default values.
class Customer:
def __init__(self, c="", f="", l=""):
self.customerID = c
self.firstName = f
self.lastName = l
def fullName(self):
return self.firstName + " " + self.lastName
marcel = Customer("h", "Marcel", "Dempers")
print(marcel.fullName())
Let's plug our class into our current application and put it all together: Firstly, we convert all our customers from strings to objects:
def getCustomers():
customers = {
"a": Customer("a","James", "Baker"),
"b": Customer("b", "Jonathan", "D"),
"c": Customer("c", "Aleem", "Janmohamed"),
"d": Customer("d", "Ivo", "Galic"),
"e": Customer("e", "Joel", "Griffiths"),
"f": Customer("f", "Michael", "Spinks"),
"g": Customer("g", "Victor", "Savkov"),
"h" : Customer("h", "Marcel", "Dempers")
}
return customers
Then we can proceed to get our customer and access their fields:
customers = getCustomers()
for customerID in customers:
print(customers[customerID].fullName())
Docker
So far we have used our container as a development environment.
Docker allows us to run python in an isolated environment.
Docker also has a concept of stages, I.E Docker Multistage.
Therefore we may have a stage for development where we simply mount source code to access a python environment. In addition to this, we may add another layer for debugging where we can install debugger and extra development tools which we
do not want in production.
Finally we can create a smaller stage which contains only python + our source which we can run as a runtime image in production.
Example:
FROM python:3.9.6-alpine3.13 as dev
WORKDIR /work
FROM python:3.9.6-alpine3.13 as debugging
# add a debugger
FROM dev as runtime
COPY ./src/ /app
ENTRYPOINT [ "python", "/app/app.py" ]
Building the Container
docker build . -t customer-app
Running the Container
docker run customer-app