Python OOP

Python OOP Classes and Instances:

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
class Employee:
 
 
 
    def __init__(self, first, last, pay):
 
        self.first = first
 
        self.last = last
 
        self.email = first + '.' + last + '@email.com'
 
        self.pay = pay
 
 
 
    def fullname(self):
 
        return '{} {}'.format(self.first, self.last)
 
 
 
emp_1 = Employee('Alex', 'Brown', 50000)
 
emp_2 = Employee('Lisa', 'Miller', 60000)
 
 
 
print(type(emp_1)) # <class '__main__.Employee'>
 
 
 
print(emp_1.email) # Alex.Brown@email.com
 
 
 
print(emp_2.fullname()) # Lisa Miller
 
print(Employee.fullname(emp_2)) # Lisa Miller

Python OOP Class Variables:

Class Variables shared for all instances of the class.

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
class Employee:
 
    raise_amount = 1.04
 
    num_of_emps = 0
 
     
 
    def __init__(self, first, last, pay):
 
        self.first = first
 
        self.last = last
 
        self.email = first + '.' + last + '@email.com'
 
        self.pay = pay
 
 
 
        Employee.num_of_emps += 1
 
 
 
    def fullname(self):
 
        return '{} {}'.format(self.first, self.last)
 
     
 
    def apply_raise(self):
 
        self.pay = int(self.pay * self.raise_amount)
 
         
 
emp_1 = Employee('Alex', 'Brown', 50000)
 
emp_2 = Employee('Lisa', 'Miller', 60000)
 
 
 
print(emp_1.raise_amount) # 1.04
 
print(Employee.raise_amount) # 1.04
 
print(emp_1.pay) # 50000
 
emp_1.apply_raise()
 
print(emp_1.pay) # 52000
 
 
 
Employee.raise_amount = 1.05
 
 
 
print(Employee.raise_amount) # 1.05
 
print(emp_2.raise_amount) # 1.05
 
 
 
emp_2.raise_amount = 1.07
 
 
 
print(emp_2.raise_amount) # 1.07
 
 
 
print(emp_1.__dict__)
 
# {'first': 'Alex', 'last': 'Brown', 'email': 'Alex.Brown@email.com', 'pay': 50000}
 
 
 
print(emp_2.__dict__)
 
# {'first': 'Lisa', 'last': 'Miller', 'email': 'Lisa.Miller@email.com', 'pay': 60000, 'raise_amount': 1.07}
 
 
 
print(Employee.__dict__)
 
# {'__module__': '__main__', 'raise_amount': 1.04, 'num_of_emps': 2,
 
# '__init__': <function Employee.__init__ at 0x000001F34784EF28>,
 
# 'fullname': <function Employee.fullname at 0x000001F347852048>,
 
# 'apply_raise': <function Employee.apply_raise at 0x000001F3478520D0>,
 
# '__dict__': <attribute '__dict__' of 'Employee' objects>,
 
# '__weakref__': <attribute '__weakref__' of 'Employee' objects>, '__doc__': None}
 
 
 
print(Employee.num_of_emps) # 2

Python OOP classmethods

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
class Employee:
 
    raise_amount = 1.04
 
    num_of_emps = 0
 
     
 
    def __init__(self, first, last, pay):
 
        self.first = first
 
        self.last = last
 
        self.email = first + '.' + last + '@email.com'
 
        self.pay = pay
 
 
 
        Employee.num_of_emps += 1
 
 
 
    def fullname(self):
 
        return '{} {}'.format(self.first, self.last)
 
     
 
    def apply_raise(self):
 
        self.pay = int(self.pay * self.raise_amount)
 
 
 
    @classmethod
 
    def set_raise_amount(cls, amount):
 
        cls.raise_amount = amount
 
 
 
    @classmethod
 
    def from_string(cls, emp_str): # Alternative constructor
 
        first, last, pay = emp_str.split('-')
 
        return cls(first, last, pay)
 
         
 
emp_1 = Employee('Alex', 'Brown', 50000)
 
emp_2 = Employee('Lisa', 'Miller', 60000)
 
 
 
 
 
