class JazzRecord:
def __init__(self, player, album, year):
self.player = player
self.album = album
self.year = year
def as_string(self):
return "{} (by {}, {})".format(self.album, self.player, self.year)
record = JazzRecord("John Coltrane", "Giant Steps", 1957)
print(record.as_string())
import math
# we have to repeat some class declarations here
# so that our solution works in this notebook:
class Point2D:
def __init__(self, x0, y0):
self.x = x0 # set attribute x
self.y = y0 # set attribute y
def distance_to_origin(self):
"""method which computes length of Vector2D"""
return math.hypot(self.x, self.y)
def as_string(self):
return "<Point2D x={}, y={}>".format(self.x, self.y)
class Vector2D(Point2D):
def add(self, other):
""" is called when you execute self + other """
return Vector2D(self.x + other.x, self.y + other.y)
def length(self):
return self.distance_to_origin()
def as_string(self):
return "<Vector2D x={}, y={}>".format(self.x, self.y)
class FancyVector2D(Vector2D):
def __init__(self, x, y, name):
# call method of same name in base class
super().__init__(x, y)
self.name = name
def __len__(self):
# implements len(..) for a Point2D Object
return 2
def __str__(self):
# to string conversion, when str(.) is called
# or implicitly within print:
return "<FancyVector2D x={}, y={} name='{}'>".format(self.x, self.y, self.name)
def __add__(self, other):
# implements "self + other"
assert isinstance(other, FancyVector2D)
new_name = "{} + {}".format(self.name, other.name)
return FancyVector2D(self.x + other.x, self.y + other.y, new_name)
def __getitem__(self, index):
# square bracket access
if 0 <= index < 2:
return (self.x, self.y)[index]
raise IndexError()
def __eq__(self, other):
# implements "self == other"
if type(self) != type(other):
return False
return self.x == other.x and self.y == other.y
# SOLUTIONS FROM THE EXERCISE:
def scale(self, factor):
self.x *= factor
self.y *= factor
def __mul__(self, other):
assert isinstance(other, Vector2D) # can also be vector2d here !
return self.x * other.x + self.y * other.y
f = FancyVector2D(2, 1, "v1")
f.scale(2)
print(f)
v = Vector2D(1, 2)
print(f * v)
This solution implements a bit more than the exercise asked for:
class ComplexNumber(Vector2D):
def __str__(self):
if self.y == 0:
return str(self.x)
elif self.x == 0:
return "{} i".format(self.y)
elif self.y > 0:
return "{} + {} i".format(self.x, self.y)
else:
return "{} - {} i".format(self.x, -self.y)
def __mul__(self, other):
re = self.x * other.x - self.y * other.y
im = self.x * other.y + self.y * other.x
return ComplexNumber(re, im)
# EVERYTHING WHAT FOLLOWS NOW WAS NOT PART OF THE
# EXERCISE !
# used to print internals using repr() function
# we use the same implementation as for __str__:
__repr__ = __str__
def __neg__(self):
"implements unary minus"
return ComplexNumber(-self.x, -self.y)
def __abs__(self):
"called by abs(..) function"
return self.length()
def __iadd__(self, other):
"implementx self += other"
self.x += other.x
self.y += other.y
return self
def __float__(self):
"implements type conversion to float."
assert self.y == 0
return float(self.x) # could be int
def __hash__(self):
"""computes hash value, required if you want to use complex
numbers as keys of a dictionary, you als must implent
__eq__ to complete this"""
return hash((self.x, self.y)) # use builtin hash function
def __eq__(self, other):
if type(self) != type(other):
return False
return self.x == other.x and self.y == other.y
def __getattr__(self, name):
"is called when the user uses unknown attributes"
if name == "real":
return self.x
if name == "imag":
return self.y
raise AttributeError("instances of ComplexNumber have no attribute '{}'".format(name))
@property
def conjugate(self):
"""properties are computed attributes, so the client writes
c.conjugate and not c.conjugate()
we also could have used properites for implementin additional
real and imag attributes as we did it in __getattr__.
"""
return ComplexNumber(self.x, -self.y)
c1 = ComplexNumber(1, 1)
c2 = ComplexNumber(1, -1)
c3 = ComplexNumber(2, 0)
print("check to string conversion")
print("c1 is", c1)
print("c2 is", c2)
print("c3 is", c3)
print()
print("check multiplication")
print("c1 * c1 is", c1 * c1)
print("c1 * c2 is", c1 * c2)
print("c1 * c3 is", c1 * c3)
print()
print("-c1 is", -c1)
print("abs(c1) is", abs(c1))
print()
c1 += c2
print("c1 += c2 updated c1 to", c1)
print("c3 has no imag value, so conversion to float is", float(c3))
print()
print("dictionary with complex numbers as keys:")
dd = {c3: 1, c2: 2}
print(dd)
# this will also call __repr__ for the keys:
print("dd[c3] is", dd[c3])
print()
print("check if attribute lookup for real and imag works:")
print("c3.real is", c3.real)
print("c3.imag is", c3.imag)
print()
print("c1.conjugate is", c1.conjugate)