Previously I worked in C#, now switching to Python and Robot Framework. Recently I’ve been doing great Python course. In this post I’ll try to wrap up my basic Python knowledge gained during the course with the main focus on syntax.
age_input = input("How old are you?")
age = int(x)
print(f"You live for {xx * 525600} minutes")
Above we wrote a simple sort of hello world program where we defined a variable, converted it to int and printed it with some message.
my_list = [3, 2, 7, 1]
my_list.append(9)
greatest = max(my_list)
smallest = min(my_list)
length = len(my_list)
print("Smallest:", smallest)
print("Greatest:", greatest)
print("Length of the list:", length)
my_list.sort()
print(my_list)
Here we created a list, did some operations on ot and printed a sorted version.
my_list = [3, 2, 4, 5, 2]
#1st way to loop thru a list:
index = 0
while index < len(my_list):
print(my_list[index])
index += 1
#2nd way to loop thru a list:
for item in my_list:
print(item)
Above 2 ways to loop thru
#1st looping with range
for i in range(5):
print(i)
#prints numbers 0-4
#2nd looping with range
for i in range(3, 7):
print(i)
#prints numbers 3-6
#3rd looping with range
for i in range(1, 9, 2):
print(i)
#prints every second number in range 1-8 that is: 1,3,5,7
#4th range can create lists
numbers = list(range(2, 7))
print(numbers)
#5th accesing list elements with Range
my_string = "exemplary"
print(my_string[3:7])
#prints "mpla"
my_list = [3,4,2,4,6,1,2,4,2]
print(my_list[3:7])
#prints 4, 6, 1, 2
Here we had some usages of Range
def print_reversed(names: list):
i = len(names) - 1
while i >= 0:
print(names[i])
i -= 1
name_list = ["Steve", "Jean", "Katherine", "Paul"]
print_reversed(name_list)
#prints Paul Katherine Jean Steve
Now we know how to define and call a function with parameter
def print_reversed(names: list):
i = len(my_list) - 1
while i >= 0:
print(my_list[i])
i -= 1
def global_testing():
global my_list
my_list = ["Steve", "Jean", "Katherine", "Paul"]
print_reversed(my_list)
global_testing()
Variable defined in the function is local by default. Sometimes we want to make it global and then we can use “global” keyword. Generally using global variables directly in method definitions is a bad approach and we should avoid it.
class BankAccount:
def __init__(self, account_number: str, owner: str, balance: float, annual_interest: float):
self.account_number = account_number
self.owner = owner
self.balance = balance
self.annual_interest = annual_interest
def add_interest(self):
self.balance += self.balance * self.annual_interest
peters_account = BankAccount("12345-678", "Peter Python", 1500.0, 0.015)
peters_account.add_interest()
print(peters_account.balance)
The name of the constructor method is always __init__. Notice the two underscores on both sides of the word init. The first parameter in a constructor definition is always named self. This refers to the object itself, and is necessary for declaring any attributes attached to the object. The assignment
self.balance = balance
assigns the balance received as an argument to the balance attribute of the object. It is a common convention to use the same variable names for the parameters and the data attributes defined in a constructor, but the variable names self.balance and balance above refer to two different variables:
1. The variable balance is a parameter in the constructor method __init__. Its value is set to the value passed as an argument to the method as the constructor is called (that is, when a new instance of the class is created).
2. The variable self.balance is an attribute of the object. Each BankAccount object has its own balance.
class BankAccount:
def __init__(self, account_number: str, owner: str, balance: float, annual_interest: float):
self.account_number = account_number
self.owner = owner
self.balance = balance
self.annual_interest = annual_interest
# This method adds the annual interest to the balance of the account
def add_interest(self):
self.balance += self.balance * self.annual_interest
# This method "withdraws" money from the account
# If the withdrawal is successful the method returns True, and False otherwise
def withdraw(self, amount: float):
if amount <= self.balance:
self.balance -= amount
return True
return False
peters_account = BankAccount("12345-678", "Peter Python", 1500.0, 0.015)
if peters_account.withdraw(1000):
print("The withdrawal was successful, the balance is now", peters_account.balance)
else:
print("The withdrawal was unsuccessful, the balance is insufficient")
# Yritetään uudestaan
if peters_account.withdraw(1000):
print("The withdrawal was successful, the balance is now", peters_account.balance)
else:
print("The withdrawal was unsuccessful, the balance is insufficient")
In object oriented programming the word client comes up from time to time. This is used to refer to a section of code which creates an object and uses the service provided by its methods. When the data contained in an object is used only through the methods it provides, the internal integrity of the object is guaranteed. In practice this means that, for example, a BankAccount class offers methods to handle the balance attribute, so the balance is never accessed directly by the client. These methods can then verify that the balance is not allowed to go below zero, for instance. Maintaining the internal integrity of the object and offering suitable methods to ensure this is called encapsulation. The idea is that the inner workings of the object are hidden from the client, but the object offers methods which can be used to access the data stored in the object.
class Rectangle:
def __init__(self, left_upper: tuple, right_lower: tuple):
self.left_upper = left_upper
self.right_lower = right_lower
self.width = right_lower[0]-left_upper[0]
self.height = right_lower[1]-left_upper[1]
def area(self):
return self.width * self.height
def perimeter(self):
return self.width * 2 + self.height * 2
def move(self, x_change: int, y_change: int):
corner = self.left_upper
self.left_upper = (corner[0]+x_change, corner[1]+y_change)
corner = self.right_lower
self.right_lower = (corner[0]+x_change, corner[1]+y_change)
def __str__(self):
return f"rectangle {self.left_upper} ... {self.right_lower}"
rectangle = Rectangle((1, 1), (4, 3))
print(rectangle)
#prints rectangle (1, 1) ... (4, 3)
To print a string representation of the object you need to use __str__ in class definition.
list1 = [1, 2, 3]
list2 = [1, 2, 3]
list3 = list1
print(list1 is list2)
print(list1 is list3)
print(list2 is list3)
print()
print(list1 == list2)
print(list1 == list3)
print(list2 == list3)
#prints:
#False True False
#True True True
The operator is is used for checking if the two references refer to the exact same object, while the operator == will tell you if the contents of the objects are the same.
class Product:
def __init__(self, name: int, unit: str):
self.name = name
self.unit = unit
if __name__ == "__main__":
#obj references in list
shopping_list = []
milk = Product("Milk", "litre")
shopping_list.append(milk)
shopping_list.append(milk)
shopping_list.append(Product("Cucumber", "piece"))
#obj references in dictionary
products = {}
products["12345"] = Product("Cucumber", "piece")
products["54321"] = Product("Milk", "litre")
This list doesn’t contain 2 objects “milk” but 2 references to the same object “milk”. Same with dictionary.
class Student:
def __init__(self, name: str, student_number: str):
self.name = name
self.student_number = student_number
def __str__(self):
return f"{self.name} ({self.student_number})"
# the type hint here uses the name of the class defined above
def change_name(student: Student):
student.name = "Saul Student"
# create a Student object
steve = Student("Steve Student", "12345")
print(steve)
change_name(steve)
print(steve)
#prints
#Steve Student (12345) Saul Student (12345)
Above function change_name receives Student object as an argument.