family ties
The tests from everything is an object show that in Python everything inherits. This allows me to make new objects that get their magic powers from other objects.
Making new objects can be easier with Inheritance because I do not have to write things that have already been written again, I can inherit them instead and change the new objects to do what I want.
It can also be more complicated because I can make new instances to inherit from one class and customize it for what I need instead of making new classes that require me to keep track of Python’s Method Resolution Order.
what is Python’s Method Resolution Order?
When an instance is made, Python calls every __init__ method of the parent and its parent going through every ancestor until it gets to the last one that is needed to make the instance.
how to make a class with a parent
To use inheritance I put the “parent” in parentheses when I make the new object (the child) to make the relationship.
class Child(Parent):
attribute = SOMETHING
def method():
the body of the method
...
questions about family ties
Questions to think about as I go through the chapter
preview
I have these tests by the end of the chapter
1import src.family_ties
2import unittest
3
4
5class TestFamilyTies(unittest.TestCase):
6
7 def test_making_a_class_w_inheritance(self):
8 person_class = src.person.Person
9 doe_class = src.family_ties.Doe
10 doe_instance = doe_class('the_first')
11
12 self.assertNotIsInstance(
13 doe_class, person_class
14 )
15
16 self.assertNotIsInstance(
17 doe_class, doe_class
18 )
19
20 self.assertIsSubclass(
21 doe_class, person_class
22 )
23
24 self.assertIsInstance(
25 doe_instance, person_class
26 )
27
28 self.assertEqual(
29 dir(doe_class), dir(person_class)
30 )
31
32 def test_classes_w_one_parent(self):
33 doe = src.family_ties.Doe('the_first')
34 self.assertEqual(doe.last_name, 'doe')
35
36 joe = src.family_ties.Blow('joe')
37 self.assertEqual(joe.last_name, 'blow')
38
39 blow = src.person.Person('joe', last_name='blow')
40 self.assertEqual(blow.last_name, joe.last_name)
41
42 jane = src.person.Person('jane')
43 self.assertEqual(jane.last_name, doe.last_name)
44
45 john = src.family_ties.Smith('john')
46 self.assertEqual(john.last_name, 'smith')
47
48 smith = src.person.Person('john', 'smith')
49 self.assertEqual(smith.last_name, john.last_name)
50
51 def test_classes_w_multiple_parents(self):
52 joe = src.family_ties.Joe()
53 self.assertEqual(joe.first_name, 'joe')
54 self.assertEqual(joe.last_name, 'blow')
55 self.assertEqual(joe.eye_color, 'blue')
56 self.assertIsSubclass(
57 src.family_ties.Joe, src.family_ties.Blow
58 )
59
60 jane = src.family_ties.Jane()
61 self.assertEqual(jane.first_name, 'jane')
62 self.assertEqual(jane.last_name, 'doe')
63 self.assertEqual(jane.eye_color, 'green')
64 self.assertIsSubclass(
65 src.family_ties.Jane, src.family_ties.Doe
66 )
67
68 mary = src.family_ties.Mary()
69 self.assertEqual(mary.first_name, 'mary')
70 self.assertEqual(mary.last_name, jane.last_name)
71 self.assertEqual(mary.eye_color, joe.eye_color)
72 self.assertIsSubclass(
73 src.family_ties.Mary, src.family_ties.Jane
74 )
75 self.assertIsSubclass(
76 src.family_ties.Mary, src.family_ties.Joe
77 )
78
79 john = src.family_ties.John()
80 self.assertEqual(john.first_name, 'john')
81 self.assertEqual(john.last_name, 'smith')
82 self.assertEqual(john.eye_color, 'brown')
83 self.assertIsSubclass(
84 src.family_ties.John, src.family_ties.Smith
85 )
86
87 lil = src.family_ties.Lil()
88 self.assertEqual(lil.first_name, 'lil')
89 self.assertEqual(lil.last_name, john.last_name)
90 self.assertEqual(lil.eye_color, mary.eye_color)
91 self.assertIsSubclass(
92 src.family_ties.Lil, src.family_ties.John
93 )
94 self.assertIsSubclass(
95 src.family_ties.Lil, src.family_ties.Mary
96 )
97
98
99# Exceptions seen
100# AssertionError
101# NameError
102# AttributeError
103# ModuleNotFoundError
104# TypeError
requirements
open the project
I change directory to the
personfoldercd personthe terminal shows I am in the
personfolder.../pumping_python/personI make a new file in the
testsfolder namedtest_family_ties.pytouch tests/test_family_ties.pyI make a new file in the
srcfolder namedfamily_ties.pytouch src/family_ties.pyI open
test_family_ties.pyI add the first failing test to
test_family_ties.py1import unittest 2 3 4class TestFamilyTies(unittest.TestCase): 5 6 def test_failure(self): 7 self.assertFalse(True)I go back to the terminal to add the new files and folders to git for tracking
git add .the terminal goes back to the command line.
I use
pytest-watcherto run the testsuv run pytest-watcher . --nowthe terminal is my friend, and shows AssertionError
============================ FAILURES ========================== _________________ TestFamilyTies.test_failure __________________ self = <tests.test_family_ties.TestFamilyTies testMethod=test_failure> def test_failure(self): > self.assertFalse(True) E AssertionError: True is not false tests/test_family_ties.py:7: AssertionError =================== short test summary info ==================== FAILED tests/test_family_ties.py::TestFamilyTies::test_failure - AssertionError: True is not false ================= 1 failed, 6 passed in X.YZs ==================I add AssertionError to the list of Exceptions seen, in
test_functions.py4class TestFamilyTies(unittest.TestCase): 5 6 def test_failure(self): 7 self.assertFalse(True) 8 9 10# Exceptions seen 11# AssertionErrorI change True to False in the assertion
7 self.assertFalse(False)the test passes.
test_making_a_class_w_inheritance
I know from test_making_a_class_w_object that I can make classes with inheritance by stating the parent class and that an instance (a copy) and a subclass (child) are different.
RED: make it fail
I go back to the terminal where the tests are running
I change test_failure to test_making_a_class_w_inheritance with an assertion
4class TestFamilyTies(unittest.TestCase): 5 6 def test_making_a_class_w_inheritance(self): 7 self.assertIsInstance( 8 src.family_ties.Doe, 9 src.person.Person 10 ) 11 12 13# Exceptions seenthe terminal is my friend, and shows NameError
NameError: name 'src' is not definedbecause
srcis not defined in this file.I add NameError to the list of Exceptions seen
4# Exceptions seen 5# AssertionError 6# NameError
GREEN: make it pass
I add an import statement for the
family_tiesmodule at the top of the file1import src.family_ties 2import unittest 3 4 5class TestFamilyTies(unittest.TestCase):import src.family_tiesbrings in an object for thefamily_ties.pymodule from thesrcfolder so I can use it intest_family_ties.pythe terminal is my friend, and shows AttributeError
AttributeError: module 'src.family_ties' has no attribute 'Doe'because there is no definition for
Doeinfamily_ties.py
I add AttributeError to the list of Exceptions seen
14# Exceptions seen 15# AssertionError 16# NameError 17# AttributeErrorI open
family_ties.pyfrom thesrcfolderI add a class definition definition to
family_ties.py1class Doe(object): passthe terminal is my friend, and shows AssertionError
AssertionError: <class 'src.family_ties.Doe'> is not an instance of <class 'src.person.Person'>because
Doeis not an instance (a copy) ofPerson.I change the assertion in test_making_a_class_w_inheritance in
test_family_ties.py7 def test_making_a_class_w_inheritance(self): 8 # self.assertIsInstance( 9 self.assertNotIsInstance( 10 src.family_ties.Doe, 11 src.person.Person 12 ) 13 14 15# Exceptions seenthe test passes.
Doeis NOT an instance of thePersonclass, they are siblings - both children of object.
REFACTOR: make it better
I add a call to assertIsSubclass
7 def test_making_a_class_w_inheritance(self): 8 self.assertIsInstance( 9 # self.assertNotIsInstance( 10 src.family_ties.Doe, 11 src.person.Person 12 ) 13 14 self.assertIsSubclass( 15 src.family_ties.Doe, 16 src.person.Person 17 ) 18 19 20# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'src.family_ties.Doe'> is not a subclass of <class 'src.person.Person'>because
Doeis not a child ofPerson, yet.I change the parent of
DoefromobjecttoPersoninfamily_ties.py1# class Doe(object): pass 2class Doe(person.Person): passthe terminal is my friend, and shows NameError
NameError: name 'person' is not definedbecause there is no definition for
personinfamily_ties.pyI add an import statement at the top of
family_ties.py1import person 2 3 4# class Doe(object): pass 5class Doe(person.Person): passthe terminal is my friend, and shows ModuleNotFoundError
E ModuleNotFoundError: No module named 'person'because Python cannot find
person.pyin the main project folder (the parent ofsrcandtests) where I run the tests from, so it cannot import the Module.I add ModuleNotFoundError to the list of Exceptions seen, in
test_family_ties.py20# Exceptions seen 21# AssertionError 22# NameError 23# AttributeError 24# ModuleNotFoundErrorI add the path of
person.pyfrom the main project folder (the parent ofsrcandtests) to the import statement, infamily_ties.py1# import person 2import src.person 3 4 5# class Doe(object): pass 6class Doe(person.Person): passthe terminal is my friend, it goes back to NameError
NameError: name 'person' is not definedbecause there is no definition for
personin this file.I add
src.to the parent ofDoe5# class Doe(object): pass 6# class Doe(person.Person): pass 7class Doe(src.person.Person): passimport src.personbrings in an object for theperson.pymodule from thesrcfolder so I can use it infamily_ties.py.I have to use
src.person.Personinfamily_ties.pybecause I am testing from the root folder of the project (the parent folder ofsrcandtests).The test needs to know where
person.pyis in relation to where I ran the tests from.This is a problem because if
family_ties.pyis run from insidesrcthe import statement will not be able to findsrc.personfrom insidesrc. Same thing if I run the tests from insidetests(a problem for another time).The test passes because
Doeis now a child (subclass) ofPerson.
more about instances vs subclasses
I add a call to assertIsInstance to show that
src.family_ties.Doeis not an instance7 def test_making_a_class_w_inheritance(self): 8 # self.assertIsInstance( 9 self.assertNotIsInstance( 10 src.family_ties.Doe, 11 src.person.Person 12 ) 13 14 self.assertIsInstance( 15 src.family_ties.Doe, 16 src.family_ties.Doe 17 ) 18 19 self.assertIsSubclass( 20 src.family_ties.Doe, 21 src.person.Person 22 ) 23 24 25# Exceptions seenthe terminal shows AssertionError
AssertionError: <class 'src.family_ties.Doe'> is not an instance of <class 'src.family_ties.Doe'>I change assertIsInstance to assertNotIsInstance
7 def test_making_a_class_w_inheritance(self): 8 # self.assertIsInstance( 9 self.assertNotIsInstance( 10 src.family_ties.Doe, 11 src.person.Person 12 ) 13 14 # self.assertIsInstance( 15 self.assertNotIsInstance( 16 src.family_ties.Doe, 17 src.family_ties.Doe 18 ) 19 20 self.assertIsSubclass( 21 src.family_ties.Doe, 22 src.person.Person 23 ) 24 25 26# Exceptions seenI add a variable
7 def test_making_a_class_w_inheritance(self): 8 doe_class = src.family_ties.Doe 9 10 # self.assertIsInstance( 11 self.assertNotIsInstance( 12 src.family_ties.Doe, 13 src.person.Person 14 )I use the variable to remove repetition of
src.family_ties.Doefrom the test7 def test_making_a_class_w_inheritance(self): 8 doe_class = src.family_ties.Doe 9 10 # self.assertIsInstance( 11 self.assertNotIsInstance( 12 # src.family_ties.Doe, 13 doe_class, 14 src.person.Person 15 ) 16 17 # self.assertIsInstance( 18 self.assertNotIsInstance( 19 # src.family_ties.Doe, 20 # src.family_ties.Doe 21 doe_class, doe_class 22 ) 23 24 self.assertIsSubclass( 25 # src.family_ties.Doe, 26 doe_class, 27 src.person.Person 28 ) 29 30 31# Exceptions seenthe test is still green.
what happens when a child calls the parent?
I add a call to the assertIsInstance method, this time with an instance of
Doe24 self.assertIsSubclass( 25 # src.family_ties.Doe, 26 doe_class, 27 src.person.Person 28 ) 29 30 self.assertIsInstance( 31 src.family_ties.Doe(), 32 src.person.Person 33 ) 34 35 36# Exceptions seenthe terminal is my friend, and shows TypeError
TypeError: Person.__init__() missing 1 required positional argument: 'first_name'I called
Doeto make an instance. How didPerson.__init__get called?Here is what is happens when
src.class.Doe()runssrc.family_ties.Doe() Doe # has no __init__ # call the parent of Doe (Person) Person.__init__()which raises TypeError since the __init__ method of the
Personclass takes one required argument forfirst_name.I add TypeError to the list of Exceptions seen
36# Exceptions seen 37# AssertionError 38# NameError 39# AttributeError 40# ModuleNotFoundError 41# TypeError
how to call the parent from the child
I add the super built-in function to
Doeto call the parent __init__ method (Parent.__init__) directly fromDoe, infamily_ties.py5# class Doe(object): pass 6# class Doe(person.Person): pass 7# class Doe(src.person.Person): pass 8class Doe(src.person.Person): 9 10 def __init__(self): 11 super().__init__()the super built-in function calls the __init__ method of the parent class
super()is the parent - “super class” for parent, “subclass” for childsuperisPersonin this casesuper().__init__()isPerson.__init__()in this casethe terminal still shows TypeError
TypeError: Person.__init__() missing 1 required positional argument: 'first_name'because this is what happens now when
src.class.Doe()runssrc.family_ties.Doe() Doe.__init__() super().__init__() # super is the parent (Person) Person.__init__()which raises TypeError since the __init__ method of the
Personclass takes one required argument forfirst_name.
I add a value for
first_nameto the call tosrc.family_ties.Doe()in test_making_a_class_w_inheritance intest_family_ties.py30 self.assertIsInstance( 31 # src.family_ties.Doe(), 32 src.family_ties.Doe('the_first'), 33 src.person.Person 34 ) 35 36 37# Exceptions seenthe terminal is my friend, and shows TypeError
TypeError: Doe.__init__() takes 1 positional argument but 2 were givenbecause this happens when
src.family_ties.Doe('the_first')runssrc.family_ties.Doe('the_first') Doe.__init__('the_first')which raises TypeError since the definition for the __init__ method of
Doeonly takes one positional argument (self) and it was called with two (selfand'the_first')selfis the instance of the class.
I add a parameter for
first_nameto the __init__ method ofDoeinfamily_ties.py5# class Doe(object): pass 6# class Doe(person.Person): pass 7# class Doe(src.person.Person): pass 8class Doe(src.person.Person): 9 10 # def __init__(self): 11 def __init__(self, first_name): 12 super().__init__()the terminal is my friend, and shows TypeError
TypeError: Person.__init__() missing 1 required positional argument: 'first_name'because this happens when
src.family_ties.Doe('the_first')runssrc.family_ties.Doe('the_first') Doe.__init__('the_first') super().__init__() # call the parent Person.__init__()which raises TypeError since the definition for the __init__ method of
Personrequires a positional argument forfirst_nameand it was called withselfselfis the instance of the class.
I add the required parameter to
super().__init__()inDoe5# class Doe(object): pass 6# class Doe(person.Person): pass 7# class Doe(src.person.Person): pass 8class Doe(src.person.Person): 9 10 # def __init__(self): 11 def __init__(self, first_name): 12 # super().__init__() 13 super().__init__(first_name)the test passes because
an instance (a copy) of
Doeis an an instance (a copy) ofPersonPersonis the parent ofDoethe test shows that this happens when
src.family_ties.Doe('the_first')runssrc.family_ties.Doe('the_first') Doe.__init__('the_first') super().__init__('the_first') Person.__init__('the_first')
I add a test for the attributes and methods of the
Doeclass30 self.assertIsInstance( 31 # src.family_ties.Doe(), 32 src.family_ties.Doe('the_first'), 33 src.person.Person 34 ) 35 36 self.assertEqual( 37 dir(doe_class), 38 [] 39 ) 40 41 42# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: Lists differ: ['__class__', '__delattr__', '__dict__', '[370 chars]llo'] != []I change the expectation to the attributes and methods of the
Personclass36 self.assertEqual( 37 dir(doe_class), 38 # [] 39 dir(src.person.Person) 40 ) 41 42 43# Exceptions seenthe test passes because
Doehas the same attributes and methods asPersonbecauseDoeis a child ofParent.I add a variable
7 def test_making_a_class_w_inheritance(self): 8 person_class = src.person.Person 9 doe_class = src.family_ties.DoeI use the variable to remove repetition of
src.person.Personfrom the test7 def test_making_a_class_w_inheritance(self): 8 person_class = src.person.Person 9 doe_class = src.family_ties.Doe 10 11 # self.assertIsInstance( 12 self.assertNotIsInstance( 13 # src.family_ties.Doe, 14 doe_class, 15 # src.person.Person 16 person_class 17 ) 18 19 # self.assertIsInstance( 20 self.assertNotIsInstance( 21 # src.family_ties.Doe, 22 # src.family_ties.Doe 23 doe_class, doe_class 24 ) 25 26 self.assertIsSubclass( 27 # src.family_ties.Doe, 28 doe_class, 29 # src.person.Person 30 person_class 31 ) 32 33 self.assertIsInstance( 34 # src.family_ties.Doe(), 35 src.family_ties.Doe('the_first'), 36 # src.person.Person 37 person_class 38 ) 39 40 self.assertEqual( 41 dir(doe_class), 42 # [] 43 # dir(src.person.Person) 44 dir(person_class) 45 ) 46 47 48# Exceptions seenstill green.
I add a variable for
src.family_ties.Doe('the_first')7 def test_making_a_class_w_inheritance(self): 8 person_class = src.person.Person 9 doe_class = src.family_ties.Doe 10 doe_instance = doe_class('the_first') 11 12 # self.assertIsInstance( 13 self.assertNotIsInstance( 14 # src.family_ties.Doe, 15 doe_class, 16 # src.person.Person 17 person_class 18 )I use the new variable
34 self.assertIsInstance( 35 # src.family_ties.Doe(), 36 # src.family_ties.Doe('the_first'), 37 doe_instance, 38 # src.person.Person 39 person_class 40 )green, because
doe_class()andsrc.classes.Doe()are the same sincedoe_class = src.classes.Doe.I remove the commented lines
7 def test_making_a_class_w_inheritance(self): 8 person_class = src.person.Person 9 doe_class = src.family_ties.Doe 10 doe_instance = doe_class('the_first') 11 12 self.assertNotIsInstance( 13 doe_class, person_class 14 ) 15 16 self.assertNotIsInstance( 17 doe_class, doe_class 18 ) 19 20 self.assertIsSubclass( 21 doe_class, person_class 22 ) 23 24 self.assertIsInstance( 25 doe_instance, person_class 26 ) 27 28 self.assertEqual( 29 dir(doe_class), dir(person_class) 30 ) 31 32 33# Exceptions seenI remove the commented lines from
family_ties.py1import src.person 2 3 4class Doe(src.person.Person): 5 6 def __init__(self, first_name): 7 super().__init__(first_name)I add a git commit message in the other terminal
git commit -am \ 'add test_making_a_class_w_inheritance'
test_classes_w_one_parent
I want to test how the attributes of classes are set if they have only one parent (super class).
RED: make it fail
I go back to the terminal where the tests are running
I add a new test for Inheritance with an assertion, in
test_family_ties.py28 self.assertEqual( 29 dir(doe_class), dir(person_class) 30 ) 31 32 def test_classes_w_one_parent(self): 33 doe = src.family_ties.Doe('the_first') 34 self.assertEqual(doe.last_name, '') 35 36 37# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'doe' != ''
GREEN: make it pass
I change the expectation
32 def test_classes_w_one_parent(self):
33 doe = src.family_ties.Doe('the_first')
34 # self.assertEqual(doe.last_name, '')
35 self.assertEqual(doe.last_name, 'doe')
36
37
38# Exceptions seen
the test passes because this happens when doe = src.family_ties.Doe('the_first') runs
doe = src.family_ties.Doe('the_first')
Doe.__init__('the_first')
super().__init__(first_name)
Person.__init__('the_first')
Person.__init__('the_first', last_name='the_first')
self.last_name = 'the_first' # use the default value
the value for doe.last_name is doe because a method uses the default value for a parameter when it is called without the parameter.
REFACTOR: make it better
I add another assertion
32 def test_classes_w_one_parent(self): 33 doe = src.family_ties.Doe('the_first') 34 # self.assertEqual(doe.last_name, '') 35 self.assertEqual(doe.last_name, 'doe') 36 37 joe = src.family_ties.Blow('joe') 38 self.assertEqual(joe.last_name, 'blow') 39 40 41# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.family_ties' has no attribute 'Blow'because there is no definition for
Blowinfamily_ties.pyI add a new class definition to
family_ties.py4class Doe(src.person.Person): 5 6 def __init__(self, first_name): 7 super().__init__(first_name) 8 9 10class Blow(src.person.Person): passthe terminal is my friend, and shows AssertionError
AssertionError: 'doe' != 'blow'because this happens when
joe = src.family_ties.Blow('joe')runsjoe = src.family_ties.Blow('joe') Blow # has no __init__ # call the parent of Blow (Person) Person.__init__('joe') Person.__init__('joe', last_name='doe') self.last_name = 'doe' # use the default valueI add a class attribute for
last_namein theBlowclass infamily_ties.py10# class Blow(src.person.Person): pass 11class Blow(src.person.Person): 12 13 last_name = 'blow'the terminal does not feel like my friend, it still shows AssertionError because this happens when
joe = src.family_ties.Blow('joe')runsjoe = src.family_ties.Blow('joe') Blow # has no __init__ # call the parent of Blow (Person) self.last_name = 'blow' Person.__init__('joe') Person.__init__('joe', last_name='doe') self.last_name = 'doe' # use the default valuethe value for
last_namedoes not get sent to the parent (Person.__init__)I add the __init__ method to customize the last name
10# class Blow(src.person.Person): pass 11class Blow(src.person.Person): 12 13 # last_name = 'blow' 14 15 def __init__(self): 16 self.last_name = 'blow'the terminal is my friend, and shows TypeError
TypeError: Blow.__init__() takes 1 positional argument but 2 were givenbecause this happens when
joe = src.family_ties.Blow('joe')runsjoe = src.family_ties.Blow('joe') Blow.__init__('joe')which raises TypeError since the __init__ method of
Blowonly takes one positional argument (self) and it got called with two (selfandfirst_name).selfis the instance of the class.
I add
first_nameto the parentheses of the__init__method definition10# class Blow(src.person.Person): pass 11class Blow(src.person.Person): 12 13 # last_name = 'blow' 14 15 # def __init__(self): 16 def __init__(self, first_name): 17 self.last_name = 'blow'the test passes because this happens when
joe = src.family_ties.Blow('joe')runsjoe = src.family_ties.Blow('joe') Blow.__init__('joe') self.last_name = 'joe'I can make classes that are related and have their own defaults. In this test
the
Doeclass has a default value for thelast_nameattribute that is the default value for thelast_nameattribute ofPersonthe
Blowclass has a different default value for the value of thelast_nameattributeDoeandBloware children (subclasses) ofPerson
I remove the commented lines
4class Doe(src.person.Person): 5 6 def __init__(self, first_name): 7 super().__init__(first_name) 8 9 10class Blow(src.person.Person): 11 12 def __init__(self, first_name): 13 self.last_name = 'blow'In this case there is a simpler way to make
joeanddoe. I could pass the values to thePersonclass directly, since all theBlowclass does is customize thelast_nameattribute, there is nothing special about it or theDoeclass. I add an assertion to test_classes_w_one_parent intest_family_ties.py32 def test_classes_w_one_parent(self): 33 doe = src.family_ties.Doe('the_first') 34 # self.assertEqual(doe.last_name, '') 35 self.assertEqual(doe.last_name, 'doe') 36 37 joe = src.family_ties.Blow('joe') 38 self.assertEqual(joe.last_name, 'blow') 39 40 blow = src.person.Person('joe') 41 self.assertEqual(blow.last_name, joe.last_name) 42 43 44# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'doe' != 'blow'I add
last_name='blow'to the call40 # blow = src.person.Person('joe') 41 blow = src.person.Person('joe', last_name='blow') 42 self.assertEqual(blow.last_name, joe.last_name) 43 44 45# Exceptions seenthe test passes. I can make an instance and change the values of its attributes without making a new class.
I add an assertion for
jane40 # blow = src.person.Person('joe') 41 blow = src.person.Person('joe', last_name='blow') 42 self.assertEqual(blow.last_name, joe.last_name) 43 44 jane = src.person.Person('jane') 45 self.assertEqual(jane.last_name, blow.last_name) 46 47 48# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'doe' != 'blow'I change the expectation
44 jane = src.person.Person('jane') 45 # self.assertEqual(jane.last_name, blow.last_name) 46 self.assertEqual(jane.last_name, doe.last_name) 47 48 49# Exceptions seenthe test passes.
I add an assertion for
john44 jane = src.person.Person('jane') 45 # self.assertEqual(jane.last_name, blow.last_name) 46 self.assertEqual(jane.last_name, doe.last_name) 47 48 john = src.family_ties.Smith('john') 49 self.assertEqual(john.last_name, 'smith') 50 51 52# Exceptions seenthe terminal shows AttributeError
AttributeError: module 'src.family_ties' has no attribute 'Smith'I add a class definition for
Smithtofamily_ties.py10class Blow(src.person.Person): 11 12 def __init__(self, first_name): 13 self.last_name = 'blow' 14 15 16class Smith(src.person.Person): passthe terminal is my friend, and shows AssertionError
AssertionError: 'doe' != 'smith'because this happens when
john = src.family_ties.Smith('john')runsjohn = src.family_ties.Smith('john') Smith # has no __init__ # call the parent of Smith (Person) Person.__init__('john') Person.__init__('john', last_name='doe') self.last_name = 'doe' # use the default valueI add the __init__ method to
Smith16# class Smith(src.person.Person): pass 17class Smith(src.person.Person): 18 19 def __init__(self): 20 self.last_name = 'smith'TypeError: Smith.__init__() takes 1 positional argument but 2 were givenbecause this happens when
john = src.family_ties.Smith('john')runsjohn = src.family_ties.Smith('john') Smith.__init__('john')which raises TypeError since the definition for the __init__ method of
Smithtakes only one positional argument (self) and it got called with two (selfand'john')selfis the instance of the class.
I add
first_nameto the parentheses of the __init__ method16# class Smith(src.person.Person): pass 17class Smith(src.person.Person): 18 19 # def __init__(self): 20 def __init__(self, first_name): 21 self.last_name = 'smith'the test passes because this happens when
john = src.family_ties.Smith('john')runsjohn = src.family_ties.Smith('john') Smith.__init__('john') self.last_name = 'smith'I remove the commented lines
10class Blow(src.person.Person): 11 12 def __init__(self, first_name): 13 self.last_name = 'blow' 14 15 16class Smith(src.person.Person): 17 18 def __init__(self, first_name): 19 self.last_name = 'smith'the test passes.
I add another assertion to test_classes_w_one_parent in
test_family_ties.py48 john = src.family_ties.Smith('john') 49 self.assertEqual(john.last_name, 'smith') 50 51 smith = src.person.Person('john', 'smith') 52 self.assertEqual(smith.last_name, doe.last_name) 53 54 55# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'smith' != 'doe'I change the expectation
51 smith = src.person.Person('john', 'smith') 52 # self.assertEqual(smith.last_name, doe.last_name) 53 self.assertEqual(smith.last_name, john.last_name) 54 55 56# Exceptions seenthe test passes.
I remove the commented lines
32 def test_classes_w_one_parent(self): 33 doe = src.family_ties.Doe('the_first') 34 self.assertEqual(doe.last_name, 'doe') 35 36 joe = src.family_ties.Blow('joe') 37 self.assertEqual(joe.last_name, 'blow') 38 39 blow = src.person.Person('joe', last_name='blow') 40 self.assertEqual(blow.last_name, joe.last_name) 41 42 jane = src.person.Person('jane') 43 self.assertEqual(jane.last_name, doe.last_name) 44 45 john = src.family_ties.Smith('john') 46 self.assertEqual(john.last_name, 'smith') 47 48 smith = src.person.Person('john', 'smith') 49 self.assertEqual(smith.last_name, john.last_name) 50 51 52# Exceptions seenFrom the class definition of
Doe, this happens when an instance (a copy) ofDoeis madesrc.family_ties.Doe('first_name') Doe.__init__('first_name') super().__init__(first_name) Person.__init__('first_name') Person.__init__('first_name', last_name='doe') self.last_name = 'doe' # use the default valuebecause a method uses the default value for the parameter because it is called without the parameter.
From the class definitions of
SmithandBlowthis happens when an instance (a copy) ofSmithorBlowis madesrc.family_ties.ClassName('first_name') ClassName.__init__('first_name') self.last_name = 'last_name'where
ClassNameisSmithorBlowFrom the class definition of Person, this happens when an instance (a copy) of the
Personclass is madesrc.person.Person(first_name, last_name=last_name) Person.__init__(first_name, last_name=last_name) self.first_name = first_name self.last_name = last_name
it will use the default value for
last_nameif no value is given because a function uses the default value for the parameter because it is called without the parameter.I add a git commit message in the other terminal
git commit -am 'add test_classes_w_one_parent'
test_classes_w_multiple_parents
Can a class have more than one parent? How are the attributes set if they have more than one parent (super class)?
RED: make it fail
I go back to the terminal where the tests are running
I add a test with an assertion for
jane48 smith = src.person.Person('john', 'smith') 49 self.assertEqual(smith.last_name, john.last_name) 50 51 def test_classes_w_multiple_parents(self): 52 jane = src.family_ties.Jane() 53 self.assertEqual(jane.first_name, 'jane') 54 55 56# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.family_ties' has no attribute 'Jane'
GREEN: make it pass
I add a class definition for
Janetofamily_ties.py16class Smith(src.person.Person): 17 18 def __init__(self, first_name): 19 self.last_name = 'smith' 20 21 22class Jane(src.person.Person): passTypeError: Person.__init__() missing 1 required positional argument: 'first_name'because this happens when
jane = src.family_ties.Jane()runsjane = src.family_ties.Jane() Jane # has no __init__ # call the parent of Jane (Person) Person.__init__()which raises TypeError since the __init__ method of
Personrequires one positional argument (first_name) and it got called with zeroI add the __init__ method to the definition of
Jane22# class Jane(src.person.Person): pass 23class Jane(src.person.Person): 24 25 def __init__(self): 26 return Nonethe terminal is my friend, and shows AttributeError
AttributeError: 'Jane' object has no attribute 'first_name'I add a value for
first_nameto the definition22# class Jane(src.person.Person): pass 23class Jane(src.person.Person): 24 25 def __init__(self): 26 self.first_name = 'jane' 27 return None
the test passes.
REFACTOR: make it better
I add an assertion for the value of the
last_nameattribute ofjaneto test_classes_w_multiple_parents intest_family_ties.py51 def test_classes_w_multiple_parents(self): 52 jane = src.family_ties.Jane() 53 self.assertEqual(jane.first_name, 'jane') 54 self.assertEqual(jane.last_name, 'doe') 55 56 57# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: 'Jane' object has no attribute 'last_name'. Did you mean: 'first_name'?I add a value for
last_nametoJaneinfamily_ties.py22# class Jane(src.person.Person): pass 23class Jane(src.person.Person): 24 25 def __init__(self): 26 self.first_name = 'jane' 27 self.last_name = 'doe' 28 return Nonethe test passes. This is a repetition because
the default value for
PersonisdoeJaneis a child (subclass) ofPerson
I add an assertion to test_classes_w_multiple_parents to make sure
Janeis aDoe, intest_family_ties.py51 def test_classes_w_multiple_parents(self): 52 jane = src.family_ties.Jane() 53 self.assertEqual(jane.first_name, 'jane') 54 self.assertEqual(jane.last_name, 'doe') 55 self.assertIsSubclass( 56 src.family_ties.Jane, src.family_ties.Doe 57 ) 58 59 60# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'src.family_ties.Jane'> is not a subclass of <class 'src.family_ties.Doe'>I change the parent of
Janeinfamily_ties.py22# class Jane(src.person.Person): pass 23# class Jane(src.person.Person): 24class Jane(Doe): 25 26 def __init__(self): 27 self.first_name = 'jane' 28 self.last_name = 'doe' 29 return Nonethe test passes.
I add a call to the super built-in function to use to remove the repetition of
last_name22# class Jane(src.person.Person): pass 23# class Jane(src.person.Person): 24class Jane(Doe): 25 26 def __init__(self): 27 super().__init__() 28 # self.first_name = 'jane' 29 # self.last_name = 'doe' 30 return NoneTypeError: Doe.__init__() missing 1 required positional argument: 'first_name'because this happens when
jane = src.family_ties.Jane()runsjane = src.family_ties.Jane() Jane.__init__() super().__init__() Doe.__init__()which raises TypeError since the __init__ method of
Doerequires two positional arguments (selfandfirst_name) and it got called with one (self)I add
janeas the value forfirst_namein the call to the parent22# class Jane(src.person.Person): pass 23# class Jane(src.person.Person): 24class Jane(Doe): 25 26 def __init__(self): 27 # super().__init__() 28 super().__init__('jane') 29 # self.first_name = 'jane' 30 # self.last_name = 'doe' 31 return Nonethe test is green again because this happens when
jane = src.family_ties.Jane()runsjane = src.family_ties.Jane() Jane.__init__() super().__init__('jane') Doe.__init__('jane') super().__init__(first_name) Person.__init__('jane') Person.__init__('jane', last_name='doe') self.first_name = 'jane' self.last_name = 'doe' # use the default valuea method uses the default value for the parameter because it is called without the parameter.
I add an assertion for
mary, another instance ofJaneto test_classes_w_multiple_parents intest_family_ties.py51 def test_classes_w_multiple_parents(self): 52 jane = src.family_ties.Jane() 53 self.assertEqual(jane.first_name, 'jane') 54 self.assertEqual(jane.last_name, 'doe') 55 self.assertIsSubclass( 56 src.family_ties.Jane, src.family_ties.Doe 57 ) 58 59 mary = src.family_ties.Jane('mary') 60 self.assertEqual(mary.first_name, 'mary') 61 62 63# Exceptions seenthe terminal is my friend, and shows TypeError
TypeError: Jane.__init__() takes 1 positional argument but 2 were givenbecause this happens when
mary = src.family_ties.Jane('mary')runsmary = src.family_ties.Jane('mary') Jane.__init__('mary')which raises TypeError since the __init__ method takes one positional argument (
self) and it was called with two (selfand'mary')I add
first_nameto the parentheses for the __init__ method ofJaneinfamily_ties.py22# class Jane(src.person.Person): pass 23# class Jane(src.person.Person): 24class Jane(Doe): 25 26 # def __init__(self): 27 def __init__(self, first_name): 28 # super().__init__() 29 super().__init__('jane') 30 # self.first_name = 'jane' 31 # self.last_name = 'doe' 32 return Nonethe terminal is my friend, and shows TypeError
TypeError: Jane.__init__() missing 1 required positional argument: 'first_name'I broke the assertion for
janebecause this happens whenjane = src.family_ties.Jane()runsjane = src.family_ties.Jane() Jane.__init__()which raises TypeError since the __init__ method takes two required positional arguments (
selfandfirst_name) and the call only sends one (self).I add a default value to make
first_nameoptional22# class Jane(src.person.Person): pass 23# class Jane(src.person.Person): 24class Jane(Doe): 25 26 # def __init__(self): 27 # def __init__(self, first_name): 28 def __init__(self, first_name='jane'): 29 # super().__init__() 30 super().__init__('jane') 31 # self.first_name = 'jane' 32 # self.last_name = 'doe' 33 return Nonethe terminal is my friend, and shows AssertionError
AssertionError: 'jane' != 'mary'because this happens when
mary = src.family_ties.Jane('mary')runsmary = src.family_ties.Jane('mary') Jane.__init__('mary') super().__init__('jane') Doe.__init__('jane') super().__init__(first_name) Person.__init__('jane') Person.__init__('jane', last_name='doe') self.first_name = 'jane' self.last_name = 'doe'The parent of
Jane (Doe)gets called with a different value for thefirst_nameparameter.I change the call to the super built-in function to use the name instead of a fixed value
22# class Jane(src.person.Person): pass 23# class Jane(src.person.Person): 24class Jane(Doe): 25 26 # def __init__(self): 27 # def __init__(self, first_name): 28 def __init__(self, first_name='jane'): 29 # super().__init__() 30 # super().__init__('jane') 31 super().__init__(first_name) 32 # self.first_name = 'jane' 33 # self.last_name = 'doe' 34 returnthe test passes.
I remove the commented lines and
return None16class Smith(src.person.Person): 17 18 def __init__(self, first_name): 19 self.last_name = 'smith' 20 21 22class Jane(Doe): 23 24 def __init__(self, first_name='jane'): 25 super().__init__(first_name)I add an assertion that will fail, for the last name of
maryin test_classes_w_multiple_parents intest_family_ties.py59 mary = src.family_ties.Jane('mary') 60 self.assertEqual(mary.first_name, 'mary') 61 self.assertEqual(mary.last_name, mary.first_name) 62 63 64# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'doe' != 'mary'I change the expectation to match reality
59 mary = src.family_ties.Jane('mary') 60 self.assertEqual(mary.first_name, 'mary') 61 # self.assertEqual(mary.last_name, mary.first_name) 62 self.assertEqual(mary.last_name, jane.last_name) 63 64 65# Exceptions seenthe test passes because
maryandjaneare instances ofJane
I add an assertion for
joe51 def test_classes_w_multiple_parents(self): 52 joe = src.family_ties.Joe() 53 self.assertEqual(joe.first_name, 'joe') 54 55 jane = src.family_ties.Jane() 56 self.assertEqual(jane.first_name, 'jane') 57 self.assertEqual(jane.last_name, 'doe') 58 self.assertIsSubclass( 59 src.family_ties.Jane, src.family_ties.Doe 60 ) 61 62 mary = src.family_ties.Jane('mary') 63 self.assertEqual(mary.first_name, 'mary') 64 # self.assertEqual(mary.last_name, mary.first_name) 65 self.assertEqual(mary.last_name, jane.last_name) 66 67 68# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.family_ties' has no attribute 'Joe'. Did you mean: 'Doe'?I add a class definition for the
Joeclass tofamily_ties.py22class Jane(Doe): 23 24 def __init__(self, first_name='jane'): 25 super().__init__(first_name) 26 27 28class Joe(src.person.Person): passthe terminal is my friend, and shows TypeError
TypeError: Person.__init__() missing 1 required positional argument: 'first_name'because this happens when
joe = src.family_ties.Joe()runsjoe = src.family_ties.Joe() Person.__init__()which raises TypeError since the __init__ method takes two required positional arguments (
selfandfirst_name) and it was called with one (self)selfis the instance of the class
I add the __init__ method to
Joe28# class Joe(src.person.Person): pass 29class Joe(src.person.Person): 30 31 def __init__(self): 32 return Nonethe terminal is my friend, and shows AttributeError
AttributeError: 'Joe' object has no attribute 'first_name'I add
self.first_nametoJoewith a value28# class Joe(src.person.Person): pass 29class Joe(src.person.Person): 30 31 def __init__(self): 32 self.first_name = 'joe' 33 return Nonethe test passes.
I add an assertion to test_classes_w_multiple_parents to make sure that
joeis aBlow, intest_family_ties.py51 def test_classes_w_multiple_parents(self): 52 joe = src.family_ties.Joe() 53 self.assertEqual(joe.first_name, 'joe') 54 self.assertEqual(joe.last_name, 'blow')the terminal is my friend, and shows AttributeError
AttributeError: 'Joe' object has no attribute 'last_name'. Did you mean: 'first_name'?I add
last_nameto the __init__ method ofJoeinfamily_ties.py28# class Joe(src.person.Person): pass 29class Joe(src.person.Person): 30 31 def __init__(self): 32 self.first_name = 'joe' 33 self.last_name = 'blow' 34 return Nonethe test passes. I cheated, which means I need a better test.
I add assertIsSubclass to test_classes_w_multiple_parents to make sure
Joeis a child (subclass) ofBlow, intest_family_ties.py51 def test_classes_w_multiple_parents(self): 52 joe = src.family_ties.Joe() 53 self.assertEqual(joe.first_name, 'joe') 54 self.assertEqual(joe.last_name, 'blow') 55 self.assertIsSubclass( 56 src.family_ties.Joe, src.family_ties.Blow 57 )the terminal is my friend, and shows AssertionError
AssertionError: <class 'src.family_ties.Joe'> is not a subclass of <class 'src.family_ties.Blow'>I change the parent of
JoetoBlowinfamily_ties.py28# class Joe(src.person.Person): pass 29# class Joe(src.person.Person): 30class Joe(Blow): 31 32 def __init__(self): 33 self.first_name = 'joe' 34 self.last_name = 'blow' 35 return Nonethe test passes.
I no longer need
self.last_name = 'blow'because it is a repetition. I add a call to the super built-in function28# class Joe(src.person.Person): pass 29# class Joe(src.person.Person): 30class Joe(Blow): 31 32 def __init__(self): 33 super().__init__('joe') 34 # self.first_name = 'joe' 35 # self.last_name = 'blow' 36 return Nonethe terminal is my friend, and shows AttributeError
AttributeError: 'Joe' object has no attribute 'first_name'. Did you mean: 'last_name'?because this happens when
joe = src.family_ties.Joe()runsjoe = src.family_ties.Joe() Joe.__init__() super().__init__('joe') Blow.__init__('joe') self.last_name = 'blow'there is no assignment of a value to the
first_nameattribute inBlow.I add
self.first_nametoBlow10class Blow(src.person.Person): 11 12 def __init__(self, first_name): 13 self.first_name = first_name 14 self.last_name = 'blow'the test passes because this happens when
joe = src.family_ties.Joe()runsjoe = src.family_ties.Joe() Joe.__init__() super().__init__('joe') Blow.__init__('joe') self.first_name = 'joe' self.last_name = 'blow'I remove the commented lines and
return None, fromJoe23class Jane(Doe): 24 25 def __init__(self, first_name='jane'): 26 super().__init__(first_name) 27 28 29class Joe(Blow): 30 31 def __init__(self): 32 super().__init__('joe')
I change
maryto be an instance ofMary, a child (subclass) ofJane66 # mary = src.family_ties.Jane('mary') 67 mary = src.family_ties.Mary() 68 self.assertEqual(mary.first_name, 'mary') 69 # self.assertEqual(mary.last_name, mary.first_name) 70 self.assertEqual(mary.last_name, jane.last_name) 71 72 73# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.family_ties' has no attribute 'Mary'I add a class definition for
Marytofamily_ties.py29class Joe(Blow): 30 31 def __init__(self): 32 super().__init__('joe') 33 34 35class Mary(Jane): passthe terminal is my friend, and shows AssertionError
AssertionError: 'jane' != 'mary'because this happens when
mary = src.family_ties.Mary()runsmary = src.family_ties.Mary() Mary # has no __init__ # call the parent of Mary (Jane) Jane.__init__() # use the default value Jane.__init__(first_name='jane') super().__init__(first_name) Doe.__init__('jane') super().__init__(first_name) Person.__init__('jane') Person.__init__('jane', last_name='doe') self.first_name = 'jane' self.last_name = 'doe' # use the default valueI add the __init__ method to
Mary35# class Mary(Jane): pass 36class Mary(Jane): 37 38 def __init__(self): 39 self.first_name = 'mary'the terminal shows AttributeError
AttributeError: 'Mary' object has no attribute 'last_name'. Did you mean: 'first_name'?because this happens when
mary = src.family_ties.Mary()runsmary = src.family_ties.Mary() Mary.__init__() self.first_name = 'mary'I add a value for
last_name44# class Mary(Jane): pass 45class Mary(Jane): 46 47 def __init__(self): 48 self.first_name = 'mary' 49 self.last_name = 'doe'the test passes. This is a repetition because
Maryis aJaneJaneis aDoeDoeis aPersonthe default value for
last_nameinPersonis'doe'
I add a call to the super built-in function to remove the repetition
44# class Mary(Jane): pass 45class Mary(Jane): 46 47 def __init__(self): 48 super().__init__('mary') 49 # self.first_name = 'mary' 50 # self.last_name = 'doe'the test is still green because this happens when
mary = src.family_ties.Mary()runsmary = src.family_ties.Mary() Mary.__init__() super().__init__('mary') Jane.__init__('mary') super().__init__(first_name) Doe.__init__('mary') super().__init__(first_name) Person.__init__('mary') Person.__init__('mary', last_name='doe') self.first_name = 'mary' self.last_name = 'doe' # use the default valueI add a call to the assertNotIsSubclass method to test_classes_w_multiple_parents in
test_family_ties.py66 # mary = src.family_ties.Jane('mary') 67 mary = src.family_ties.Mary() 68 self.assertEqual(mary.first_name, 'mary') 69 # self.assertEqual(mary.last_name, mary.first_name) 70 self.assertEqual(mary.last_name, jane.last_name) 71 self.assertNotIsSubclass( 72 src.family_ties.Mary, src.family_ties.Jane 73 ) 74 75 76# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'src.family_ties.Mary'> is a subclass of <class 'src.family_ties.Jane'>I change assertNotIsSubclass to the assertIsSubclass method
66 # mary = src.family_ties.Jane('mary') 67 mary = src.family_ties.Mary() 68 self.assertEqual(mary.first_name, 'mary') 69 # self.assertEqual(mary.last_name, mary.first_name) 70 self.assertEqual(mary.last_name, jane.last_name) 71 # self.assertNotIsSubclass( 72 self.assertIsSubclass( 73 src.family_ties.Mary, src.family_ties.Jane 74 ) 75 76 77# Exceptions seenthe test passes.
what happens when a child has more than one parent?
I add an assertion to test if I can make
JoeandJaneboth be parents ofMary?66 # mary = src.family_ties.Jane('mary') 67 mary = src.family_ties.Mary() 68 self.assertEqual(mary.first_name, 'mary') 69 # self.assertEqual(mary.last_name, mary.first_name) 70 self.assertEqual(mary.last_name, jane.last_name) 71 # self.assertNotIsSubclass( 72 self.assertIsSubclass( 73 src.family_ties.Mary, src.family_ties.Jane 74 ) 75 self.assertIsSubclass( 76 src.family_ties.Mary, src.family_ties.Joe 77 ) 78 79 80# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'src.family_ties.Mary'> is not a subclass of <class 'src.family_ties.Joe'>because
Maryis not a child (subclass) ofJoe.I add
Joeas a parent ofMaryinfamily_ties.py44# class Mary(Jane): pass 45# class Mary(Jane): 46class Mary(Jane, Joe): 47 48 def __init__(self): 49 super().__init__('mary') 50 # self.first_name = 'mary' 51 # self.last_name = 'doe'the terminal is my friend, and shows TypeError
TypeError: Joe.__init__() takes 1 positional argument but 2 werebecause this happens when
mary = src.family_ties.Mary()runsmary = src.family_ties.Mary() Mary.__init__() super().__init__('mary') Jane.__init__('mary') super().__init__(first_name) Doe.__init__('mary') super().__init__(first_name) # call the next parent of Mary Joe.__init__('mary')which raises TypeError since the __init__ method of
Joeonly takes one positional argument (self) and it got called with two (selfandmary)selfis the instance of the class.
I change the __init__ method of
Joeto take afirst_nameargument29class Joe(Blow): 30 31 # def __init__(self): 32 def __init__(self, first_name): 33 super().__init__('joe')the terminal is my friend, and shows TypeError
TypeError: Joe.__init__() missing 1 required positional argument: 'first_name'I broke the
joe = src.family_ties.Joe()call because the __init__ method now has two required positional arguments (selfandfirst_name) and it was called with one (self)I add a default value to make
first_nameoptional44class Joe(Blow): 45 46 # def __init__(self): 47 # def __init__(self, first_name): 48 def __init__(self, first_name='joe'): 49 super().__init__('joe')the terminal is my friend, and shows AssertionError
AssertionError: 'joe' != 'mary'for
mary.first_namebecause this happens whenmary = src.family_ties.Mary()runsmary = src.family_ties.Mary() Mary.__init__() super().__init__('mary') Jane.__init__('mary') super().__init__(first_name) Doe.__init__('mary') super().__init__(first_name) Joe.__init__('mary') super().__init__('joe') # the problem Blow.__init__('joe') self.first_name = 'joe' self.last_name = 'blow'I use the parameter name in the call to
superinstead of a fixed value inJoe29 class Joe(Blow): 30 31 # def __init__(self): 32 # def __init__(self, first_name): 33 def __init__(self, first_name='joe'): 34 # super().__init__('joe') 35 super().__init__(first_name)the terminal shows AssertionError
AssertionError: 'blow' != 'doe'I change the expectation of the assertion in test_classes_w_multiple_parents for the last name of
maryintest_family_ties.py66 # mary = src.family_ties.Jane('mary') 67 mary = src.family_ties.Mary() 68 self.assertEqual(mary.first_name, 'mary') 69 # self.assertEqual(mary.last_name, mary.first_name) 70 # self.assertEqual(mary.last_name, jane.last_name) 71 self.assertEqual(mary.last_name, joe.last_name) 72 # self.assertNotIsSubclass( 73 self.assertIsSubclass( 74 src.family_ties.Mary, src.family_ties.Jane 75 ) 76 self.assertIsSubclass( 77 src.family_ties.Mary, src.family_ties.Joe 78 ) 79 80 81# Exceptions seenthe test passes.
I change the order of the parents of
Maryto see what it does to the value oflast_name, infamily_ties.py47# class Mary(Jane): pass 48# class Mary(Jane): 49# class Mary(Jane, Joe): 50class Mary(Joe, Jane): 51 52 def __init__(self): 53 super().__init__('mary') 54 # self.first_name = 'mary' 55 # self.last_name = 'doe'the test is still green because this happens when
mary = src.family_ties.Mary()runsmary = src.family_ties.Mary() Mary.__init__() super().__init__('mary') Joe.__init__('mary') super().__init__(first_name) Blow.__init__('mary') self.first_name = 'mary' self.last_name = 'blow'the __init__ method of
Janedid not get called even though it is a parent ofMaryI add an assertion to show this in test_classes_w_multiple_parents in
test_family_ties.py59 jane = src.family_ties.Jane() 60 self.assertEqual(jane.first_name, 'jane') 61 self.assertEqual(jane.last_name, 'doe') 62 self.assertEqual(jane.eye_color, 'green') 63 self.assertIsSubclass( 64 src.family_ties.Jane, src.family_ties.Doe 65 ) 66 67 # mary = src.family_ties.Jane('mary')the terminal is my friend, and shows AssertionError
AttributeError: 'Jane' object has no attribute 'eye_color'I add a class attribute to
Janeinfamily_ties.py23class Jane(Doe): 24 25 def __init__(self, first_name='jane'): 26 super().__init__(first_name) 27 self.eye_color = 'green'the test passes.
I add an assertion for the
eye_colorattribute ofMaryin test_classes_w_multiple_parents intest_family_ties.py67 # mary = src.family_ties.Jane('mary') 68 mary = src.family_ties.Mary() 69 self.assertEqual(mary.first_name, 'mary') 70 # self.assertEqual(mary.last_name, mary.first_name) 71 # self.assertEqual(mary.last_name, jane.last_name) 72 self.assertEqual(mary.last_name, joe.last_name) 73 self.assertEqual(mary.eye_color, jane.eye_color) 74 # self.assertNotIsSubclass( 75 self.assertIsSubclass( 76 src.family_ties.Mary, src.family_ties.Jane 77 ) 78 self.assertIsSubclass( 79 src.family_ties.Mary, src.family_ties.Joe 80 ) 81 82 83# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: 'Mary' object has no attribute 'eye_color'because the __init__ method of
Janedid not get called.I change the order of the parents of
Maryfrom(Joe, Jane)back to(Jane, Joe)infamily_ties.py39# class Mary(Jane): pass 40# class Mary(Jane): 41class Mary(Jane, Joe): 42# class Mary(Joe, Jane): 43 44 def __init__(self): 45 super().__init__('mary') 46 # self.first_name = 'mary' 47 # self.last_name = 'doe'the test passes because this happens when
mary = src.family_ties.Mary()runsmary = src.family_ties.Mary() Mary.__init__() super().__init__('mary') Jane.__init__('mary') super().__init__(first_name) self.eye_color = 'green' Doe.__init__('mary') super().__init__(first_name) Joe.__init__('mary') super().__init__('joe') Blow.__init__('mary') self.first_name = 'mary' self.last_name = 'blow'The order of the parents matters.
If the order is
(Jane, Joe)then instances ofMaryget theeye_colorattribute ofJane.If the order is
(Joe, Jane)then instances ofMarydo NOT get theeye_colorattribute since the __init__ method ofJanedoes not get called.
I change the order of the parents to
(Joe, Jane)again39# class Mary(Jane): pass 40# class Mary(Jane): 41# class Mary(Jane, Joe): 42class Mary(Joe, Jane): 43 44 def __init__(self): 45 super().__init__('mary') 46 # self.first_name = 'mary' 47 # self.last_name = 'doe'the terminal is my friend, and shows AttributeError
AttributeError: 'Mary' object has no attribute 'eye_color'I add the
eye_colorclass attribute toJoe30class Joe(Blow): 31 32 # def __init__(self): 33 # def __init__(self, first_name): 34 def __init__(self, first_name='joe'): 35 # super().__init__('joe') 36 super().__init__(first_name) 37 self.eye_color = 'blue'the terminal is my friend, and shows AssertionError
AssertionError: 'blue' != 'green'I change the expectation of the assertion for
mary.eye_colorin test_classes_w_multiple_parents intest_family_ties.py67 # mary = src.family_ties.Jane('mary') 68 mary = src.family_ties.Mary() 69 self.assertEqual(mary.first_name, 'mary') 70 # self.assertEqual(mary.last_name, mary.first_name) 71 # self.assertEqual(mary.last_name, jane.last_name) 72 self.assertEqual(mary.last_name, joe.last_name) 73 # self.assertEqual(mary.eye_color, jane.eye_color) 74 self.assertEqual(mary.eye_color, joe.eye_color) 75 # self.assertNotIsSubclass( 76 self.assertIsSubclass( 77 src.family_ties.Mary, src.family_ties.Jane 78 ) 79 self.assertIsSubclass( 80 src.family_ties.Mary, src.family_ties.Joe 81 ) 82 83 84# Exceptions seenthe test passes because this happens when
mary = src.family_ties.Mary()runsmary = src.family_ties.Mary() Mary.__init__() super().__init__('mary') Joe.__init__('mary') super().__init__(first_name) self.eye_color = 'blue' Blow.__init__('mary') self.first_name = 'mary' self.last_name = 'blow'The order of the parents matters.
If the order is
(Jane, Joe)then instances ofMaryget theeye_colorattribute ofJane.If the order is
(Joe, Jane)thenthe __init__ method of
Janedoes not get called
I remove the commented lines from
JoeandMaryinfamily_ties.py23class Jane(Doe): 24 25 def __init__(self, first_name='jane'): 26 super().__init__(first_name) 27 self.eye_color = 'green' 28 29 30class Joe(Blow): 31 32 def __init__(self, first_name='joe'): 33 super().__init__(first_name) 34 self.eye_color = 'blue' 35 36 37class Mary(Joe, Jane): 38 39 def __init__(self): 40 super().__init__('mary')
I add
johnto test_classes_w_multiple_parents intest_family_ties.py67 # mary = src.family_ties.Jane('mary') 68 mary = src.family_ties.Mary() 69 self.assertEqual(mary.first_name, 'mary') 70 # self.assertEqual(mary.last_name, mary.first_name) 71 # self.assertEqual(mary.last_name, jane.last_name) 72 self.assertEqual(mary.last_name, joe.last_name) 73 # self.assertEqual(mary.eye_color, jane.eye_color) 74 self.assertEqual(mary.eye_color, joe.eye_color) 75 # self.assertNotIsSubclass( 76 self.assertIsSubclass( 77 src.family_ties.Mary, src.family_ties.Jane 78 ) 79 self.assertIsSubclass( 80 src.family_ties.Mary, src.family_ties.Joe 81 ) 82 83 john = src.family_ties.John() 84 self.assertEqual(john.first_name, 'john') 85 86 87# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.family_ties' has no attribute 'John'I add a class definition for
Johntofamily_ties.py37class Mary(Joe, Jane): 38 39 def __init__(self): 40 super().__init__('mary') 41 42 43class John(src.person.Person): passthe terminal is my friend, and shows TypeError
TypeError: Person.__init__() missing 1 required positional argument: 'first_name'because this happens when
john = src.family_ties.John()runsjohn = src.family_ties.John() Person.__init__()which raises TypeError since the __init__ method of
Persontakes two positional arguments (selfandfirst_name) and it got called with one (self)I add the __init__ method to
Johninfamily_ties.py43# class John(src.person.Person): pass 44class John(src.person.Person): 45 46 def __init__(self): 47 self.first_name = 'john'the test passes.
I add an assertion to make sure that
Johnis a child (subclass) ofSmith83 john = src.family_ties.John() 84 self.assertEqual(john.first_name, 'john') 85 self.assertIsSubclass( 86 src.family_ties.John, src.family_ties.Smith 87 ) 88 89 90# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'src.family_ties.John'> is a subclass of <class 'src.family_ties.Smith'>no cheating this time.
I change the parent of
JohntoSmithinfamily_ties.py43# class John(src.person.Person): pass 44# class John(src.person.Person): 45class John(Smith): 46 47 def __init__(self): 48 self.first_name = 'john'the test passes.
I add an assertion for the
last_nameattribute83 john = src.family_ties.John() 84 self.assertEqual(john.first_name, 'john') 85 self.assertEqual(john.last_name, 'smith') 86 self.assertIsSubclass( 87 src.family_ties.John, src.family_ties.Smith 88 ) 89 90 91# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: 'John' object has no attribute 'last_name'. Did you mean: 'first_name'?I add a class attribute for
last_nametoJohninfamily_ties.py43# class John(src.person.Person): pass 44# class John(src.person.Person): 45class John(Smith): 46 47 def __init__(self): 48 self.first_name = 'john' 49 self.last_name = 'smith'the test passes. This is a repetition because
I add a call to the super built-in function so instances of
Johncan inherit thelast_nameclass attribute43# class John(src.person.Person): pass 44# class John(src.person.Person): 45class John(Smith): 46 47 def __init__(self): 48 super().__init__('john') 49 # self.first_name = 'john' 50 # self.last_name = 'smith'the terminal is my friend, and shows AttributeError
AttributeError: 'John' object has no attribute 'first_name'. Did you mean: 'last_name'?I add the
first_nameattribute toSmith17class Smith(src.person.Person): 18 19 def __init__(self, first_name): 20 self.first_name = first_name 21 self.last_name = 'smith'the test passes because this happens when
john = src.family_ties.John()runsjohn = src.family_ties.John() John.__init__() super().__init__('john') Smith.__init__('john') self.first_name = 'john' self.last_name = 'smith'I remove the commented lines from
John38class Mary(Joe, Jane): 39 40 def __init__(self): 41 super().__init__('mary') 42 43 44class John(Smith): 45 46 def __init__(self): 47 super().__init__('john')
I add
lil, an instance of a child (subclass) ofJohnto test_classes_w_multiple_parents intest_family_ties.py83 john = src.family_ties.John() 84 self.assertEqual(john.first_name, 'john') 85 self.assertEqual(john.last_name, 'smith') 86 self.assertIsSubclass( 87 src.family_ties.John, src.family_ties.Smith 88 ) 89 90 lil = src.family_ties.Lil() 91 self.assertIsSubclass( 92 src.family_ties.Lil, src.family_ties.John 93 ) 94 95 96# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.family_ties' has no attribute 'Lil'I add a class definition for
Liltofamily_ties.py44class John(Smith): 45 46 def __init__(self): 47 super().__init__('john') 48 49 50class Lil(John): passthe test passes.
I add an assertion to test
JohnandMaryas parents ofLil?90 lil = src.family_ties.Lil() 91 self.assertIsSubclass( 92 src.family_ties.Lil, src.family_ties.John 93 ) 94 self.assertIsSubclass( 95 src.family_ties.Lil, src.family_ties.Mary 96 ) 97 98 99# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'src.family_ties.Lil'> is not a subclass of <class 'src.family_ties.Mary'>I add
Maryas a parent toLilinfamily_ties.py50# class Lil(John): pass 51class Lil(John, Mary): passthe test passes.
I add an assertion for the
first_nameattribute oflilintest_family_ties.py90 lil = src.family_ties.Lil() 91 self.assertEqual(lil.first_name, 'lil') 92 self.assertIsSubclass( 93 src.family_ties.Lil, src.family_ties.John 94 ) 95 self.assertIsSubclass( 96 src.family_ties.Lil, src.family_ties.Mary 97 ) 98 99 100# Exceptions seenthe terminal shows AssertionError
AssertionError: 'john' != 'lil'because this happens when
lil = src.family_ties.Lil()runslil = src.family_ties.Lil() Lil # has no __init__ # call the parent of Lil (John) John.__init__() super().__init__('john') Smith.__init__('john') self.first_name = 'john' self.last_name = 'smith'I add the __init__ method with a value for the
first_nameattribute intoLilinfamily_ties.py50# class Lil(John): pass 51# class Lil(John, Mary): pass 52class Lil(John, Mary): 53 54 def __init__(self): 55 self.first_name = 'lil'the test passes.
I add an assertion for the
last_nameattribute oflil, in test_classes_w_multiple_parents intest_family_ties.py90 lil = src.family_ties.Lil() 91 self.assertEqual(lil.first_name, 'lil') 92 self.assertEqual(lil.last_name, john.last_name) 93 self.assertIsSubclass( 94 src.family_ties.Lil, src.family_ties.John 95 ) 96 self.assertIsSubclass( 97 src.family_ties.Lil, src.family_ties.Mary 98 ) 99 100 101# Exceptions seenthe terminal is my friend, and shows AssertionError
AttributeError: 'Lil' object has no attribute 'last_name'. Did you mean: 'first_name'?I add a value for
last_nametoLilinfamily_ties.py50# class Lil(John): pass 51# class Lil(John, Mary): pass 52class Lil(John, Mary): 53 54 def __init__(self): 55 self.first_name = 'lil' 56 self.last_name = 'smith'the test passes. This is a repetition, and a problem if the value of the
last_nameattribute of the parent changes.I add a call to the super built-in function to remove the repetition
50# class Lil(John): pass 51# class Lil(John, Mary): pass 52class Lil(John, Mary): 53 54 def __init__(self): 55 super().__init__('lil') 56 # self.first_name = 'lil' 57 # self.last_name = 'smith'the terminal is my friend, and shows TypeError
TypeError: John.__init__() takes 1 positional argument but 2 were givenbecause this happens when
lil = src.family_ties.Lil()runslil = src.family_ties.Lil() Lil.__init__() super().__init__('lil') John.__init__('lil')which raises TypeError since the __init__ method of
Johntakes one positional argument (self) and it was called with two (selfandlil)I change the __init__ method in
Johnto take in a parameter forfirst_namewith a default value to make it optional44class John(Smith): 45 46 # def __init__(self): 47 def __init__(self, first_name='john'): 48 # super().__init__('john') 49 super().__init__(first_name)the terminal shows AssertionError
AssertionError: 'smith' != 'blow'because this happens when
lil = src.family_ties.Lil()runslil = src.family_ties.Lil() Lil.__init__() super().__init__('lil') John.__init__('lil') super().__init__(first_name) Smith.__init__('lil') super().__init__(first_name) self.first_name = first_name self.last_name = last_namethe __init__ method of
Marydid not get called.I add a call to the super built-in function in
Smith17class Smith(src.person.Person): 18 19 def __init__(self, first_name): 20 super().__init__( 21 first_name=first_name, 22 last_name='smith', 23 ) 24 # self.first_name = first_name 25 # self.last_name = 'smith'the terminal is my friend, and shows TypeError
TypeError: Mary.__init__() got an unexpected keyword argument 'first_name'because this happens when
lil = src.family_ties.Lil()runslil = src.family_ties.Lil() Lil.__init__() super().__init__('lil') John.__init__('lil') super().__init__(first_name) Smith.__init__('lil') super().__init__( first_name=first_name, last_name='smith', ) # call the next parent of Lil Mary.__init__( first_name='lil', last_name='smith' )which raises TypeError since the __init__ method of
Marywas called with a keyword argument and it only takesselfselfis the instance of the class.
I add
first_namewith a default value to the __init__ method ofMary42class Mary(Joe, Jane): 43 44 # def __init__(self): 45 def __init__(self, first_name='mary'): 46 # super().__init__('mary') 47 super().__init__(first_name)the terminal is my friend, and shows TypeError
TypeError: Mary.__init__() got an unexpected keyword argument 'last_name'. Did you mean 'first_name'?I add
last_nameto the __init__ method42class Mary(Joe, Jane): 43 44 # def __init__(self): 45 # def __init__(self, first_name='mary'): 46 def __init__(self, first_name='mary', last_name): 47 # super().__init__('mary') 48 super().__init__(first_name)the terminal shows SyntaxError
SyntaxError: parameter without a default follows parameter with a defaultbecause parameters without default values must come before parameters with default values.
I add a default value for
last_name42class Mary(Joe, Jane): 43 44 # def __init__(self): 45 # def __init__(self, first_name='mary'): 46 # def __init__(self, first_name='mary', last_name): 47 def __init__( 48 self, first_name='mary', 49 last_name=None, 50 ): 51 # super().__init__('mary') 52 super().__init__(first_name)the test passes because this happens when
lil = src.family_ties.Lil()runslil = src.family_ties.Lil() Lil.__init__() super().__init__('lil') John.__init__('lil') super().__init__(first_name) Smith.__init__('lil') super().__init__( first_name=first_name, last_name='smith', ) Mary.__init__('lil', 'smith') super().__init__(first_name) # no last_name passed to Parent Joe.__init__('lil') super().__init__(first_name) self.eye_color = 'blue' Blow.__init__('lil') self.first_name = 'lil' self.last_name = 'blow'the __init__ method of
Janedid not get called.I change the order of the parents of
Lilto(Mary, John)to see if the value will change tojohn.last_name63# class Lil(John): pass 64# class Lil(John, Mary): pass 65# class Lil(John, Mary): 66class Lil(Mary, John): 67 68 def __init__(self): 69 super().__init__('lil') 70 # self.first_name = 'lil' 71 # self.last_name = 'smith'the test is still green because this happens when
lil = src.family_ties.Lil()runslil = src.family_ties.Lil() Lil.__init__() super().__init__('lil') Mary.__init__('lil') Mary.__init__('lil', last_name=None) # use the default value super().__init__(first_name) # no last_name passed to Parent Joe.__init__('lil') super().__init__(first_name) self.eye_color = 'blue' Blow.__init__('lil') self.first_name = 'lil' self.last_name = 'blow'the __init__ method of
Janedid not get called.I add a call to the super built-in function in
Blow10class Blow(src.person.Person): 11 12 def __init__(self, first_name): 13 super().__init__( 14 first_name=first_name, 15 last_name='blow', 16 ) 17 # self.first_name = first_name 18 # self.last_name = 'blow'the terminal is my friend, and shows TypeError
TypeError: Jane.__init__() got an unexpected keyword argument 'last_name'. Did you mean 'first_name'?because this happens when
lil = src.family_ties.Lil()runslil = src.family_ties.Lil() Lil.__init__() super().__init__('lil') Mary.__init__('lil') Mary.__init__('lil', last_name=None) # use the default value super().__init__(first_name) # no last_name passed to Parent Joe.__init__('lil') super().__init__(first_name) self.eye_color = 'blue' Blow.__init__('lil') super().__init__( first_name=first_name, last_name='blow' ) # call the next parent of Mary Jane.__init__('lil', last_name='blow')which raises TypeError since the __init__ method of
Janedoes not have a parameter namedlast_name. Confused?I add
last_nametoJane32class Jane(Doe): 33 34 # def __init__(self, first_name='jane'): 35 def __init__(self, first_name='jane', last_name): 36 super().__init__(first_name) 37 self.eye_color = 'green'the terminal is my friend, and shows SyntaxError
SyntaxError: parameter without a default follows parameter with a defaultbecause parameters without default values must come before parameters with default values.
I give
last_namea default value75# class John(src.person.Person): pass 76# class John(src.person.Person): 77class John(Smith): 78 79 # def __init__(self): 80 # def __init__(self, first_name='john'): 81 # def __init__(self, first_name='john', last_name): 82 def __init__( 83 self, first_name='john', 84 last_name=None, 85 ): 86 # super().__init__('john') 87 super().__init__(first_name) 88 # self.first_name = 'john' 89 # self.last_name = 'smith'the terminal is my friend, and shows AssertionError
AssertionError: 'doe' != 'blow'for the expectation of
mary.last_namebecause this happens whenmary = src.family_ties.Mary()runs, if the parents ofMaryare(Joe, Jane)mary = src.family_ties.Mary() Mary.__init__( first_name='mary', last_name=None, ) super().__init__(first_name) Joe.__init__('mary') super().__init__(first_name) self.eye_color = 'blue' Blow.__init__('mary') super().__init__( first_name=first_name, last_name='blow' ) # call the next parent of Mary Jane.__init__('mary', last_name='blow') super().__init__('mary') self.eye_color = 'green' Doe.__init__('mary') super().__init__('mary') Person.__init__('mary') Person.__init__('mary', last_name='doe') self.first_name = 'mary' self.last_name = 'doe' # use the default valueI change the expectation of the assertion for
mary.last_namein test_classes_w_multiple_parents67 # mary = src.family_ties.Jane('mary') 68 mary = src.family_ties.Mary() 69 self.assertEqual(mary.first_name, 'mary') 70 # self.assertEqual(mary.last_name, mary.first_name) 71 self.assertEqual(mary.last_name, jane.last_name) 72 # self.assertEqual(mary.last_name, joe.last_name) 73 # self.assertEqual(mary.eye_color, jane.eye_color) 74 self.assertEqual(mary.eye_color, joe.eye_color) 75 # self.assertNotIsSubclass( 76 self.assertIsSubclass( 77 src.family_ties.Mary, src.family_ties.Jane 78 ) 79 self.assertIsSubclass( 80 src.family_ties.Mary, src.family_ties.Joe 81 )the test passes because this happens when
lil = src.family_ties.Lil()runslil = src.family_ties.Lil() Lil.__init__() super().__init__('lil') Mary.__init__( first_name='lil', last_name=None, ) super().__init__(first_name) Joe.__init__('lil') super().__init__(first_name) self.eye_color = 'blue' Blow.__init__('lil') super().__init__( first_name=first_name, last_name='blow' ) # call the next parent of Mary Jane.__init__( first_name='lil', last_name='blow', ) super().__init__('lil') # last_name does not get passed to parent self.eye_color = 'green' Doe.__init__('lil') super().__init__('lil') # call the next parent of Lil John.__init__('lil') super().__init__(first_name) Smith.__init__('lil') super().__init__( first_name=first_name, last_name='smith', ) Person.__init__( first_name='lil', last_name='smith', ) self.first_name = 'lil' self.last_name = 'smith'the order of the parents matters.
I remove the commented lines from
family_ties.py10class Blow(src.person.Person): 11 12 def __init__(self, first_name): 13 super().__init__( 14 first_name=first_name, 15 last_name='blow', 16 ) 17 18 19class Smith(src.person.Person): 20 21 def __init__(self, first_name): 22 super().__init__( 23 first_name=first_name, 24 last_name='smith', 25 ) 26 27 28class Jane(Doe): 29 30 def __init__( 31 self, first_name='jane', 32 last_name=None 33 ): 34 super().__init__(first_name) 35 self.eye_color = 'green' 36 37 38class Joe(Blow): 39 40 def __init__(self, first_name='joe'): 41 super().__init__(first_name) 42 self.eye_color = 'blue' 43 44 45class Mary(Joe, Jane): 46 47 def __init__( 48 self, first_name='mary', 49 last_name=None, 50 ): 51 super().__init__(first_name) 52 53 54class John(Smith): 55 56 def __init__(self, first_name='john'): 57 super().__init__(first_name) 58 59 60class Lil(Mary, John): 61 62 def __init__(self): 63 super().__init__('lil')
I add an assertion for
lil.eye_colorto test if instances ofLilinheriteye_colorfromJaneorJoe, in test_classes_w_multiple_parents intest_family_ties.py90 lil = src.family_ties.Lil() 91 self.assertEqual(lil.first_name, 'lil') 92 self.assertEqual(lil.last_name, john.last_name) 93 self.assertEqual(lil.eye_color, jane.eye_color) 94 self.assertIsSubclass( 95 src.family_ties.Lil, src.family_ties.John 96 ) 97 self.assertIsSubclass( 98 src.family_ties.Lil, src.family_ties.Mary 99 ) 100 101 102# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'blue' != 'green'I change the expectation of the assertion
90 lil = src.family_ties.Lil() 91 self.assertEqual(lil.first_name, 'lil') 92 self.assertEqual(lil.last_name, john.last_name) 93 # self.assertEqual(lil.eye_color, jane.eye_color) 94 self.assertEqual(lil.eye_color, mary.eye_color) 95 self.assertIsSubclass( 96 src.family_ties.Lil, src.family_ties.John 97 ) 98 self.assertIsSubclass( 99 src.family_ties.Lil, src.family_ties.Mary 100 ) 101 102 103# Exceptions seen
I add an assertion for
joe.eye_colorthat will fail51 def test_classes_w_multiple_parents(self): 52 joe = src.family_ties.Joe() 53 self.assertEqual(joe.first_name, 'joe') 54 self.assertEqual(joe.last_name, 'blow') 55 self.assertEqual(joe.eye_color, '') 56 self.assertIsSubclass( 57 src.family_ties.Joe, src.family_ties.Blow 58 )the terminal is my friend, and shows AssertionError
AssertionError: 'blue' != ''I change the expectation of the assertion
51 def test_classes_w_multiple_parents(self): 52 joe = src.family_ties.Joe() 53 self.assertEqual(joe.first_name, 'joe') 54 self.assertEqual(joe.last_name, 'blow') 55 # self.assertEqual(joe.eye_color, '') 56 self.assertEqual(joe.eye_color, 'blue') 57 self.assertIsSubclass( 58 src.family_ties.Joe, src.family_ties.Blow 59 )the test passes.
I add an assertion for
john.eye_color85 john = src.family_ties.John() 86 self.assertEqual(john.first_name, 'john') 87 self.assertEqual(john.last_name, 'smith') 88 self.assertEqual(john.eye_color, '') 89 self.assertIsSubclass( 90 src.family_ties.John, src.family_ties.Smith 91 )the terminal is my friend, and shows AttributeError
AttributeError: 'John' object has no attribute 'eye_color'I add the
eye_colorattribute toSmithinfamily_ties.py19class Smith(src.person.Person): 20 21 eye_color = 'brown' 22 23 def __init__(self, first_name): 24 super().__init__( 25 first_name=first_name, 26 last_name='smith', 27 )the terminal is my friend, and shows AssertionError
AssertionError: 'brown' != ''I change the expectation of the assertion for
john.eye_colorin test_classes_w_multiple_parents intest_family_ties.py85 john = src.family_ties.John() 86 self.assertEqual(john.first_name, 'john') 87 self.assertEqual(john.last_name, 'smith') 88 # self.assertEqual(john.eye_color, '') 89 self.assertEqual(john.eye_color, 'brown') 90 self.assertIsSubclass( 91 src.family_ties.John, src.family_ties.Smith 92 )the test passes.
I remove the commented lines
51 def test_classes_w_multiple_parents(self): 52 joe = src.family_ties.Joe() 53 self.assertEqual(joe.first_name, 'joe') 54 self.assertEqual(joe.last_name, 'blow') 55 self.assertEqual(joe.eye_color, 'blue') 56 self.assertIsSubclass( 57 src.family_ties.Joe, src.family_ties.Blow 58 ) 59 60 jane = src.family_ties.Jane() 61 self.assertEqual(jane.first_name, 'jane') 62 self.assertEqual(jane.last_name, 'doe') 63 self.assertEqual(jane.eye_color, 'green') 64 self.assertIsSubclass( 65 src.family_ties.Jane, src.family_ties.Doe 66 ) 67 68 mary = src.family_ties.Mary() 69 self.assertEqual(mary.first_name, 'mary') 70 self.assertEqual(mary.last_name, jane.last_name) 71 self.assertEqual(mary.eye_color, joe.eye_color) 72 self.assertIsSubclass( 73 src.family_ties.Mary, src.family_ties.Jane 74 ) 75 self.assertIsSubclass( 76 src.family_ties.Mary, src.family_ties.Joe 77 ) 78 79 john = src.family_ties.John() 80 self.assertEqual(john.first_name, 'john') 81 self.assertEqual(john.last_name, 'smith') 82 self.assertEqual(john.eye_color, 'brown') 83 self.assertIsSubclass( 84 src.family_ties.John, src.family_ties.Smith 85 ) 86 87 lil = src.family_ties.Lil() 88 self.assertEqual(lil.first_name, 'lil') 89 self.assertEqual(lil.last_name, john.last_name) 90 self.assertEqual(lil.eye_color, mary.eye_color) 91 self.assertIsSubclass( 92 src.family_ties.Lil, src.family_ties.John 93 ) 94 self.assertIsSubclass( 95 src.family_ties.Lil, src.family_ties.Mary 96 ) 97 98 99# Exceptions seen 100# AssertionError 101# NameError 102# AttributeError 103# ModuleNotFoundError 104# TypeErrorI add a git commit message in the other terminal
git commit -am \ 'add test_classes_w_multiple_parents'
Note
All the instances could have been made with only the Person class because there was nothing unique about the classes I made in family_ties.py and it would not have given me the chance to practice making classes with multiple parents and seeing how Python resolves them.
joe = src.family_ties.Joe()
joe = src.person.Person('joe', last_name='blow')
joe.eye_color = 'blue'
jane = src.family_ties.Jane()
jane = src.person.Person('jane')
jane.eye_color = 'green'
mary = src.family_ties.Mary()
mary = src.person.Person('mary', joe.last_name)
mary.eye_color = joe.eye_color
john = src.family_ties.John()
john = src.person.Person('john', 'smith')
john.eye_color = 'brown'
lil = src.family_ties.Lil()
lil = src.person.Person('lil', john.last_name)
lil.eye_color = mary.eye_color
which would have just been Python making these calls to make instances (copies) of the Person class
a_name = src.person.Person(first_name, last_name=last_name)
Person.__init__(first_name, last_name=last_name)
self.first_name = first_name
self.last_name = last_name
a_name.eye_color = color
review
I can make a class with
close the project
I close
test_family_ties.pyandfamily_ties.pyI click in the terminal where the tests are running
I use q on the keyboard to leave the tests. The terminal goes back to the command line.
I change directory to the parent of
personcd ..the terminal shows
.../pumping_pythonI am back in the
pumping_pythondirectory.
code from the chapter
what is next?
I know how to make a Python Test Driven Development environment manually.
how to use class attributes to remove repetition
Would you like to use class attributes with the ‘functions’ project?
rate pumping python
If this has been a 7 star experience for you, please CLICK HERE to leave a 5 star review of pumping python. It helps other people get into the book too.