4.8. Polymorphism¶
4.8.1. Switch¶
Switch moves business logic to the execution place:
watney = 'Astronaut'
if watney == 'Astronaut':
print('Hello')
elif watney == 'Cosmonaut':
print('Привет!')
elif watney == 'Taikonaut':
print('你好')
else:
print('Default Value')
# Hello
def say_hello(key=None):
return {
'Astronaut': 'Hello',
'Cosmonaut': 'Привет!',
'Taikonaut': '你好',
}.get(key, 'Default Value')
watney = 'Astronaut'
ivanovic = 'Cosmonaut'
twardowski = 'Sorcerer'
say_hello(watney)
# Hello
say_hello(ivanovic)
# Привет!
say_hello(twardowski):
# 'Default Value'
4.8.2. Polymorphism in a Function¶
from abc import ABCMeta, abstractmethod
class UIElement(metaclass=ABCMeta):
@abstractmethod
def draw(self):
pass
class TextBox(UIElement):
def draw(self):
print('Drawing text box')
class CheckBox(UIElement):
def draw(self):
print('Drawing check box')
def draw(element: UIElement):
element.draw()
if __name__ == '__main__':
draw(TextBox())
draw(CheckBox())
class Sorcerer:
pass
class Astronaut:
def say_hello(self):
return 'Hello'
class Cosmonaut:
def say_hello(self):
return 'Привет!'
def say_hello(spaceman):
if hasattr(spaceman, 'say_hello')
return spaceman.say_hello()
else:
return 'Default Value'
watney = Astronaut()
ivanovic = Cosmonaut()
twardowski = Sorcerer()
say_hello(watney)
# Hello
say_hello(ivanovic)
# Привет!
say_hello(twardowski)
# 'Default Value'
4.8.3. Polymorphism on a Class¶
Polymorphism on Classes:
class Astronaut:
def __init__(self, name):
self.name = name
def say_hello(self):
return 'Hello'
class Cosmonaut:
def __init__(self, name):
self.name = name
def say_hello(self):
return 'Привет!'
crew = [
Astronaut('Mark Watney'),
Cosmonaut('Иван Иванович'),
Astronaut('Matt Kowalski'),
Cosmonaut('Jan Twardowski'),
]
for member in crew:
print(member.say_hello())
# Hello
# Привет!
# Hello
# Привет!
4.8.4. Factory¶
DATA = [('Sepal length', 'Sepal width', 'Petal length', 'Petal width', 'Species'),
(5.8, 2.7, 5.1, 1.9, 'virginica'),
(5.1, 3.5, 1.4, 0.2, 'setosa'),
(5.7, 2.8, 4.1, 1.3, 'versicolor'),
(6.3, 2.9, 5.6, 1.8, 'virginica'),
(6.4, 3.2, 4.5, 1.5, 'versicolor'),
(4.7, 3.2, 1.3, 0.2, 'setosa')]
class Iris:
def __init__(self, sepal_length, sepal_width, petal_length, petal_width):
self.sepal_length = sepal_length
self.sepal_width = sepal_width
self.petal_length = petal_length
self.petal_width = petal_width
def __repr__(self):
name = self.__class__.__name__
values = tuple(self.__dict__.values())
return f'\n {name}{values}'
class Setosa(Iris):
pass
class Virginica(Iris):
pass
class Versicolor(Iris):
pass
def factory(species: str):
if species == 'setosa':
return Setosa
if species == 'virginica':
return Virginica
if species == 'versicolor':
return Versicolor
result = []
for *features, species in DATA[1:]:
iris = factory(species)
i = iris(*features)
result.append(i)
print(result)
# [Virginica(5.8, 2.7, 5.1, 1.9),
# Setosa(5.1, 3.5, 1.4, 0.2),
# Versicolor(5.7, 2.8, 4.1, 1.3),
# Virginica(6.3, 2.9, 5.6, 1.8),
# Versicolor(6.4, 3.2, 4.5, 1.5),
# Setosa(4.7, 3.2, 1.3, 0.2)]
from dataclasses import dataclass
DATA = [('Sepal length', 'Sepal width', 'Petal length', 'Petal width', 'Species'),
(5.8, 2.7, 5.1, 1.9, 'virginica'),
(5.1, 3.5, 1.4, 0.2, 'setosa'),
(5.7, 2.8, 4.1, 1.3, 'versicolor'),
(6.3, 2.9, 5.6, 1.8, 'virginica'),
(6.4, 3.2, 4.5, 1.5, 'versicolor'),
(4.7, 3.2, 1.3, 0.2, 'setosa')]
@dataclass
class Iris:
sepal_length: float
sepal_width: float
petal_length: float
petal_width: float
class Setosa(Iris):
pass
class Virginica(Iris):
pass
class Versicolor(Iris):
pass
def factory(species: str):
species = species.capitalize()
classes = globals()
return classes[species]
result = [
factory(species)(*features)
for *features, species in DATA[1:]
]
print(result)
# [Virginica(sepal_length=5.8, sepal_width=2.7, petal_length=5.1, petal_width=1.9),
# Setosa(sepal_length=5.1, sepal_width=3.5, petal_length=1.4, petal_width=0.2),
# Versicolor(sepal_length=5.7, sepal_width=2.8, petal_length=4.1, petal_width=1.3),
# Virginica(sepal_length=6.3, sepal_width=2.9, petal_length=5.6, petal_width=1.8),
# Versicolor(sepal_length=6.4, sepal_width=3.2, petal_length=4.5, petal_width=1.5),
# Setosa(sepal_length=4.7, sepal_width=3.2, petal_length=1.3, petal_width=0.2)]