print(Employee.raise_amount) # 1.04
 
print(emp_1.raise_amount) # 1.04
 
print(emp_2.raise_amount) # 1.04
 
 
 
Employee.set_raise_amount(1.05)
 
print(Employee.raise_amount) # 1.05
 
print(emp_1.raise_amount) # 1.05
 
print(emp_2.raise_amount) # 1.05
 
 
 
emp_3 = Employee.from_string('Bob-Fox-70000')
 
print(emp_3.fullname()) # Bob Fox

Python OOP staticmethods

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
class Employee:
 
    raise_amount = 1.04
 
    num_of_emps = 0
 
     
 
    def __init__(self, first, last, pay):
 
        self.first = first
 
        self.last = last
 
        self.email = first + '.' + last + '@email.com'
 
        self.pay = pay
 
 
 
        Employee.num_of_emps += 1
 
 
 
    def fullname(self):
 
        return '{} {}'.format(self.first, self.last)
 
     
 
    def apply_raise(self):
 
        self.pay = int(self.pay * self.raise_amount)
 
 
 
    @classmethod
 
    def set_raise_amount(cls, amount):
 
        cls.raise_amount = amount
 
 
 
    @classmethod
 
    def from_string(cls, emp_str): # Alternative constructor
 
        first, last, pay = emp_str.split('-')
 
        return cls(first, last, pay)
 
 
 
    @staticmethod
 
    def is_workday(day):
 
        if day.weekday() == 5 or day.weekday() == 6: # Saturday or Sunday
 
            return False
 
        return True
 
         
 
emp_1 = Employee('Alex', 'Brown', 50000)
 
emp_2 = Employee('Lisa', 'Miller', 60000)
 
 
 
 
 
import datetime
 
 
 
my_date = datetime.date(2015,4,19)
 
print(Employee.is_workday(my_date)) # False

Python OOP Inheritance - Creating Subclasses

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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
class Employee:
 
    raise_amount = 1.04
 
    num_of_emps = 0
 
     
 
    def __init__(self, first, last, pay):
 
        self.first = first
 
        self.last = last
 
        self.email = first + '.' + last + '@email.com'
 
        self.pay = pay
 
 
 
        Employee.num_of_emps += 1
 
 
 
    def fullname(self):
 
        return '{} {}'.format(self.first, self.last)
 
     
 
    def apply_raise(self):
 
        self.pay = int(self.pay * self.raise_amount)
 
 
 
    @classmethod
 
    def set_raise_amount(cls, amount):
 
        cls.raise_amount = amount
 
 
 
    @classmethod
 
    def from_string(cls, emp_str): # Alternative constructor
 
        first, last, pay = emp_str.split('-')
 
        return cls(first, last, pay)
 
 
 
    @staticmethod
 
    def is_workday(day):
 
        if day.weekday() == 5 or day.weekday() == 6: # Saturday or Sunday
 
            return False
 
        return True
 
 
 
class Developer(Employee):
 
    raise_amount = 1.10
 
 
 
    def __init__(self, first, last, pay, prog_lang):
 
        super().__init__(first, last, pay)
 
        # Employee.__init__(self, first, last, pay) # Same as before
 
        self.prog_lang = prog_lang
 
 
 
class Manager(Employee):
 
 
 
    def __init__(self, first, last, pay, employees=None):
 
        super().__init__(first, last, pay)
 
        if employees is None:
 
            self.employees = []
 
        else:
 
            self.employees = employees
 
 
 
    def add_emp(self, emp):
 
        if emp not in self.employees:
 
            self.employees.append(emp)
 
 
 
    def del_emp(self, emp):
 
        if emp in self.employees:
 
            self.employees.remove(emp)
 
 
 
    def print_emps(self):
 
        for emp in self.employees:
 
            print('=emp=', emp.fullname())
 
 
 
 
 
dev_1 = Developer('Alex', 'Brown', 50000, 'Python')
 
dev_2 = Developer('Lisa', 'Miller', 60000, 'JavaScript')
 
 
 
print(type(dev_1)) # <class '__main__.Developer'>
 
