This can be done with a single class, Employee
, which contains an attribute/member _manager
, which is a reference to this employees manager if any and an attribute/member '_managees', a set of all Employee instances/objects that this employee manages.
Note: I am going exclusively by my interpretation of the problem definition, which were bullet points 1-3 and not by the OP's or any other person's interpretation. The description for setPeer is sets A as a colleague of B. After that, A and B will have the same direct Manager. Thus when you call setPeer(A, B), you are setting A's manager to be B's manager and that it doesn't make any sense unless B has a manager. And everyone has a manager except for the head boss, and by definition the head boss can have no peers. So perhaps A just got a promotion (or a demotion or just a lateral move to another department). It doesn't mean that every former peer of A has gotten the same promotion and now have the same new manager, too. So I see this a less-complicated problem than others are making of it.
class Employee:
def __init__(self, name, manager=None):
self._name = name
self._managees = set()
self._manager = None # so far
if manager:
self.set_manager(manager) # Could be none if this is the "top dog"
def __repr__(self):
return f'Name: {self._name}, Managed By: {self._manager._name if self._manager else ""}, Manages: {[managee._name for managee in self._managees]}'
def get_name(self):
return self._name
def get_manager(self):
return self._manager
def get_managees(self):
return self._managees
def manages(self, employee):
return employee in self._managees
def is_managed_by(self, employee):
return self._manager is employee
def remove_manager(self):
"""
We are no longer managed by anyone.
"""
if self._manager:
self._manager.remove_managee(self)
self._manager = None
return self
def remove_managee(self, managee):
"""
This manager no longer manages managee.
"""
self._managees.remove(managee)
managee._manager = None # No longer has a manager
return self
def set_manager(self, manager):
if not manager:
self.remove_manager()
return self
if self._manager:
# We have an existing manager:
self._manager.remove_managee(self)
self._manager = manager
manager._managees.add(self)
return self
def add_managee(self, managee):
"""
This manager now manages managee.
"""
managee.set_manager(self)
return sell
def set_peer(self, managee):
assert managee._manager # Make sure managee can have a peer
self.set_manager(managee._manager)
return self
@staticmethod
def query(employee1, employee2):
"""
Is employee1 in the management chain of employee2?
"""
manager = employee2._manager
while manager:
if manager is employee1:
return True
manager = manager._manager
return False
tom = Employee('Tom')
dick = Employee('Dick', tom)
harry = Employee('Harry', dick)
sally = Employee('Sally')
sally.set_manager(harry)
assert sally.is_managed_by(harry) and harry.manages(sally)
sally.set_manager(tom)
assert sally.is_managed_by(tom) and tom.manages(sally)
sally.set_peer(harry)
assert sally.is_managed_by(dick) and dick.manages(sally)
assert Employee.query(tom, harry)
assert not Employee.query(harry, dick)
print(tom)
print(dick)
print(harry)
print(sally)
Prints:
Name: Tom, Managed By: , Manages: ['Dick']
Name: Dick, Managed By: Tom, Manages: ['Harry', 'Sally']
Name: Harry, Managed By: Dick, Manages: []
Name: Sally, Managed By: Dick, Manages: []