-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdecoratorPart2.py
More file actions
136 lines (108 loc) · 3.54 KB
/
Copy pathdecoratorPart2.py
File metadata and controls
136 lines (108 loc) · 3.54 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
"""
Decorators:
-----------
They are used to implement particular behavior for our classes.
Summary:
--------
1. property - Acts like an instance variable, no need to call like function.
2. static method - Directly called from the class.
3. class method - Returns a new instance of the class.
4. getter & setter - Used for `Data Encapsulation`.
Info:
-----
We can mark the class as `final` so that no other class can subclass it.
"""
from __future__ import annotations
import sys
from datetime import datetime
from enum import Enum, auto
from typing import final
print(sys.version)
class Role(Enum):
ASSOCIATE = auto()
SUPERVISOR = auto()
MANAGER = auto()
class Person:
def __init__(self, fname: str, lname: str) -> None:
self.fname = fname
self.lname = lname
def __str__(self) -> str:
return f"Person: {self.fname} {self.lname}"
@property
def fullname(self) -> str:
return f"{self.fname} {self.lname}"
p = Person("M", "V")
print(p)
print(p.fname)
@final
class Staff(Person):
# Class variable just for practice
STORE = "Walmart"
def __init__(self, fname: str, lname: str, staff_id: int, role: Role) -> None:
# Initialize parent/super class
super().__init__(fname, lname)
# Instance Variables/Members
self.staff_id = staff_id
self.is_staff = True
self.role = role
# Private Member
self._date_joined = datetime.now()
# Dynamically create & assign instance variables
match role:
case role.ASSOCIATE:
self.__salary: float = 15
case role.SUPERVISOR:
self.__salary = 20
case role.MANAGER:
self.__salary = 25
def __str__(self) -> str:
return f"Staff => Name: {self.fullname}, ID: {self.staff_id}"
@classmethod
def new(cls, person: Person, staff_id: int, role: Role) -> Staff:
"""
Create a new `Staff` instance
NOTE: It takes `class` as the first argument and return a instance
of that class.
"""
return cls(person.fname, person.lname, staff_id, role)
@property
def joined_on(self) -> str:
"""Joining date of staff member."""
return f"{self._date_joined.strftime('%B %d, %Y')}"
@staticmethod
def describe() -> None:
"""
Describes what the class does.
NOTE: It does not take `self` as an argument.
"""
print("Class to create a staff member")
@property
def salary(self) -> float:
"""`GETTER` returns the salary."""
return self.__salary
@salary.setter
def salary(self, amt: float) -> None:
"""`SETTER` sets salary after validation."""
if self.role == Role.ASSOCIATE and amt < 15:
print("Error! Associate cannot have salary less than $15/hr")
elif self.role == Role.SUPERVISOR and amt < 20:
print("Error! Supervisor cannot have salary less than $20/hr")
elif self.role == Role.MANAGER and amt < 25:
print("Error! Manager cannot have salary less than $25/hr")
else:
self.__salary = amt
print(f"{self.fullname} now has a salary of ${self.salary}/hr")
# -------------------------------------------------------------------------
p1 = Person("Louis", "Zappa")
print(p1.fullname)
s1 = Staff.new(p1, 1234, Role.SUPERVISOR)
print(s1)
print(s1.joined_on)
s2 = Staff("Chiko", "Jones", 3245, Role.MANAGER)
print(s2)
Staff.describe()
print(s1.salary)
print(s2.salary)
s1.salary = 17
s1.salary = 22
print(s1.salary)