Skip to content

Commit a44b62a

Browse files
committed
Level 06: Beispiel für Vererbung: Komplexe Zahlen
1 parent 6ae3614 commit a44b62a

1 file changed

Lines changed: 182 additions & 0 deletions

File tree

Level_06/OOP2.py

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Dies ist ein Beispiel für Vererbung.
4+
5+
Wir implementieren hier die komplexen Zahlen,
6+
indem wir von der abstrakten Klasse numbers.Complex erben
7+
und die relevanten Methoden schreiben.
8+
9+
(Wenn man einfach nur mit komplexen Zahlen rechnen möchte,
10+
ist dieser Aufwand nicht nötig oder sinnvoll.
11+
`complex` ist bereits in der Standardbibliothek enthalten.)
12+
13+
Siehe auch https://docs.python.org/3.7/library/numbers.html.
14+
"""
15+
16+
from numbers import Complex
17+
from math import sqrt
18+
19+
__all__ = ["C"]
20+
21+
class C(Complex):
22+
"""
23+
Komplexe Zahlen haben einen Real- und einen Imaginärteil.
24+
25+
Sie werden häufig als a + bi geschrieben,
26+
wobei a der Realteil und b der Imaginärteil ist.
27+
28+
Man kann sie sich auch als zweidimensionalen Vektorraum vorstellen, der 1 + 0i (bzw. (1, 0)) und 0 + 1i (bzw. (0, 1)) als Basisvektoren hat, d.h. eine Dimension ist der Realteil und die andere Dimension ist der Imaginärteil
29+
"""
30+
real = 0 # type: float
31+
imag = 0 # type: float
32+
33+
def __init__(self, real: float = 0, imag: float = 0) -> None:
34+
"""
35+
Erstellt eine neue komplexe Zahl.
36+
37+
Sowohl Real- als auch Imaginärteil können weggelassen werden,
38+
dann wird einfach 0 angenommen.
39+
"""
40+
self.real = real
41+
self.imag = imag
42+
43+
def __abs__(self) -> float:
44+
"""
45+
Berechnet den Betrag einer komplexen Zahl.abs
46+
47+
Mit der Vektordarstellung (real, imag) sollte das klar sein
48+
- das ist nur der Satz von Pythagoras.
49+
"""
50+
return sqrt(self.real**2 + self.imag**2)
51+
52+
def __add__(self, o: Complex) -> C:
53+
"""
54+
Addiert zwei komplexe Zahlen.
55+
56+
Mit der Vektordarstellung sollte das klar sein:
57+
g = (a, b), h = (c, d), g + h = (a + c, b + d)
58+
"""
59+
assert isinstance(o, Complex)
60+
return C(self.real + o.real, self.imag + o.imag)
61+
62+
def __radd__(self, o: float) -> C:
63+
"""
64+
Addiert eine rationale Zahl zu einer komplexen Zahl.
65+
66+
Hierbei ändert sich einfach nur der Realteil.
67+
"""
68+
return C(self.real + o, self.imag)
69+
70+
def __mul__(self, o: Complex) -> C:
71+
"""
72+
Multipliziert zwei komplexe Zahlen.
73+
"""
74+
assert isinstance(o, Complex)
75+
return C(
76+
real=self.real * o.real - self.imag * o.imag,
77+
imag=self.real * o.imag + self.imag * o.real
78+
)
79+
80+
def __rmul__(self, o: float) -> C:
81+
"""
82+
Multipliziert eine rationale Zahl an eine komplexe Zahl.
83+
84+
Hierbei ändert sich nur der Realteil.
85+
"""
86+
return C(self.real * o, self.imag)
87+
88+
def __pow__(self, o: int) -> C:
89+
"""
90+
Potenziert eine komplexe Zahl.
91+
"""
92+
assert o >= 0
93+
value = C(1, 1)
94+
for i in range(o):
95+
value *= self
96+
return value
97+
98+
def __rpow__(self, o: float) -> C:
99+
"""
100+
Potenziert nur den Realteil.
101+
"""
102+
return C(self.real ** o, self.imag)
103+
104+
def __truediv__(self, o: Complex) -> C:
105+
"""
106+
Dividiert zwei komplexe Zahlen.
107+
"""
108+
assert isinstance(o, Complex)
109+
return C(
110+
real=(self.real * o.real + self.imag * o.imag) / (o.real ** 2 + o.imag ** 2),
111+
imag=(self.imag * o.real - self.real * o.imag) / (o.real ** 2 + o.imag ** 2)
112+
)
113+
114+
def __rtruediv__(self, o: float) -> C:
115+
"""
116+
Dividiert eine komplexe Zahl durch eine rationale Zahl.
117+
118+
Hierbei ändert sich nur der Realteil.
119+
"""
120+
return C(self.real / o, self.imag)
121+
122+
def __eq__(self, o: object) -> bool:
123+
"""
124+
Vergleicht zwei komplexe Zahlen auf Äquivalenz.
125+
126+
Mit der Vektordarstellung sollte das klar sein:
127+
g = (a, b), h = (c, d), (g = h) <=> (a = c ^ b = c)
128+
"""
129+
if not isinstance(o, Complex):
130+
return False
131+
return (self.real == o.real) and (self.imag == o.imag)
132+
133+
def conjugate(self) -> C:
134+
"""
135+
Berechnet das komplexe Konjugat einer komplexen Zahl.
136+
"""
137+
return C(self.real, -self.imag)
138+
139+
def __pos__(self) -> C:
140+
"""
141+
Berechnet +x (für x eine komplexe Zahl).
142+
"""
143+
return self
144+
145+
def __neg__(self) -> C:
146+
"""
147+
Berechnet -x (für x eine komplexe Zahl).
148+
"""
149+
return C(-self.real, -self.imag)
150+
151+
def __complex__(self) -> complex:
152+
"""
153+
Wandelt eine komplexe Zahl in eine complex-Instanz um.
154+
"""
155+
return complex(self.real, self.imag)
156+
157+
def __hash__(self) -> int:
158+
"""
159+
Berechnet den Hashwert einer komplexen Zahl.
160+
161+
Wichtig ist: Wenn zwei Zahlen äquivalent sind, sollen sie den gleichen Hash haben.
162+
163+
Wir machen es uns einfach und nehmen einfach die menschenlesbare Darstellung.
164+
"""
165+
return hash(repr(self))
166+
167+
def __repr__(self) -> str:
168+
"""
169+
Stellt eine komplexe Zahl menschenlesbar dar.
170+
171+
Dies gibt die Darstellung a + b i,
172+
nicht die Vektordarstellung (a, b) zurück.
173+
"""
174+
if self.imag >= 0:
175+
fstr = "{} + {}i"
176+
else:
177+
fstr = "{} - {}i"
178+
return fstr.format(self.real, self.imag)
179+
180+
if __name__ == "__main__":
181+
# Hier könnte Code stehen.
182+
pass

0 commit comments

Comments
 (0)