Compiled on: 2024-10-19 — printable version
(a.k.a. run a hello world program)
python
in the terminal.
>>> print("Hello, World!")
Hello, World!
exit()
or press Ctrl+D
.You can also write Python code in a file and run it.
Create a file with a .py
extension (e.g. hello.py
).
Write your Python code in the file.
# hello.py
print("Hello, World!")
Run the script with python hello.py
.
New -> Python File
.Run
.# In Python, you don't need to declare the type of a variable.
x = 5 # x is an integer
pi = 3.14159 # pi is a float
number_of_stars_in_the_galaxy = 10E11 # you can use scientific notation
true_value = True # boolean
special_value = None # None is a special value (similar to null in other languages)
welcome_message = "Hello, World!" # string
course_teachers = ["Andrea Omicini", "Giovanni Ciatto", "Matteo Magnini"] # list (of strings)
you_can_do_this = [47521, "Cesena", True, None] # list (of mixed types)
one_digits = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} # set (non-repeating elements)
booleans = (True, False) # tuple (immutable list)
emails = {
"Andrea": "andrea.omicini@unibo.it",
"Giovanni": "giovanni.ciatto@unibo.it",
"Matteo": "matteo.magnini@unibo.it"
} # dictionary (key-value pairs, keys must be unique and immutable)
# You can check the type of a variable with the type() function
print(type(x)) # <class 'int'>
print(type(pi)) # <class 'float'>
print(type(welcome_message)) # <class 'str'>
# and so on...
You can add a print
function call to see the result of the operations after every assignment.
# Python supports the usual arithmetic operators
x = 5
y = 2
z = x + y # 7
z = x - y # 3
z = x * y # 10
z = x / y # 2.5
z = x % y # 1 (modulo)
z = x ** y # 25 (exponentiation)
z = x // y # 2 (integer division)
Why on Earth they decided to use //
for integer division if **
is for exponentiation?
One would have expected //
to be for root extraction, but it is not.
# Python supports the usual comparison operators
x = 5
y = 2
z = x == y # False
z = x != y # True
z = x > y # True
z = x < y # False
z = x >= y # True
z = x <= y # False
# Python supports the usual logical operators
x = True
y = False
z = x and y # False
z = x or y # True
z = not x # False
# Mixing comparison and logical operators
z = x + True # 2 (True is evaluated as 1)
z = x * False # 1 (False is evaluated as 0)
z = x and 5 # 5 (5 is evaluated as True)
z = True == 3 # False (True is not equal to 3)
z = True == 1 # True (True is equal to 1)
z = False == None # False (False is not equal to None)
# Python supports many operations on lists
numbers = [1, 2, 3, 4, 5]
numbers.append(6) # [1, 2, 3, 4, 5, 6]
numbers.insert(0, 0) # [0, 1, 2, 3, 4, 5, 6]
six = numbers.pop() # [0, 1, 2, 3, 4, 5]
three = numbers.pop(2) # [0, 1, 3, 4, 5]
numbers.remove(4) # [0, 1, 3, 5]
numbers.reverse() # [5, 3, 1, 0]
numbers.sort() # [0, 1, 3, 5]
length = len(numbers) # 4
is_in = 3 in numbers # True
# You can also concatenate lists
numbers = [1, 2, 3]
more_numbers = [4, 5, 6]
all_numbers = numbers + more_numbers # [1, 2, 3, 4, 5, 6]
# You can also multiply lists
more_numbers = numbers * 3 # [1, 2, 3, 1, 2, 3, 1, 2, 3]
two = more_numbers[1] # 2
three_two_one = more_numbers[2:5] # [3, 2, 1]
three_two_one = more_numbers[-3:] # [3, 2, 1]
# You can define functions with the def keyword
def greet(name):
return "Hello, " + name + "!"
# You can call the function with the arguments
greeting = greet("World") # "Hello, World!"
# You can also define functions with default arguments
def greet(name="World"):
return "Hello, " + name + "!"
greeting = greet() # "Hello, World!"
# You can also define functions with variable arguments
def greet(*names):
return "Hello, " + ", ".join(names) + "!"
greeting = greet("Andrea", "Giovanni", "Matteo") # "Hello, Andrea, Giovanni, Matteo!"
# Kwargs are used for named arguments
def greet(**kwargs):
return "Hello, " + kwargs["name"] + "!"
greeting = greet(name="Andrea") # "Hello, Andrea!"
# we can have also lists as default arguments in functions
def add_to_list(value, lst=[]):
lst.append(value)
return lst
# but be careful with mutable default arguments!
print(add_to_list(1)) # [1]
print(add_to_list(2)) # [1, 2]
print(add_to_list(3)) # [1, 2, 3]
# the list is shared between all the calls
# to avoid this, you can use None as default argument
def add_to_list(value, lst=None):
if lst is None:
lst = []
lst.append(value)
return lst
print(add_to_list(1)) # [1]
print(add_to_list(2)) # [2]
print(add_to_list(3)) # [3]
# List comprehensions are a concise way to create lists
numbers = [1, 2, 3, 4, 5]
squared_numbers = [x ** 2 for x in numbers] # [1, 4, 9, 16, 25]
even_numbers = [x for x in numbers if x % 2 == 0] # [2, 4]
# Dictionary comprehensions are a concise way to create dictionaries
teachers = ["Andrea Omicini", "Giovanni Ciatto", "Matteo Magnini"]
emails = {teacher: teacher.lower().replace(" ", ".") + "@unibo.it" for teacher in teachers}
# Set comprehensions are a concise way to create sets
numbers = {x for x in range(10) if x % 2 == 0} # {0, 2, 4, 6, 8}
# Tuple comprehensions are a concise way to create tuples
numbers = tuple(x for x in range(10) if x % 2 == 0) # (0, 2, 4, 6, 8)
# If you forget the parentheses, you will create a generator
numbers = (x for x in range(10) if x % 2 == 0) # A generator is a lazy iterable
# Nested comprehensions
chessboard = [(x, y) for x in range(8) for y in range(8)]
# If statements in comprehensions
black_squares = [(x, y) for x in range(8) for y in range(8) if (x + y) % 2 == 0]
# You can use the if-else statement
traffic_light = "red"
if traffic_light == "red":
action = "stop"
elif traffic_light == "yellow":
action = "slow down"
else:
action = "go"
# You can also use the ternary operator
action = "stop" if traffic_light == "red" else "go"
match
statement, which is similar to the switch
statement in other languages.# You can use the match statement
traffic_light = "red"
action = match traffic_light:
case "red":
"stop"
case "yellow":
"slow down"
case _:
"go"
# You can use the for loop
numbers = [1, 2, 3, 4, 5]
for number in numbers:
print(number)
# You can also use the range function
for number in range(5):
print(number)
# You can also use the enumerate function
for index, number in enumerate(numbers):
print(index, number)
# You can also use the zip function
names = ["Andrea", "Giovanni", "Matteo"]
ages = [59, 31, 29]
for name, age in zip(names, ages):
print(name, age)
# You can use the while loop
x = 0
while x < 5:
print(x)
x += 1
# You can define classes with the class keyword
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
return "Hello, " + self.name + "!"
# You can create instances of the class
person = Person("Andrea", 30)
greeting = person.greet() # "Hello, Andrea!"
# You can also define classes with inheritance
class Student(Person):
def __init__(self, name, age, student_id):
super().__init__(name, age)
self.student_id = student_id
def study(self):
return self.name + " is studying!"
# You can create instances of the subclass
student = Student("Giovanni", 25, 12345)
study = student.study() # "Giovanni is studying!"
__method__
.__repr__
method for debugging purposes.__str__
method is used when you want to print the object.__add__
method is used when you want to add two objects, and you can use the +
operator.# Python has many magic methods that you can override
class Euro:
def __init__(self, amount):
self.amount = amount
def __add__(self, other):
return Euro(self.amount + other.amount)
def __str__(self):
return "€" + str(self.amount)
def __repr__(self):
return "Euro(" + str(self.amount) + ")"
# You can use the magic methods
euro1 = Euro(10)
euro2 = Euro(20)
euro3 = euro1 + euro2 # €30
print(euro3) # €30
print(repr(euro3)) # Euro(30)
__eq__
method (and __hash__
) to compare two objects.# Here an example of the __eq__ with the Car class
class Car:
def __init__(self, brand, model):
self.brand = brand
self.model = model
def __hash__(self):
return hash((self.brand, self.model))
def __eq__(self, other):
return self.brand == other.brand and self.model == other.model
# You can use the magic methods
car1 = Car("Fiat", "500")
car2 = Car("Fiat", "500")
car3 = Car("Fiat", "Panda")
print(car1 == car2) # True
print(car1 == car3) # False
__init__
, __repr__
, __eq__
, and __hash__
methods.# Here an example of a data class
from dataclasses import dataclass
@dataclass
class StockItem:
name: str
price: float
quantity: int
# You can use the data class
stock_item1 = StockItem("Apple", 1.0, 10)
stock_item2 = StockItem("Apple", 1.0, 10)
stock_item3 = StockItem("Banana", 0.5, 20)
print(stock_item1 == stock_item2) # True
print(stock_item1 == stock_item3) # False
@
symbol and are placed above the function definition.# Here an example of a simple decorator
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
@property
decorator for getters.@property_name.setter
decorator for setters.# Here an example of a property decorator
class Person:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
# You can use the property
person = Person("Andrea")
name = person.name # "Andrea"
person.name = "Giovanni"
name = person.name # "Giovanni"
# Here an example of a decorator with arguments
def my_decorator_with_args(number):
def decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
print("The number is:", number)
return wrapper
return decorator
@my_decorator_with_args(42)
def say_hello():
print("Hello!")
say_hello()
@staticmethod
decorator. Static methods do not have access to the class or instance.@classmethod
decorator. Class methods have access to the class.# Here an example of static and class methods
class Math:
@staticmethod
def add(x, y):
return x + y
@staticmethod
def multiply(x, y):
return x * y
class Number:
@classmethod
def parse(cls, s):
return cls(s)
def __repr__(self):
return str(self.value)
class Integer(Number):
def __init__(self, value):
self.value = int(value)
class Float(Number):
def __init__(self, value):
self.value = float(value)
sum = Math.add(5, 2)
product = Math.multiply(5, 2)
integer = Integer.parse("5")
float = Float.parse("5.5")
super()
function to call the methods of the parent classes.# Here an example of multiple inheritance
class Rectangle:
def __init__(self, length, width, **kwargs):
self.length = length
self.width = width
super().__init__(**kwargs)
def area(self):
return self.length * self.width
def perimeter(self):
return 2 * self.length + 2 * self.width
class Square(Rectangle):
def __init__(self, length, **kwargs):
super().__init__(length=length, width=length, **kwargs)
class Triangle:
def __init__(self, base, height, **kwargs):
self.base = base
self.height = height
super().__init__(**kwargs)
def tri_area(self):
return 0.5 * self.base * self.height
class RightPyramid(Square, Triangle):
def __init__(self, base, slant_height, **kwargs):
self.base = base
self.slant_height = slant_height
kwargs["height"] = slant_height
kwargs["length"] = base
super().__init__(base=base, **kwargs)
def area(self):
base_area = super().area()
perimeter = super().perimeter()
return 0.5 * perimeter * self.slant_height + base_area
def area_2(self):
base_area = super().area()
triangle_area = super().tri_area()
return triangle_area * 4 + base_area
try
, except
, else
, and finally
statements.raise
statement.# Here an example of an exception
try:
raise Exception("Something went wrong!") # use the keyword raise to raise an exception
except Exception as e:
print(e) # "Something went wrong!"
else:
print("Everything is fine!")
finally:
print("This is always executed!")
# Here an example of cyclic imports
# file1.py
from file2 import function2
def function1():
return function2()
# file2.py
from file1 import function1
def function2():
return function1()
# Here an example of recursion that will raise an exception
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
fibonacci(10) # This will work
fibonacci(1000) # This will raise a RecursionError
sys
module.# Here an example of recursion limit
import sys
sys.setrecursionlimit(10000)
fibonacci(1000) # This will work but it will take a lot of time
# Do not run it, or just halt the execution