-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path04_injecting_functionality.py
More file actions
163 lines (109 loc) Β· 4.4 KB
/
04_injecting_functionality.py
File metadata and controls
163 lines (109 loc) Β· 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""04 - Inject functionality into a class in Python.
Use multiple inheritance to override functionality on base classes.
"""
import contextlib
import typing
class Person:
"""A person has a name and likes to do things."""
def __init__(self, *, name: str, **kwargs: typing.Any):
self.name = name
def __str__(self) -> str:
return f"{self.name}"
def stay_hydrated(self) -> None:
print(f"{self} drinks some water. π°")
def go_to_the_movies(self) -> None:
print(f"{self} goes to the movies. πΏ")
def go_hiking(self) -> None:
print(f"{self} goes hiking. β°")
def build_a_robot(self) -> None:
print(f"{self} builds a robot. π€")
class TeaPerson(Person):
"""A person who prefers tea over water."""
def stay_hydrated(self) -> None:
print(f"{self} drinks tea. π΅")
class Project:
"""A project has a board_name and a description."""
def __init__(self, board_name: str, description: str):
self.board_name = board_name
self.description = description
def __str__(self) -> str:
return f"Project '{self.board_name}'"
class TeamMember(Person):
"""A team member is a person, who works on projects, and may have
specialized in a specific field.
"""
expertise: typing.Optional[str] = None
def __str__(self) -> str:
# Get default string representation from the super class
default = super().__str__()
if self.expertise is None:
return f"{default}"
return f"{self.expertise} {default}"
@contextlib.contextmanager
def commute(self) -> typing.Generator:
"""Commute to the office and back."""
print(f"{self} commutes to the office. π’")
yield
print(f"{self} commutes home. π‘")
def work_on_project(self, project) -> None:
"""Start working on the given project."""
with self.commute():
print(f"{self} is now working on {project}. π")
self.stay_hydrated()
class MobileEngineer(TeamMember):
"""Team member specialized in developing for mobile platforms."""
expertise = "π±"
class DataScientist(TeamMember):
"""Team member specialized in data science."""
expertise = "π"
class ProjectManager(TeamMember):
"""Team member specialized in project management."""
expertise = "π"
class OperationsEngineer(TeamMember):
"""Team member specialized in running cloud infrastructure."""
expertise = "π¦"
class RemoteTeamMember(TeamMember):
"""Team member who works remotely."""
def __init__(self, *, workplace: str, **kwargs: typing.Any):
self.workplace = workplace
# Forward kwargs to super class
super().__init__(**kwargs)
@contextlib.contextmanager
def commute(self) -> typing.Generator:
"""Stay at home or commute to the workplace and back."""
if self.workplace == "home":
print(f"{self} works from home. π‘")
yield
return
print(f"{self} commutes to {self.workplace}. π")
yield
print(f"{self} commutes home. π‘")
class DataScientistWhoLikesTea(DataScientist, TeaPerson):
"""Data scientist who prefers tea over water."""
class ProjectManagerWhoWorksRemotely(ProjectManager, RemoteTeamMember):
"""Project manager who works remotely."""
class MobileEngineerWhoWorksRemotelyAndLikesTea(
MobileEngineer, RemoteTeamMember, TeaPerson
):
"""Mobile engineer who works remotely and prefers tea over water."""
if __name__ == "__main__":
simone = OperationsEngineer(name="Simone")
simone.go_to_the_movies()
simone.build_a_robot()
simone.go_hiking()
chelsea = DataScientistWhoLikesTea(name="Chelsea")
dave = ProjectManagerWhoWorksRemotely(name="Dave", workplace="a local coffee shop")
marlene = MobileEngineerWhoWorksRemotelyAndLikesTea(
name="Marlene", workplace="home"
)
data_platform = Project(
board_name="Data Platform",
description="Platform providing datasets and data viewing tools.",
)
simone.work_on_project(data_platform)
chelsea.work_on_project(data_platform)
dave.work_on_project(data_platform)
marlene.work_on_project(data_platform)