# print(help(Developer)) # Shows info on Developer class
 
 
 
print(dev_1.fullname()) # Alex Brown
 
print(dev_2.fullname()) # Lisa Miller
 
 
 
print(dev_1.prog_lang) # Python
 
print(dev_2.prog_lang) # JavaScript
 
 
 
print(dev_1.pay) # 50000
 
dev_1.apply_raise()
 
print(dev_1.pay) # 55000
 
 
 
mgr_1 = Manager('Jack', 'Russell', 70000)
 
mgr_1.add_emp(dev_1)
 
mgr_1.print_emps() # Alex Brown
 
mgr_1.add_emp(dev_2)
 
mgr_1.print_emps() # Alex Brown, Lisa Miller
 
 
 
print(isinstance(mgr_1, Manager)) # True
 
print(isinstance(mgr_1, Employee)) # True
 
 
 
print(isinstance(dev_1, Manager)) # False
 
 
 
print(issubclass(Manager, Employee)) # True
 
print(issubclass(Manager, Developer)) # False

Python OOP Special (Magic/Dunder) Methods

More info on Special (Magic/Dunder) Methods

Special method names.

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
class Employee:
 
    raise_amount = 1.04
 
    num_of_emps = 0
 
     
 
    def __init__(self, first, last, pay):
 
        self.first = first
 
        self.last = last
 
        self.email = first + '.' + last + '@email.com'
 
        self.pay = pay
 
 
 
        Employee.num_of_emps += 1
 
 
 
    def fullname(self):
 
        return '{} {}'.format(self.first, self.last)
 
     
 
    def apply_raise(self):
 
        self.pay = int(self.pay * self.raise_amount)
 
 
 
    # This method is used for debug. It makes print(cls) and repr(cls) look pretty
 
    def __repr__(self):
 
        return "Employee('{}', '{}', {})".format(self.first, self.last, self.pay)
 
 
 
    # This method is used for debug. It makes print(cls) and str(cls) look pretty
 
    def __str__(self):
 
        return '{} - {}'.format(self.fullname(), self.email)
 
 
 
    def __len__(self):
 
        return len(self.fullname())
 
         
 
emp_1 = Employee('Alex', 'Brown', 50000)
 
emp_2 = Employee('Lisa', 'Miller', 60000)
 
 
 
print(emp_1) # Alex Brown - Alex.Brown@email.com
 
 
 
print(repr(emp_1)) # Employee('Alex', 'Brown', 50000)
 
print(emp_1.__repr__()) # same as prev line
 
print(str(emp_1)) # Alex Brown - Alex.Brown@email.com
 
print(emp_1.__str__()) # same as prev line
 
 
 
print(len(emp_1)) # 10

Python OOP Property Decorators - Getters, Setters, and Deleters

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
class Employee:
 
     
 
    def __init__(self, first, last):
 
        self.first = first
 
        self.last = last
 
 
 
    @property
 
    def email(self):
 
        return '{}.{}@email.com'.format(self.first, self.last)
 
 
 
    @property
 
    def fullname(self):
 
        return '{} {}'.format(self.first, self.last)
 
 
 
    @fullname.setter
 
    def fullname(self, name):
 
        self.first, self.last = name.split(' ')
 
         
 
    @fullname.deleter
 
    def fullname(self):
 
        print('Deleted!')
 
        self.first = None
 
        self.last = None
 
         
 
emp_1 = Employee('Alex', 'Brown')
 
emp_2 = Employee('Lisa', 'Miller')
 
 
 
emp_1.first = 'Jim'
 
print(emp_1.fullname) # Jim Brown
 
print(emp_1.email) # Jim.Brown@email.com
 
 
 
 
 
emp_1.fullname = 'Jack Russell'
 
 
 
print(emp_1.first) # Jack
 
print(emp_1.fullname) # Jack Russell
 
print(emp_1.email) # Jack.Russell@email.com
 
 
 
del emp_1.fullname
 
 
 
print(emp_1.first) # None
 
print(emp_1.fullname) # None None

Source: CoreyMS.com