# image_processor.py # YOUR NAME(S) AND NETID(S) HERE # DATE COMPLETED HERE """Person class for a geneological database""" class Person(object): """Instance represents a person in a genealogical database. Person has a name, as well as a father, mother, and possibly some children.""" _first_name = '' # The first name of this person _last_name = '' # The first name of this person _mother = None # Person representing biological mother; None if unknown _father = None # Person representing biological father; None if unknown _children = None # List of all children (Person objects) of this Person # Empty list if no children. @property # getter, immutable def firstName(self): """First name of this person. Cannot be changed.""" return self._first_name @property # getter, immutable def lastName(self): """Last name of this person. Cannot be changed.""" return self._last_name @property # getter def mother(self): """Mother of this person. Invariant: A Person object. None if not known.""" return self._mother @mother.setter # setter def mother(self,value): assert value is None or type(value) == Person, `value`+' is an invalid mother' # IMPLEMENT ME # if there is an old mother # remove me from mother's list of children # set _mother to value # if there is a new mother (not None) # add me to mother's list of children @property # getter def father(self): """Father of this person. Invariant: A Person object. None if not known.""" return self._father @father.setter # setter def father(self,value): assert value is None or type(value) == Person, `value`+' is an invalid mother' # IMPLEMENT ME # if there is an old father # remove me from father's list of children # set _father to value # if there is a new father (not None) # add me to father's list of children @property # getter, immutable def children(self): """Children of this person. Cannot be changed. Returns a copy of the field, since otherwise we could modify the contents of the field even if we do not change the field directly.""" return self._children[:] # slice to copy def __init__(self, first='', last=''): """Constructor: Makes a person with given first and last name Precondition: first and last are both strings.""" assert type(first) == str, `first`+' is not a string' assert type(last) == str, `last`+' is not a string' self._first_name = first self._last_name = last self._children = list() # We have to do this for complicated reasons # Otherwise, all persons share the same list. def __str__(self): """Returns: description of this Person""" kids = len(self._children) kids = str(kids) + (' kid' if kids == 1 else ' kids') return self._last_name+','+self._first_name+' ['+kids+']' def fullstr(self,padding=''): """Returns: a string of this person and all ancestors. Each person is put on a new line. Each generation is indented by the amount padding, allowing us to separate generations. An ancestor is defined recursively. A mother or father of this Person is an ancestor. A mother or father of an ancestor is an ancestor. Precondition: padding is a string""" # Base case result = padding+str(self)+'\n' # Check mother for ancestors if not self.mother is None: result = result+self.mother.fullstr(padding+' ') # Check father for ancestors if not self.father is None: result = result+self.father.fullstr(padding+' ') return result def familyNamed(self,name): """Returns: number of family who share this Person's first name. The number of family members includes this person (e.g. self) as well as all family members. You should implement this method recursively. An ancestor is defined recursively as follows. A mother or father of this Person is an ancestor. A mother or father of an ancestor is an ancestor. Look at the method above for hints. Precondition: name is a string.""" # IMPLEMENT ME return 0 def test(): """Testing code. Easier than making a separate test module for this lab.""" # Construct the family tree # Great-Granparents f0 = Person('John','Smith') # John Smith Sr. m0 = Person('Pamela','Grey') m1 = Person('Eva', 'Brown') f2 = Person('Dan', 'O\'Reilly') m2 = Person('Heather','Chase') # Grandparents f3 = Person('John','Smith') # John Smith Jr. f3.father = f0 f3.mother = m0 m3 = Person('Jane','Dare') m3.mother = m1 f4 = Person('John','Evans') m4 = Person('Ellen','O\'Reilly') m4.father = f2 m4.mother = m2 # Parents f5 = Person('John','Smith') # John Smith III f5.father = f3 f5.mother = m3 m5 = Person('Ellen','Evans') m5.father = f4 m5.mother = m4 # Child p = Person('John', 'Smith') # John Smith IV p.father = f5 p.mother = m5 # Display the family tree print '' print 'Family Tree' print '-----------' print p.fullstr() # Test if property assignment is working correct. assert p.mother is m5, 'mother setter not assigning correctly' assert p.father is f5, 'father setter not assigning correctly' # Test if children updated assert len(m5.children) == 1, 'mother setter not updating children' assert p in m5.children, 'mother setter not updating children' assert len(f5.children) == 1, 'father setter not updating children' assert p in f5.children, 'father setter not updating children' # Remove someone from tree m4.mother = None assert m4.mother is None, 'mother setter not reassigning correctly' assert len(m2.children) == 0, 'mother setter not updating children correctly' m4.father = None assert m4.father is None, 'father setter not reassigning correctly' assert len(m2.children) == 0, 'father setter not updating children correctly' print 'Properties mother and father working correctly' print '' # Count the number with first name result = p.familyNamed('John') assert result == 5, 'ancestors named not working correctly' result = p.familyNamed('Ellen') assert result == 2, 'ancestors named not working correctly' result = p.familyNamed('Pamela') assert result == 1, 'ancestors named not working correctly' result = p.familyNamed('Alistair') assert result == 0, 'ancestors named not working correctly' print 'Method familyNamed working correctly' print '' # Application Code if __name__ == '__main__': test()