# Properties
class Point:
def __init__(self, x, y): # constructor
self._xPos = x
self._yPos = y
@property # getter
def x(self):
print("Property get x position called\n")
return self._xPos
@x.setter # setter
def xPos(self, value):
if value < 1000:
self._xPos = value
else:
print("Value out of range\n")
point = Point(0, 0)
point.xPos += 125
# Magic methods / Dunder methods
# __init__ -> constructor
# __del__ -> destructor
# __str__ -> string representation of an object (output by print())
# __hash__ -> hash value of an object (used in dictionaries)
# __add__ -> allows defining the addition operation (+)
# __len__ -> returns the length of an object (used in len())
# __eq__ -> allows defining the equality operation (==)
# __lt__ -> allows defining the less than operation (<)
# __gt__ -> allows defining the greater than operation (>)
# ------------------------------- EXAMPLES -------------------------------
# __init__ and __str__ example
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
def __str__(self):
return f"{self._name} is {self._age} years old.\n"
p = Person("Matteo", 22)
print(p) # Output: Matteo is 22 years old.
# __add__ and __eq__ example
class Point:
def __init__(self, xPos, yPos):
self._xPos = xPos
self._yPos = yPos
def __add__(self, other):
return Point(self._xPos + other._xPos, self._yPos + other._yPos)
def __eq__(self, other):
return self._xPos == other._xPos and self._yPos == other._yPos
def __str__(self):
return f"Point({self._xPos}, {self._yPos})"
p1 = Point(1, 2)
p2 = Point(3, 4)
p3 = p1 + p2
print(p3) # Output: Point(4, 6)
print(p1 == p2) # Output: False
# __hash__ example
class Point:
def __init__(self, xPos, yPos):
self.__xPos = xPos
self.__yPos = yPos
def __eq__(self, other):
return self.__xPos == other.__xPos and self.__yPos == other.__yPos
def __hash__(self):
return hash((self.__xPos, self.__yPos)) # all attributes of Point
def __str__(self):
return f"Point({self.__xPos}, {self.__yPos})"
p1 = Point(1, 2)
p2 = Point(1, 2)
if p1 == p2: # comparison with __eq__
print("p1 and p2 are equal\n")
# ------------------- ValueError and ZeroDivisionError -------------------
try:
#age = int(input("Age: "))
age=10
xfactor = 10 / age
except (ValueError, ZeroDivisionError):
print("You didn’t enter a valid age.")
else:
print("No exceptions were thrown.\n")
# --- ValueError is "expensive" ---
# If you can avoid raising exceptions, do it
code1 = """
def calculate_xfactor(age):
if age <= 0:
raise ValueError("Invalid Age")
return 10 / age
try:
calculate_xfactor(-1)
except ValueError as error:
pass
"""
code2 = """
def calculate_xfactor(age):
if age <= 0:
return None
return 10 / age
xfactor = calculate_xfactor(-1)
if xfactor == None:
pass
"""
from timeit import timeit
print("first code ", round(timeit(code1, number=10000)*1000,3), "ms")
print("second code", round(timeit(code2, number=10000)*1000,3), "ms")
print(f"second code is {round((timeit(code1, number=10000)-timeit(code2, number=10000))*1000,3)} ms faster ({round((timeit(code2, number=10000)/timeit(code1, number=10000))*100,1)}% faster)\n")