family ties
In object oriented programming there is a concept called Inheritance, it allows me to define new objects that get their magic powers from other objects.
Making new objects can be easier with Inheritance because I do not have to rewrite things that have already been written, 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.
how to make a class with a parent
To use inheritance I put the “parent” in parentheses when I define the new object (the child) to make the relationship
class Child(Parent):
attribute = SOMETHING
def method():
the body of the method
...
preview
I have these tests by the end of the chapter
1import src.classes
2import unittest
3
4
5class TestClasses(unittest.TestCase):
6
7 def test_making_a_class_w_pass(self):
8 an_instance = src.classes.WPass()
9 assert isinstance(an_instance, object)
10 self.assertIsInstance(an_instance, object)
11
12 def test_making_a_class_w_parentheses(self):
13 an_instance = src.classes.WParentheses()
14 assert isinstance(an_instance, object)
15 self.assertIsInstance(an_instance, object)
16
17 def test_making_a_class_w_object(self):
18 an_instance = src.classes.WObject()
19 assert isinstance(an_instance, object)
20 self.assertIsInstance(an_instance, object)
21
22 def test_is_none_an_object(self):
23 assert isinstance(None, object)
24 self.assertIsInstance(None, object)
25
26 def test_is_a_boolean_an_object(self):
27 assert issubclass(bool, object)
28 self.assertIsSubclass(bool, object)
29
30 def test_is_an_integer_an_object(self):
31 assert issubclass(int, object)
32 self.assertIsSubclass(int, object)
33
34 def test_is_a_float_an_object(self):
35 assert issubclass(float, object)
36 self.assertIsSubclass(float, object)
37
38 def test_is_a_string_an_object(self):
39 assert issubclass(str, object)
40 self.assertIsSubclass(str, object)
41
42 def test_is_a_tuple_an_object(self):
43 assert issubclass(tuple, object)
44 self.assertIsSubclass(tuple, object)
45
46 def test_is_a_list_an_object(self):
47 assert issubclass(list, object)
48 self.assertIsSubclass(list, object)
49
50 def test_is_a_set_an_object(self):
51 assert issubclass(set, object)
52 self.assertIsSubclass(set, object)
53
54 def test_is_a_dictionary_an_object(self):
55 assert issubclass(dict, object)
56 self.assertIsSubclass(dict, object)
57
58 def test_attributes_and_methods_of_objects(self):
59 reality = dir(object)
60 my_expectation = [
61 '__class__',
62 '__delattr__',
63 '__dir__',
64 '__doc__',
65 '__eq__',
66 '__format__',
67 '__ge__',
68 '__getattribute__',
69 '__getstate__',
70 '__gt__',
71 '__hash__',
72 '__init__',
73 '__init_subclass__',
74 '__le__',
75 '__lt__',
76 '__ne__',
77 '__new__',
78 '__reduce__',
79 '__reduce_ex__',
80 '__repr__',
81 '__setattr__',
82 '__sizeof__',
83 '__str__',
84 '__subclasshook__'
85 ]
86 self.assertEqual(reality, my_expectation)
87
88 def test_making_a_class_w_inheritance(self):
89 a_class = src.classes.Doe
90
91 assert not isinstance(a_class, src.person.Person)
92 self.assertNotIsInstance(
93 a_class, src.person.Person
94 )
95
96 assert issubclass(a_class, src.person.Person)
97 self.assertIsSubclass(
98 a_class, src.person.Person
99 )
100
101 assert not isinstance(a_class, a_class)
102 self.assertNotIsInstance(a_class, a_class)
103
104 an_instance = src.classes.Doe('first_name')
105 assert isinstance(
106 an_instance, src.person.Person
107 )
108 self.assertIsInstance(
109 an_instance, src.person.Person
110 )
111
112 self.assertEqual(
113 dir(a_class),
114 dir(src.person.Person)
115 )
116
117 def test_classes_w_one_parent(self):
118 doe = src.classes.Doe('doe')
119 self.assertEqual(doe.last_name, 'doe')
120
121 joe = src.classes.Blow('joe')
122 self.assertEqual(joe.last_name, 'blow')
123
124 blow = src.person.Person('joe', last_name='blow')
125 self.assertEqual(blow.last_name, joe.last_name)
126
127 jane = src.person.Person('jane')
128 self.assertEqual(jane.last_name, doe.last_name)
129
130 john = src.classes.Smith('john')
131 self.assertEqual(john.last_name, 'smith')
132
133 smith = src.person.Person('john', 'smith')
134 self.assertEqual(smith.last_name, john.last_name)
135
136 def test_classes_w_multiple_parents(self):
137 joe = src.classes.Joe()
138 self.assertEqual(joe.first_name, 'joe')
139 self.assertEqual(joe.last_name, 'blow')
140 assert issubclass(
141 src.classes.Joe, src.classes.Blow
142 )
143 # self.assertNotIsSubclass(
144 self.assertIsSubclass(
145 src.classes.Joe, src.classes.Blow
146 )
147
148 jane = src.classes.Jane()
149 self.assertEqual(jane.first_name, 'jane')
150 self.assertEqual(jane.last_name, 'doe')
151 self.assertEqual(jane.eye_color, 'brown')
152 self.assertIsSubclass(
153 src.classes.Jane, src.classes.Doe
154 )
155
156 # mary = src.classes.Jane('mary')
157 mary = src.classes.Mary()
158 self.assertEqual(mary.first_name, 'mary')
159 # self.assertEqual(mary.last_name, mary.first_name)
160 # self.assertEqual(mary.last_name, jane.last_name)
161 self.assertEqual(mary.last_name, joe.last_name)
162 # self.assertEqual(mary.eye_color, jane.eye_color)
163 self.assertEqual(mary.eye_color, 'red')
164 # assert not issubclass(
165 assert issubclass(
166 src.classes.Mary, src.classes.Jane
167 )
168 # self.assertNotIsSubclass(
169 self.assertIsSubclass(
170 src.classes.Mary, src.classes.Jane
171 )
172 assert issubclass(
173 src.classes.Mary, src.classes.Joe
174 )
175 # self.assertNotIsSubclass(
176 self.assertIsSubclass(
177 src.classes.Mary, src.classes.Joe
178 )
179
180 john = src.classes.John()
181 self.assertEqual(john.first_name, 'john')
182 self.assertEqual(john.last_name, 'smith')
183 self.assertEqual(john.eye_color, 'orange')
184 assert issubclass(
185 src.classes.John, src.classes.Smith
186 )
187 # self.assertNotIsSubclass(
188 self.assertIsSubclass(
189 src.classes.John, src.classes.Smith
190 )
191
192 lil = src.classes.Lil()
193 self.assertEqual(lil.first_name, 'lil')
194 self.assertEqual(lil.last_name, mary.last_name)
195 # self.assertEqual(lil.last_name, john.last_name)
196 # self.assertEqual(lil.eye_color, '')
197 # self.assertEqual(lil.eye_color, jane.eye_color)
198 self.assertEqual(lil.eye_color, mary.eye_color)
199 assert issubclass(
200 src.classes.Lil, src.classes.John
201 )
202 # self.assertNotIsSubclass(
203 self.assertIsSubclass(
204 src.classes.Lil, src.classes.John
205 )
206 assert issubclass(
207 src.classes.Lil, src.classes.Mary
208 )
209
210
211# Exceptions seen
212# AssertionError
213# NameError
214# AttributeError
215# ModuleNotFoundError
216# 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_classes.pytouch tests/test_classes.pyI make a new file in the
srcfolder namedclasses.pytouch src/classes.pyI open
test_classes.pyin the editor of the Integrated Development Environment (IDE)Tip
I can open a file from the terminal in the Integrated Development Environment (IDE) with the name of the program and the name of the file. That means if I type this in the terminal
code tests/test_classes.pyVisual Studio Code opens
test_classes.pyin the editorI add the first failing test to
test_functions.py1import unittest 2 3 4class TestClasses(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 ============================== _______________________ TestClasses.test_failure _______________________ self = <tests.test_classes.TestClasses testMethod=test_failure> def test_failure(self): > self.assertFalse(True) E AssertionError: True is not false tests/test_classes.py:7: AssertionError ======================== short test summary info ========================= FAILED tests/test_classes.py::TestClasses::test_failure - AssertionError: True is not false =========================== 1 failed in X.YZs ============================I add AssertionError to the list of Exceptions seen in
test_functions.pyin the editor4class TestFunctions(unittest.TestCase): 5 6 def test_failure(self): 7 self.assertFalse(True) 8 9 10# Exceptions seen 11# AssertionErrorthen I change True to False in the assertion
7 self.assertFalse(False)the test passes.
test_making_a_class_w_pass
To review, I can make a class with the class keyword, use CapWords format for the name and use a name that tells what the group of attributes and methods do.
RED: make it fail
how to test if something is NOT an instance of a class
I can test if an object is an instance (a copy) of another object or NOT with the `isinstance built-in function`_ from The Python Standard Library, it checks if the thing in the parentheses on the left is an instance of the class on the right in the parentheses
I change
test_failureto test_making_a_class_w_pass then add an assertion with isinstance_4class TestClasses(unittest.TestCase): 5 6 def test_making_a_class_w_pass(self): 7 assert not isinstance( 8 src.classes.WPass(), object 9 ) 10 11 12# Exceptions seenthe terminal is my friend, and shows NameError
NameError: name 'src' is not definedbecause
srcis not defined in this fileI add NameError to the list of Exceptions seen
12# Exceptions seen 13# AssertionError 14# NameError
GREEN: make it pass
I add an import statement for the
classesmodule1import src.classes 2import unittest 3 4 5class TestClasses(unittest.TestCase):import src.classesbrings in an object that represents theclasses.pymodule from thesrcfolder so I can use it intest_classes.pythe terminal is my friend, and shows AttributeError
AttributeError: module 'src.classes' has no attribute 'WPass'because there is no definition for
WPassinclasses.py
I add AttributeError to the list of Exceptions seen
13# Exceptions seen 14# AssertionError 15# NameError 16# AttributeErrorI use the Explorer to open
classes.pyfrom thesrcfolder in the editorthen I add a class definition for
WPasstoclasses.py1class WPass: passthe terminal is my friend, and shows AssertionError
AssertionError: assert not Truebecause the statement
not isinstance(src.classes.WPass(), object)is False
how to test if something is an instance of a class
I change the assertion to make the statement True, in
test_classes.py7 def test_making_a_class_w_pass(self): 8 # assert not isinstance( 9 assert isinstance( 10 src.classes.WPass(), object 11 ) 12 13 14# Exceptions seenthe assertion -
assert isinstance(src.classes.WPass(), object)checks if the result of a call toWPassinsrc.classes.pyin thesrcfolder also known assrc.classes.WPass(), is an instance of the object class (the mother of all classes)the class definition simply says pass and the test passes
pass is a special keyword that allows the class definition to follow Python language rules (the class must have a body)
the test passes because all classes inherit from ‘object’
REFACTOR: make it better
The unittest.TestCase class has 2 methods I can also use to test if an object is an instance (a copy) of a class or NOT - assertIsInstance_ and assertNotIsInstance_
another way to test if something is NOT an instance of a class
I add the `assertNotIsInstance method`_ to the test
7 def test_making_a_class_w_pass(self):
8 # assert not isinstance(
9 assert isinstance(
10 src.classes.WPass(), object
11 )
12 self.assertNotIsInstance(
13 src.classes.WPass(), object
14 )
15
16
17# Exceptions seen
the terminal is my friend, and shows AssertionError
AssertionError:
<src.classes.WPass() object at 0xffff8a7b6543>
is an instance of <class 'object'>
another way to test if something is an instance of a class
I change assertNotIsInstance_ to assertIsInstance_
7 def test_making_a_class_w_pass(self): 8 # assert not isinstance( 9 assert isinstance( 10 src.classes.WPass(), object 11 ) 12 # self.assertNotIsInstance( 13 self.assertIsInstance( 14 src.classes.WPass(), object 15 ) 16 17 18# Exceptions seenthe test passes.
I add a variable to use to remove repetition of
src.classes.WPass()7 def test_making_a_class_w_pass(self): 8 an_instance = src.classes.WPass() 9 # assert not isinstance( 10 assert isinstance( 11 src.classes.WPass(), object 12 ) 13 # self.assertNotIsInstance( 14 self.assertIsInstance( 15 src.classes.WPass(), object 16 ) 17 18 19# Exceptions seenI use the variable to remove repetition of
src.classes.WPass()7 def test_making_a_class_w_pass(self): 8 an_instance = src.classes.WPass() 9 # assert not isinstance( 10 assert isinstance(an_instance, object) 11 # src.classes.WPass(), object 12 # ) 13 # self.assertNotIsInstance( 14 self.assertIsInstance(an_instance, object) 15 # src.classes.WPass(), object 16 # ) 17 18 19# Exceptions seenI remove the commented lines
7 def test_making_a_class_w_pass(self): 8 an_instance = src.classes.WPass() 9 assert isinstance(an_instance, object) 10 self.assertIsInstance(an_instance, object) 11 12 13# Exceptions seenI open a new terminal, then add a git commit message
git commit -am \ 'add test_making_a_class_w_pass'
test_making_a_class_w_parentheses
I can also make a class with parentheses/brackets ( ).
RED: make it red
I go back to the terminal that is running the tests
I add another test
7 def test_making_a_class_w_pass(self): 8 an_instance = src.classes.WPass() 9 assert isinstance(an_instance, object) 10 self.assertIsInstance(an_instance, object) 11 12 def test_making_a_class_w_parentheses(self): 13 assert not isinstance( 14 src.classes.WParentheses(), object 15 ) 16 17 18# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.classes' has no attribute 'WParentheses'
GREEN: make it pass
I add a class definition like
WPasstoclasses.py1class WPass: pass 2 3 4class WParentheses: passthe terminal is my friend, and shows AssertionError
AssertionError: assert not Truebecause the statement
not isinstance(src.classes.WParentheses(), object)is FalseI change the assertion to make the statement True
12 def test_making_a_class_w_parentheses(self): 13 # assert not isinstance( 14 assert isinstance( 15 src.classes.WParentheses(), object 16 ) 17 18 19# Exceptions seenthe test passes.
REFACTOR: make it better
I add parentheses to the definition
4# class WParentheses: pass 5class WParentheses(): passthe test is still green because all classes inherit from ‘object’
the assertion -
assert isinstance(src.classes.WParentheses(), object)checks if the result of a call toWParenthesesinsrc.classes.pyin thesrcfolder also known assrc.classes.WParentheses(), is an instance of the object class (the mother of all classes)this class definition has parentheses after the name
the class definition simply says pass and the test passes
pass is a special keyword that allows the class definition to follow Python language rules (the class must have a body)
I remove the commented line
1class WPass: pass 2 3 4class WParentheses(): passI add the `assertNotIsInstance method`_ to test_making_a_class_w_parentheses in
test_classes.py12 def test_making_a_class_w_parentheses(self): 13 # assert not isinstance( 14 assert isinstance( 15 src.classes.WParentheses(), object 16 ) 17 self.assertNotIsInstance( 18 src.classes.WParentheses(), object 19 ) 20 21 22# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <src.classes.WParentheses() object at 0xffffab123456> is an instance of <class 'object'>I change assertNotIsInstance_ to assertIsInstance_
12 def test_making_a_class_w_parentheses(self): 13 # assert not isinstance( 14 assert isinstance( 15 src.classes.WParentheses(), object 16 ) 17 # self.assertNotIsInstance( 18 self.assertIsInstance( 19 src.classes.WParentheses(), object 20 ) 21 22 23# Exceptions seenthe test passes.
I add a variable to use to remove repetition of
src.classes.WParentheses()12 def test_making_a_class_w_parentheses(self): 13 an_instance = src.classes.WParentheses() 14 # assert not isinstance( 15 assert isinstance( 16 src.classes.WParentheses(), object 17 ) 18 # self.assertNotIsInstance( 19 self.assertIsInstance( 20 src.classes.WParentheses(), object 21 ) 22 23 24# Exceptions seenI use the variable to remove repetition of
src.classes.WParentheses()12 def test_making_a_class_w_parentheses(self): 13 an_instance = src.classes.WParentheses() 14 # assert not isinstance( 15 assert isinstance(an_instance, object) 16 # src.classes.WParentheses(), object 17 # ) 18 # self.assertNotIsInstance( 19 self.assertIsInstance(an_instance, object) 20 # src.classes.WParentheses(), object 21 # ) 22 23 24# Exceptions seenI remove the commented lines
12 def test_making_a_class_w_parentheses(self): 13 an_instance = src.classes.WParentheses() 14 assert isinstance(an_instance, object) 15 self.assertIsInstance(an_instance, object) 16 17 18# Exceptions seenI add a git commit message in the other terminal
git commit -am \ 'add test_making_a_class_w_parentheses'
I can make a class with parentheses
I have two classes with different statements, and the tests show that they are both instances of the object class
class WPass: pass
class WParentheses(): pass
because “all classes inherit from ‘object’”, which leads me to the next test.
test_making_a_class_w_object
I can make a class with object (the mother of all classes).
RED: make it fail
I go back to the terminal that is running the tests
I add a test with an assertion for a new class
12 def test_making_a_class_w_parentheses(self): 13 an_instance = src.classes.WParentheses() 14 assert isinstance(an_instance, object) 15 self.assertIsInstance(an_instance, object) 16 17 def test_making_a_class_w_object(self): 18 assert not isinstance( 19 src.classes.WObject(), object 20 ) 21 22 23# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.classes' has no attribute 'WObject'
GREEN: make it pass
I add the class definition to
classes.py4class WParentheses(): pass 5 6 7class WObject(): passthe terminal is my friend, and shows AssertionError
AssertionError: assert not TrueI change the statement of the assertion in test_making_a_class_w_object to make it True
17 def test_making_a_class_w_object(self): 18 # assert not isinstance( 19 assert isinstance( 20 src.classes.WObject(), object 21 ) 22 23 24# Exceptions seenthe test passes.
REFACTOR: make it better
I add object to the parentheses of the class definition for
WObjectinclasses.py7# class WObject(): pass 8class WObject(object): passthe test is still green.
I remove the commented line
4class WParentheses(): pass 5 6 7class WObject(object): passI add an assertion with the `assertNotIsInstance method`_ to test_making_a_class_w_object in
test_classes.py17 def test_making_a_class_w_object(self): 18 # assert not isinstance( 19 assert isinstance( 20 src.classes.WObject(), object 21 ) 22 self.assertNotIsInstance( 23 src.classes.WObject(), object 24 ) 25 26 27# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <src.classes.WObject() object at 0xffffcd781234> is an instance of <class 'object'>I change assertNotIsInstance_ to assertIsInstance_
17 def test_making_a_class_w_object(self): 18 # assert not isinstance( 19 assert isinstance( 20 src.classes.WObject(), object 21 ) 22 # self.assertNotIsInstance( 23 self.assertIsInstance( 24 src.classes.WObject(), object 25 ) 26 27 28# Exceptions seenthe test passes.
I add a variable to remove repetition of
src.classes.WObject()17 def test_making_a_class_w_object(self): 18 an_instance = src.classes.WObject() 19 # assert not isinstance( 20 assert isinstance( 21 src.classes.WObject(), object 22 ) 23 # self.assertNotIsInstance( 24 self.assertIsInstance( 25 src.classes.WObject(), object 26 ) 27 28 29# Exceptions seenI use the variable to remove repetition of
src.classes.WObject()17 def test_making_a_class_w_object(self): 18 an_instance = src.classes.WObject() 19 # assert not isinstance( 20 assert isinstance(an_instance, object) 21 # src.classes.WObject(), object 22 # ) 23 # self.assertNotIsInstance( 24 self.assertIsInstance(an_instance, object) 25 # src.classes.WObject(), object 26 # ) 27 28 29# Exceptions seenthe test is still green.
I remove the commented lines
17 def test_making_a_class_w_object(self): 18 an_instance = src.classes.WObject() 19 assert isinstance(an_instance, object) 20 self.assertIsInstance(an_instance, object) 21 22 23# Exceptions seenI add a git commit message in the other terminal
git commit -am 'add test_making_a_class_w_object'
I have three different classes, and the tests show that they are all instances of the object class
class WPass: pass
class WParentheses(): pass
class WObject(object): pass
their definitions are different, their results are the same because “all classes inherit from ‘object’”
I like to write my classes with (object), so that anyone can see what the parent class is without thinking about it.
test_is_none_an_object
I want to test if None is an object.
RED: make it fail
I go back to the terminal that is running the tests
I add a test with an assertion
17 def test_making_a_class_w_object(self): 18 an_instance = src.classes.WObject() 19 assert isinstance(an_instance, object) 20 self.assertIsInstance(an_instance, object) 21 22 def test_is_none_an_object(self): 23 assert not isinstance(None, object) 24 25 26# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert not True
GREEN: make it pass
I change the statement to make it True
22 def test_is_none_an_object(self):
23 # assert not isinstance(None, object)
24 assert isinstance(None, object)
25
26
27# Exceptions seen
the test passes.
REFACTOR: make it better
I use assertNotIsInstance_ to show that None is a child of object
22 def test_is_none_an_object(self): 23 # assert not isinstance(None, object) 24 assert isinstance(None, object) 25 self.assertNotIsInstance(None, object) 26 27 28# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: None is an instance of <class 'object'>I change assertNotIsInstance_ to assertIsInstance_
22 def test_is_none_an_object(self): 23 # assert not isinstance(None, object) 24 assert isinstance(None, object) 25 # self.assertNotIsInstance(None, object) 26 self.assertIsInstance(None, object) 27 28 29# Exceptions seenthe test passes.
I remove the commented lines
22 def test_is_none_an_object(self): 23 assert isinstance(None, object) 24 self.assertIsInstance(None, object) 25 26 27# Exceptions seenI add a git commit message in the other terminal
git commit -am 'add test_is_none_an_object'
test_is_a_boolean_an_object
I want to test if a boolean is an object.
RED: make it fail
how to test if something is NOT a subclass of a class
I can test if an object is a subclass (child) of another object or NOT with the `issubclass built-in function`_ from The Python Standard Library, it checks if the thing in the parentheses on the left is a subclass of the class on the right in the parentheses
I go back to the terminal that is running the tests
I add a test with an assertion for bool to show that everything in Python is a child of object
22 def test_is_none_an_object(self): 23 assert isinstance(None, object) 24 self.assertIsInstance(None, object) 25 26 def test_is_a_boolean_an_object(self): 27 assert not issubclass(bool, object) 28 29 30# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert not Truebecause bool is a child of object.
GREEN: make it pass
how to test if something is a subclass of a class
I change the statement to make it True
26 def test_is_a_boolean_an_object(self):
27 # assert not issubclass(bool, object)
28 assert issubclass(bool, object)
29
30
31# Exceptions seen
the test passes.
REFACTOR: make it better
The unittest.TestCase class has 2 methods I can also use to test if an object is a subclass (child) of a class or NOT - assertIsSubclass_ and assertNotIsSubclass_
another way to test if something is NOT a subclass of a class
I use `unittest.TestCase.assertNotIsSubclass`_ to show that bool (the class for booleans) is a child of object
26 def test_is_a_boolean_an_object(self):
27 # assert not issubclass(bool, object)
28 assert issubclass(bool, object)
29 self.assertNotIsSubclass(bool, object)
30
31
32# Exceptions seen
the terminal is my friend, and shows AssertionError
AssertionError:
<class 'bool'> is a subclass of <class 'object'>
because bool is a child of object.
another way to test if something is a subclass of a class
I change assertNotIsSubclass_ to assertIsSubclass_
26 def test_is_a_boolean_an_object(self): 27 # assert not issubclass(bool, object) 28 assert issubclass(bool, object) 29 # self.assertNotIsSubclass(bool, object) 30 self.assertIsSubclass(bool, object) 31 32 33# Exceptions seenthe test passes.
I remove the commented lines
26 def test_is_a_boolean_an_object(self): 27 assert issubclass(bool, object) 28 self.assertIsSubclass(bool, object) 29 30 31# Exceptions seenI add a git commit message in the other terminal
git commit -am \ 'add test_is_a_boolean_an_object'
test_is_an_integer_an_object
I want to test if an integer (a whole number without decimals) is an object
RED: make it fail
I go back to the terminal that is running the tests
I add a test with an assertion for int (the class for whole numbers without decimals), to show that everything in Python is a child of object.
26 def test_is_a_boolean_an_object(self): 27 assert issubclass(bool, object) 28 self.assertIsSubclass(bool, object) 29 30 def test_is_an_integer_an_object(self): 31 assert not issubclass(int, object) 32 33 34# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert not Truebecause int is a child of object.
GREEN: make it pass
I change the statement to make it True
30 def test_is_an_integer_an_object(self):
31 # assert not issubclass(int, object)
32 assert issubclass(int, object)
33
34
35# Exceptions seen
the test passes.
REFACTOR: make it better
I use assertNotIsSubclass_ to show that int is a child of object
30 def test_is_an_integer_an_object(self): 31 # assert not issubclass(int, object) 32 assert issubclass(int, object) 33 self.assertNotIsSubclass(int, object) 34 35 36# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'int'> is a subclass of <class 'object'>because int is a child of object.
I change assertNotIsSubclass_ to assertIsSubclass_
43 def test_is_an_integer_an_object(self): 44 # assert not issubclass(int, object) 45 assert issubclass(int, object) 46 # self.assertNotIsSubclass(int, object) 47 self.assertIsSubclass(int, object) 48 49 50# Exceptions seenthe test passes.
I remove the commented lines
30 def test_is_an_integer_an_object(self): 31 assert issubclass(int, object) 32 self.assertIsSubclass(int, object) 33 34 35# Exceptions seenI add a git commit message in the other terminal
git commit -am \ 'add test_is_an_integer_an_object'
test_is_a_float_an_object
I want to test if a float (a binary floating point decimal number) is an object
RED: make it fail
I go back to the terminal that is running the tests
I add a test with an assertion for float (the class for binary floating point decimal numbers), to show that everything in Python is a child of object.
30 def test_is_an_integer_an_object(self): 31 assert issubclass(int, object) 32 self.assertIsSubclass(int, object) 33 34 def test_is_a_float_an_object(self): 35 assert not issubclass(float, object) 36 37 38# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert not Truebecause float is a child of object.
GREEN: make it pass
I change the statement to make it True
34 def test_is_a_float_an_object(self):
35 # assert not issubclass(float, object)
36 assert issubclass(float, object)
37
38
39# Exceptions seen
the test passes.
REFACTOR: make it better
I use assertNotIsSubclass_ to show that float is a child of object
34 def test_is_a_float_an_object(self): 35 # assert not issubclass(float, object) 36 assert issubclass(float, object) 37 self.assertNotIsSubclass(float, object) 38 39 40# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'float'> is a subclass of <class 'object'>because float is a child of object.
I change assertNotIsSubclass_ to assertIsSubclass_
34 def test_is_a_float_an_object(self): 35 # assert not issubclass(float, object) 36 assert issubclass(float, object) 37 # self.assertNotIsSubclass(float, object) 38 self.assertIsSubclass(float, object) 39 40 41# Exceptions seenthe test passes.
I remove the commented lines
34 def test_is_a_float_an_object(self): 35 assert issubclass(float, object) 36 self.assertIsSubclass(float, object) 37 38 39# Exceptions seenI add a git commit message in the other terminal
git commit -am 'add test_is_a_float_an_object'
test_is_a_string_an_object
I want to test if a string (anything in quotes) is an object.
RED: make it fail
I go back to the terminal that is running the tests
I add a test with an assertion for str (the class for anything in quotes), to show that everything in Python is a child of object
34 def test_is_a_float_an_object(self): 35 assert issubclass(float, object) 36 self.assertIsSubclass(float, object) 37 38 def test_is_a_string_an_object(self): 39 assert not issubclass(str, object) 40 41 42# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert not Truebecause str is a child of object.
GREEN: make it pass
I change the statement to make it True
38 def test_is_a_string_an_object(self):
39 # assert not issubclass(str, object)
40 assert issubclass(str, object)
41
42
43# Exceptions seen
the test passes.
REFACTOR: make it better
I use assertNotIsSubclass_ to show that str is a child of object
38 def test_is_a_string_an_object(self): 39 # assert not issubclass(str, object) 40 assert issubclass(str, object) 41 self.assertNotIsSubclass(str, object) 42 43 44# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'str'> is a subclass of <class 'object'>because str is a child of object.
I change assertNotIsInstance_ to assertIsInstance_
38 def test_is_a_string_an_object(self): 39 # assert not issubclass(str, object) 40 assert issubclass(str, object) 41 # self.assertNotIsSubclass(str, object) 42 self.assertIsSubclass(str, object) 43 44 45# Exceptions seenthe test passes.
I remove the commented lines
38 def test_is_a_string_an_object(self): 39 assert issubclass(str, object) 40 self.assertIsSubclass(str, object) 41 42 43# Exceptions seenI add a git commit message in the other terminal
git commit -am 'add test_is_a_string_an_object'
test_is_a_tuple_an_object
I want to test if a tuple (anything in parentheses ( ) separated by a comma) is an object.
RED: make it fail
I go back to the terminal that is running the tests
I add a test with an assertion for tuple (the class for anything in parentheses
( )separated by a comma), to show that everything in Python is a child of object38 def test_is_a_string_an_object(self): 39 assert issubclass(str, object) 40 self.assertIsSubclass(str, object) 41 42 def test_is_a_tuple_an_object(self): 43 assert not issubclass(tuple, object) 44 45 46# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert not Truebecause tuple is a child of object.
GREEN: make it pass
I change the statement to make it True
42 def test_is_a_tuple_an_object(self):
43 # assert not issubclass(tuple, object)
44 assert issubclass(tuple, object)
45
46
47# Exceptions seen
the test passes.
REFACTOR: make it better
I use assertNotIsSubclass_ to show that tuple is a child of object
42 def test_is_a_tuple_an_object(self): 43 # assert not issubclass(tuple, object) 44 assert issubclass(tuple, object) 45 self.assertNotIsSubclass(tuple, object) 46 47 48# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'tuple'> is a subclass of <class 'object'>because tuple is a child of object.
I change assertNotIsSubclass_ to assertIsSubclass_
42 def test_is_a_tuple_an_object(self): 43 # assert not issubclass(tuple, object) 44 assert issubclass(tuple, object) 45 # self.assertNotIsSubclass(tuple, object) 46 self.assertIsSubclass(tuple, object) 47 48 49# Exceptions seenthe test passes.
I remove the commented lines
42 def test_is_a_tuple_an_object(self): 43 assert issubclass(tuple, object) 44 self.assertIsSubclass(tuple, object) 45 46 47# Exceptions seenI add a git commit message in the other terminal
git commit -am 'add test_is_a_tuple_an_object'
test_is_a_list_an_object
I want to test if a list (anything in square brackets [ ]) is an object
RED: make it fail
I go back to the terminal that is running the tests
I add a test with an assertion for list (the class for anything in square brackets ‘[ ]’), to show that everything in Python is a child of object
42 def test_is_a_tuple_an_object(self): 43 assert issubclass(tuple, object) 44 self.assertIsSubclass(tuple, object) 45 46 def test_is_a_list_an_object(self): 47 assert not issubclass(list, object) 48 49 50# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert not Truebecause list is a child of object.
GREEN: make it pass
I change the statement to make it True
46 def test_is_a_list_an_object(self):
47 # assert not issubclass(list, object)
48 assert issubclass(list, object)
49
50
51 # Exceptions seen
the test passes.
REFACTOR: make it better
I use assertNotIsSubclass_ to show that list is a child of object
46 def test_is_a_list_an_object(self): 47 # assert not issubclass(list, object) 48 assert issubclass(list, object) 49 self.assertNotIsSubclass(list, object) 50 51 52# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'list'> is a subclass of <class 'object'>because list is a child of object.
I change assertNotIsSubclass_ to assertIsSubclass_
46 def test_is_a_list_an_object(self): 47 # assert not issubclass(list, object) 48 assert issubclass(list, object) 49 # self.assertNotIsSubclass(list, object) 50 self.assertIsSubclass(list, object) 51 52 53# Exceptions seenthe test passes.
I remove the commented lines
46 def test_is_a_list_an_object(self): 47 assert issubclass(list, object) 48 self.assertIsSubclass(list, object) 49 50 51# Exceptions seenI add a git commit message in the other terminal
git commit -am 'add test_is_a_list_an_object'
test_is_a_set_an_object
I want to test if a set (anything in curly braces { } separated by a comma) is an object.
RED: make it fail
I go back to the terminal that is running the tests
I add a test with an assertion for set (the class for anything in curly braces
{ }separated by a comma), to show that everything in Python is a child of object46 def test_is_a_list_an_object(self): 47 assert issubclass(list, object) 48 self.assertIsSubclass(list, object) 49 50 def test_is_a_set_an_object(self): 51 assert not issubclass(set, object) 52 53 54# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert not Truebecause set is a child of object.
GREEN: make it pass
I change the statement to make it True
50 def test_is_a_set_an_object(self):
51 # assert not issubclass(set, object)
52 assert issubclass(set, object)
53
54
55# Exceptions seen
the test passes.
REFACTOR: make it better
I use assertNotIsSubclass_ to show that set is a child of object
50 def test_is_a_set_an_object(self): 51 # assert not issubclass(set, object) 52 assert issubclass(set, object) 53 self.assertNotIsSubclass(set, object) 54 55 56# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'set'> is a subclass of <class 'object'>because set is a child of object.
I change assertNotIsSubclass_ to assertIsSubclass_
50 def test_is_a_set_an_object(self): 51 # assert not issubclass(set, object) 52 assert issubclass(set, object) 53 # self.assertNotIsSubclass(set, object) 54 self.assertIsSubclass(set, object) 55 56 57# Exceptions seenthe test passes.
I remove the commented lines
50 def test_is_a_set_an_object(self): 51 assert issubclass(set, object) 52 self.assertIsSubclass(set, object) 53 54 55# Exceptions seenI add a git commit message in the other terminal
git commit -am 'add test_is_a_set_an_object'
test_is_a_dictionary_an_object
I want to test if a dictionary (any key-value pairs in curly braces { } separated by a comma) is an object.
RED: make it fail
I go back to the terminal that is running the tests
I add a test with an assertion for dict (the class for any key-value pairs in curly braces ‘{ }’ separated by a comma), to show that everything in Python is a child of object
50 def test_is_a_set_an_object(self): 51 assert issubclass(set, object) 52 self.assertIsSubclass(set, object) 53 54 def test_is_a_dictionary_an_object(self): 55 assert not issubclass(dict, object) 56 57 58# Exceptions seenthe terminal is my friend, and shows AssertionError
E assert not Truebecause dict is a child of object.
I change the statement to make it True
54 def test_is_a_dictionary_an_object(self): 55 # assert not issubclass(dict, object) 56 assert issubclass(dict, object) 57 58 59# Exceptions seenthe test passes.
I use assertNotIsSubclass_ to show that dict is a child of object
54 def test_is_a_dictionary_an_object(self): 55 # assert not issubclass(dict, object) 56 assert issubclass(dict, object) 57 self.assertNotIsSubclass(dict, object) 58 59 60# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'dict'> is a subclass of <class 'object'>because dict is a child of object.
I change assertNotIsSubclass_ to assertIsSubclass_
54 # assert not isinstance(dict, object) 55 assert isinstance(dict, object) 56 # self.assertNotIsInstance(dict, object) 57 self.assertIsInstance(dict, object) 58 59 60# Exceptions seenthe test passes.
I remove the commented lines
54 def test_is_a_dictionary_an_object(self): 55 assert issubclass(dict, object) 56 self.assertIsSubclass(dict, object) 57 58 59# Exceptions seenI add a git commit message in the other terminal
git commit -am \ 'add test_is_a_dictionary_an_object'
test_attributes_and_methods_of_objects
In test_attributes_and_methods_of_person_class I saw the methods I added to the Person class and also names that I did not add, which led to the question of where they came from.
I want to test the attributes and methods of the object class.
RED: make it fail
I go back to the terminal that is running the tests
I add a test to
test_classes.py54 def test_is_a_dictionary_an_object(self): 55 assert issubclass(dict, object) 56 self.assertIsSubclass(dict, object) 57 58 def test_attributes_and_methods_of_objects(self): 59 reality = dir(object) 60 my_expectation = [] 61 self.assertEqual(reality, my_expectation) 62 63 64# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: Lists differ: ['__class__', '__delattr__', '__dir__', '_[272 chars]k__'] != []
GREEN: make it pass
I copy (ctrl/command+c) the values from the terminal and paste (ctrl/command+v) them as
my_expectation58 def test_attributes_and_methods_of_objects(self): 59 reality = dir(object) 60 # my_expectation = [] 61 my_expectation = [ 62 '__class__', '__delattr__', '__dir__', 63 '_[272 chars]k__' 64 ] 65 self.assertEqual(reality, my_expectation) 66 67 68# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: Lists differ: ['__c[32 chars]', '__doc__', '__eq__', '__format__', '__ge__'[231 chars]k__'] != ['__c[32 chars]', '_[272 chars]k__']it shows me the entire list below the message
I copy (ctrl/command+c) the values from the terminal and paste (ctrl/command+v) them as
my_expectation58 def test_attributes_and_methods_of_objects(self): 59 reality = dir(object) 60 # my_expectation = [] 61 # my_expectation = [ 62 # '__class__', '__delattr__', '__dir__', 63 # '_[272 chars]k__' 64 # ] 65 my_expectation = E - ['__class__', 66E - '__delattr__', 67E - '__dir__', 68E - '__doc__', 69E - '__eq__', 70E - '__format__', 71E - '__ge__', 72E - '__getattribute__', 73E - '__getstate__', 74E - '__gt__', 75E - '__hash__', 76E - '__init__', 77E - '__init_subclass__', 78E - '__le__', 79E - '__lt__', 80E - '__ne__', 81E - '__new__', 82E - '__reduce__', 83E - '__reduce_ex__', 84E - '__repr__', 85E - '__setattr__', 86E - '__sizeof__', 87E - '__str__', 88E - '__subclasshook__'] 89 self.assertEqual(reality, my_expectation) 90 91 92# Exceptions seenthe terminal is my friend, and shows NameError
NameError: name 'E' is not definedI use the
find and replacefeature of the Integrated Development Environment (IDE) to remove the extra characters, then remove the commented lines58 def test_attributes_and_methods_of_objects(self): 59 reality = dir(object) 60 my_expectation = [ 61 '__class__', 62 '__delattr__', 63 '__dir__', 64 '__doc__', 65 '__eq__', 66 '__format__', 67 '__ge__', 68 '__getattribute__', 69 '__getstate__', 70 '__gt__', 71 '__hash__', 72 '__init__', 73 '__init_subclass__', 74 '__le__', 75 '__lt__', 76 '__ne__', 77 '__new__', 78 '__reduce__', 79 '__reduce_ex__', 80 '__repr__', 81 '__setattr__', 82 '__sizeof__', 83 '__str__', 84 '__subclasshook__' 85 ] 86 self.assertEqual(reality, my_expectation) 87 88 89# Exceptions seenthe test passes. All classes automatically get these attributes, they inherit them because all classes inherit from ‘object’.
The
__init__method is also inherited which means when I defined it in test_classy_person_says_hello I overwrote the inherited one.I add a git commit message in the other terminal
git commit -am \ 'add test_attributes_and_methods_of_objects'
test_making_a_class_w_inheritance
I can make classes with inheritance by stating the parent class
RED: make it fail
I go back to the terminal that is running the tests
I add a new test
83 '__str__', 84 '__subclasshook__' 85 ] 86 self.assertEqual(reality, my_expectation) 87 88 def test_making_a_class_w_inheritance(self): 89 a_class = src.classes.Doe 90 assert isinstance(a_class, src.person.Person) 91 92 93# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.classes' has no attribute 'Doe'because there is no definition for
Doeinclasses.py
GREEN: make it pass
I add a class definition to
classes.py7class WObject(object): pass 8 9 10class Doe(object): passthe terminal is my friend, and shows AssertionError
AssertionError: assert Falsebecause
I change the assertion in test_making_a_class_w_inheritance in
test_classes.py88 def test_making_a_class_w_inheritance(self): 89 a_class = src.classes.Doe 90 # assert isinstance(a_class, src.person.Person) 91 assert not isinstance(a_class, src.person.Person) 92 93 94# Exceptions seenthe test passes.
Doeis not an instance of thePersonclass.
REFACTOR: make it better
I add a call to the `assertIsInstance method`_
88 def test_making_a_class_w_inheritance(self): 89 a_class = src.classes.Doe 90 # assert isinstance(a_class, src.person.Person) 91 assert not isinstance(a_class, src.person.Person) 92 self.assertIsInstance(a_class, src.person.Person) 93 94 95# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'src.classes.Doe'> is not an instance of <class 'src.person.Person'>I change assertIsInstance_ to assertNotIsInstance_
88 def test_making_a_class_w_inheritance(self): 89 a_class = src.classes.Doe 90 # assert isinstance(a_class, src.person.Person) 91 assert not isinstance(a_class, src.person.Person) 92 # self.assertIsInstance(a_class, src.person.Person) 93 self.assertNotIsInstance( 94 a_class, src.person.Person 95 ) 96 97 98# Exceptions seenthe test passes.
I use the `issubclass built-in function`_ to test if
Doeis a child ofPerson88 def test_making_a_class_w_inheritance(self): 89 a_class = src.classes.Doe 90 # assert isinstance(a_class, src.person.Person) 91 assert not isinstance(a_class, src.person.Person) 92 # self.assertIsInstance(a_class, src.person.Person) 93 self.assertNotIsInstance( 94 a_class, src.person.Person 95 ) 96 assert issubclass(a_class, src.person.Person) 97 98 99# Exceptions seenthe terminal is my friend, and shows AssertionError
E AssertionError: assertbecause
Doeis not a child ofPerson, yet.I change the parent of
DoefromobjecttoPersoninclasses.py10# class Doe(object): pass 11class Doe(person.Person): passthe terminal is my friend, and shows NameError
NameError: name 'person' is not definedbecause there is no definition for
personinclasses.pyI add an import statement at the top of
classes.py1import person 2 3 4class WPass: passthe terminal is my friend, and shows ModuleNotFoundError
E ModuleNotFoundError: No module named 'person'because the test cannot find
person.pyin the main project folder where I run the tests from, so it cannot import the ModuleI add ModuleNotFoundError to the list of Exceptions seen, in
test_classes.py99# Exceptions seen 100# AssertionError 101# NameError 102# AttributeError 103# ModuleNotFoundErrorI change the import statement so the path to
person.pyfrom the main project folder is correct, inclasses.py1# import person 2import src.person 3 4 5class WPass: passthe terminal does not feel like my friend, it goes back to NameError
NameError: name 'person' is not definedI add
src.to the parent ofDoe14# class Doe(object): pass 15# class Doe(person.Person): pass 16class Doe(src.person.Person): passthe test passes because
Doeis now a child (subclass) ofPerson.import src.personbrings in an object that represents theperson.pymodule from thesrcfolder so I can use it inclasses.py.I have to use
src.person.Personinclasses.pybecause I am testing from the root folder of the project.The test needs to know where
person.pyis in relation to where I ran the tests from.This is a problem because if
classes.pyis run from insidesrcthe import statement will not be able to findsrc.personfrom insidesrc. Same thing if I run the tests from insidetests. That is a problem for another time.
I add the `assertNotIsSubclass method`_ to test_making_a_class_w_inheritance in
test_classes.py88 def test_making_a_class_w_inheritance(self): 89 a_class = src.classes.Doe 90 # assert isinstance(a_class, src.person.Person) 91 assert not isinstance(a_class, src.person.Person) 92 # self.assertIsInstance(a_class, src.person.Person) 93 self.assertNotIsInstance( 94 a_class, src.person.Person 95 ) 96 assert issubclass(a_class, src.person.Person) 97 self.assertNotIsSubclass( 98 a_class, src.person.Person 99 ) 100 101 102# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'src.classes.Doe'> is a subclass of <class 'src.person.Person'>I change assertNotIsSubclass_ to assertIsSubclass_
88 def test_making_a_class_w_inheritance(self): 89 a_class = src.classes.Doe 90 # assert isinstance(a_class, src.person.Person) 91 assert not isinstance(a_class, src.person.Person) 92 # self.assertIsInstance(a_class, src.person.Person) 93 self.assertNotIsInstance( 94 a_class, src.person.Person 95 ) 96 assert issubclass(a_class, src.person.Person) 97 # self.assertNotIsSubclass( 98 self.assertIsSubclass( 99 a_class, src.person.Person 100 ) 101 102 103# Exceptions seenthe test passes.
I add an assertion to show that
a_classwhich points toDoeis just a name for the class not an instance88 def test_making_a_class_w_inheritance(self): 89 a_class = src.classes.Doe 90 # assert isinstance(a_class, src.person.Person) 91 assert not isinstance(a_class, src.person.Person) 92 # self.assertIsInstance(a_class, src.person.Person) 93 self.assertNotIsInstance( 94 a_class, src.person.Person 95 ) 96 assert issubclass(a_class, src.person.Person) 97 # self.assertNotIsSubclass( 98 self.assertIsSubclass( 99 a_class, src.person.Person 100 ) 101 assert isinstance(a_class, a_class) 102 103 104# Exceptions seenthe terminal is my friend, and shows AssertionError
E AssertionError: assert FalseI change the assertion
88 def test_making_a_class_w_inheritance(self): 89 a_class = src.classes.Doe 90 # assert isinstance(a_class, src.person.Person) 91 assert not isinstance(a_class, src.person.Person) 92 # self.assertIsInstance(a_class, src.person.Person) 93 self.assertNotIsInstance( 94 a_class, src.person.Person 95 ) 96 assert issubclass(a_class, src.person.Person) 97 # self.assertNotIsSubclass( 98 self.assertIsSubclass( 99 a_class, src.person.Person 100 ) 101 # assert isinstance(a_class, a_class) 102 assert not isinstance(a_class, a_class) 103 104 105# Exceptions seenthe test passes.
I add assertIsInstance_
88 def test_making_a_class_w_inheritance(self): 89 a_class = src.classes.Doe 90 # assert isinstance(a_class, src.person.Person) 91 assert not isinstance(a_class, src.person.Person) 92 # self.assertIsInstance(a_class, src.person.Person) 93 self.assertNotIsInstance( 94 a_class, src.person.Person 95 ) 96 assert issubclass(a_class, src.person.Person) 97 # self.assertNotIsSubclass( 98 self.assertIsSubclass( 99 a_class, src.person.Person 100 ) 101 # assert isinstance(a_class, a_class) 102 assert not isinstance(a_class, a_class) 103 self.assertIsInstance(a_class, a_class) 104 105 106# Exceptions seenthe terminal shows AssertionError
AssertionError: <class 'src.classes.Doe'> is not an instance of <class 'src.classes.Doe'>I change assertIsInstance_ to assertNotIsInstance_
88 def test_making_a_class_w_inheritance(self): 89 a_class = src.classes.Doe 90 # assert isinstance(a_class, src.person.Person) 91 assert not isinstance(a_class, src.person.Person) 92 # self.assertIsInstance(a_class, src.person.Person) 93 self.assertNotIsInstance( 94 a_class, src.person.Person 95 ) 96 assert issubclass(a_class, src.person.Person) 97 # self.assertNotIsSubclass( 98 self.assertIsSubclass( 99 a_class, src.person.Person 100 ) 101 # assert isinstance(a_class, a_class) 102 assert not isinstance(a_class, a_class) 103 # self.assertIsInstance(a_class, a_class) 104 self.assertNotIsInstance(a_class, a_class) 105 106 107# Exceptions seen
what is the difference between an instance and a class?
I add another assertion, this time with an instance of
Doe88 def test_making_a_class_w_inheritance(self): 89 a_class = src.classes.Doe 90 # assert isinstance(a_class, src.person.Person) 91 assert not isinstance(a_class, src.person.Person) 92 # self.assertIsInstance(a_class, src.person.Person) 93 self.assertNotIsInstance( 94 a_class, src.person.Person 95 ) 96 assert issubclass(a_class, src.person.Person) 97 # self.assertNotIsSubclass( 98 self.assertIsSubclass( 99 a_class, src.person.Person 100 ) 101 # assert isinstance(a_class, a_class) 102 assert not isinstance(a_class, a_class) 103 # self.assertIsInstance(a_class, a_class) 104 self.assertNotIsInstance(a_class, a_class) 105 106 an_instance = src.classes.Doe() 107 assert not isinstance( 108 an_instance, src.person.Person 109 ) 110 111 112# Exceptions seenthe terminal is my friend, and shows TypeError
TypeError: Person.__init__() missing 1 required positional argument: 'first_name'because the
__init__method of thePersonclass takes one required argument forfirst_nameand I calledDoeto make an instance. How didPerson.__init__get called?
what happens when the child calls the parent?
Here is what is happens when
an_instance = src.class.Doe()runsan_instance = src.classes.Doe() Doe # has no __init__, call Person Person.__init__()which raises TypeError
I add TypeError to the list of Exceptions seen
112# Exceptions seen 113# AssertionError 114# NameError 115# AttributeError 116# ModuleNotFoundError 117# TypeError
how to call the parent from the child
I add the super built-in function to
Doeto call the parent (Person)__init__method directly, inclasses.py14# class Doe(object): pass 15# class Doe(person.Person): pass 16# class Doe(src.person.Person): pass 17class Doe(src.person.Person): 18 19 def __init__(self): 20 super().__init__()the super built-in function calls the
__init__method of the parent class
I add a value to
src.classes.Doein test_making_a_class_w_inheritance intest_classes.py106 # an_instance = src.classes.Doe() 107 an_instance = src.classes.Doe('first_name') 108 assert not isinstance( 109 an_instance, src.person.Person 110 ) 111 112 113# Exceptions seenthe terminal is my friend, and shows TypeError
TypeError: Doe.__init__() takes 1 positional argument but 2 were givenbecause this happens when
an_instance = src.classes.Doe('first_name')runsan_instance = src.classes.Doe('first_name') Doe.__init__('first_name')which raises TypeError because the definition for the
__init__method inDoeonly takes one positional argument (self) and it was called with two (selfandfirst_name)I add a parameter for
first_nameto the__init__method ofDoeinclasses.py14# class Doe(object): pass 15# class Doe(person.Person): pass 16# class Doe(src.person.Person): pass 17class Doe(src.person.Person): 18 19 # def __init__(self): 20 def __init__(self, first_name): 21 super().__init__()the terminal is my friend, and shows TypeError
TypeError: Person.__init__() missing 1 required positional argument: 'first_name'because this happens when
an_instance = src.classes.Doe('first_name')runsan_instance = src.classes.Doe('first_name') Doe.__init__('first_name') super().__init__() Person.__init__()which raises TypeError
I add the required parameter to
super().__init__()inDoe14# class Doe(object): pass 15# class Doe(person.Person): pass 16# class Doe(src.person.Person): pass 17class Doe(src.person.Person): 18 19 # def __init__(self): 20 def __init__(self, first_name): 21 # super().__init__() 22 super().__init__(first_name)the terminal is my friend, and shows AssertionError
AssertionError: assert not Truebecause
an instance of
Doeis an instance ofPersonPersonis the parent ofDoethe test shows that this happens when
an_instance = src.classes.Doe('first_name')runsan_instance = src.classes.Doe('first_name') Doe.__init__('first_name') super().__init__('first_name') Person.__init__('first_name')
I change the assertion in test_making_a_class_w_inheritance in
test_classes.py106 # an_instance = src.classes.Doe() 107 an_instance = src.classes.Doe('first_name') 108 # assert not isinstance( 109 assert isinstance( 110 an_instance, src.person.Person 111 ) 112 113 114# Exceptions seenthe test passes.
I add a call to the `assertNotIsInstance method`_
106 # an_instance = src.classes.Doe() 107 an_instance = src.classes.Doe('first_name') 108 # assert not isinstance( 109 assert isinstance( 110 an_instance, src.person.Person 111 ) 112 self.assertNotIsInstance( 113 an_instance, src.person.Person 114 ) 115 116 117# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <src.classes.Doe object at 0xffff01a2bc34> is an instance of <class 'src.person.Person'>because an instance of
Doeis an instance ofPersonI change assertNotIsInstance_ to assertIsInstance_
106 # an_instance = src.classes.Doe() 107 an_instance = src.classes.Doe('first_name') 108 # assert not isinstance( 109 assert isinstance( 110 an_instance, src.person.Person 111 ) 112 # self.assertNotIsInstance( 113 self.assertIsInstance( 114 an_instance, src.person.Person 115 ) 116 117 118# Exceptions seenthe test passes.
I add a test for the attributes and methods of the
Doeclass106 # an_instance = src.classes.Doe() 107 an_instance = src.classes.Doe('first_name') 108 # assert not isinstance( 109 assert isinstance( 110 an_instance, src.person.Person 111 ) 112 # self.assertNotIsInstance( 113 self.assertIsInstance( 114 an_instance, src.person.Person 115 ) 116 117 self.assertEqual( 118 dir(a_class), 119 [] 120 ) 121 122 123# 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
Personclass117 self.assertEqual( 118 dir(a_class), 119 # [] 120 dir(src.person.Person) 121 ) 122 123 124# Exceptions seenthe test passes because
Doehas the same attributes and methods asPersonbecauseDoeis a child ofParentI remove the commented lines
88 def test_making_a_class_w_inheritance(self): 89 a_class = src.classes.Doe 90 91 assert not isinstance(a_class, src.person.Person) 92 self.assertNotIsInstance( 93 a_class, src.person.Person 94 ) 95 96 assert issubclass(a_class, src.person.Person) 97 self.assertIsSubclass( 98 a_class, src.person.Person 99 ) 100 101 assert not isinstance(a_class, a_class) 102 self.assertNotIsInstance(a_class, a_class) 103 104 an_instance = src.classes.Doe('first_name') 105 assert isinstance( 106 an_instance, src.person.Person 107 ) 108 self.assertIsInstance( 109 an_instance, src.person.Person 110 ) 111 112 self.assertEqual( 113 dir(a_class), 114 dir(src.person.Person) 115 ) 116 117 118# Exceptions seenI remove the commented lines from
classes.py1import src.person 2 3 4class WPass: pass 5 6 7class WParentheses(): pass 8 9 10class WObject(object): pass 11 12 13class Doe(src.person.Person): 14 15 def __init__(self, first_name): 16 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
RED: make it fail
I go back to the terminal that is running the tests
I add a new test for Inheritance with an assertion
112 self.assertEqual( 113 dir(a_class), 114 dir(src.person.Person) 115 ) 116 117 def test_classes_w_one_parent(self): 118 doe = src.classes.Doe('doe') 119 self.assertEqual(doe.last_name, '') 120 121 122# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'doe' != ''
GREEN: make it pass
I change the expectation
117 def test_classes_w_one_parent(self):
118 doe = src.classes.Doe('doe')
119 # self.assertEqual(doe.last_name, '')
120 self.assertEqual(doe.last_name, 'doe')
121
122
123# Exceptions seen
the test passes because this happens when doe = src.classes.Doe('doe') runs
doe = src.classes.Doe('doe')
Doe.__init__('doe')
super().__init__(first_name)
Person.__init__('first_name')
Person.__init__('first_name', last_name='doe')
self.last_name = 'doe' # 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
117 def test_classes_w_one_parent(self): 118 doe = src.classes.Doe('doe') 119 # self.assertEqual(doe.last_name, '') 120 self.assertEqual(doe.last_name, 'doe') 121 122 joe = src.classes.Doe('joe') 123 self.assertEqual(joe.last_name, 'blow') 124 125 126# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'doe' != 'blow'I add a new class definition to
classes.py13class Doe(src.person.Person): 14 15 def __init__(self, first_name): 16 super().__init__(first_name) 17 18 19class Blow(src.person.Person): passthe terminal still shows AssertionError
I change
joeto use the newBlowclass, in test_classes_w_one_parent intest_classes.py122 # joe = src.classes.Doe('joe') 123 joe = src.classes.Blow('joe') 124 self.assertEqual(joe.last_name, 'blow') 125 126 127# Exceptions seenthe terminal still shows AssertionError
I add a class attribute for
last_namein theBlowclass inclasses.py19# class Blow(src.person.Person): pass 20class Blow(src.person.Person): 21 22 last_name = 'blow'the terminal does not feel like my friend, it still shows AssertionError
I add the
__init__method to customize the last name19# class Blow(src.person.Person): pass 20class Blow(src.person.Person): 21 22 # last_name = 'blow' 23 24 def __init__(self): 25 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.classes.Blow('joe')runsjoe = src.classes.Blow('joe') Blow.__init__('joe')which raises TypeError since the
__init__method o ofBlowonly takes one positional argument (self) and it got called with two (selfandfirst_name)I add
first_nameto the parentheses for the__init__method16# class Blow(src.person.Person): pass 17class Blow(src.person.Person): 18 19 # last_name = 'blow' 20 21 # def __init__(self): 22 def __init__(self, first_name): 23 self.last_name = 'blow'the test passes because this happens when
joe = src.classes.Blow('joe')runsjoe = src.classes.Blow('joe') Blow.__init__('joe') self.last_name = 'joe'I can define classes that are related and have their own defaults. In this test
the
Doeclass has a defaultlast_namethat is the same as the default last name forPersonthe
Blowclass has a different defaultlast_nameDoeandBloware children (subclasses) ofPerson
I remove the commented lines
13class Doe(src.person.Person): 14 15 def __init__(self, first_name): 16 super().__init__(first_name) 17 18 19class Blow(src.person.Person): 20 21 def __init__(self, first_name): 22 self.last_name = 'blow'In this case there is a simpler way to make
joeanddoe. I could directly pass the values to thePersonclass 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_classes.py122 # joe = src.classes.Doe('joe') 123 joe = src.classes.Blow('joe') 124 self.assertEqual(joe.last_name, 'blow') 125 126 blow = src.person.Person('joe') 127 self.assertEqual(blow.last_name, joe.last_name) 128 129 130# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'doe' != 'blow'I add
last_name='blow'to the call126 # blow = src.person.Person('joe') 127 blow = src.person.Person('joe', last_name='blow') 128 self.assertEqual(blow.last_name, joe.last_name) 129 130 131# Exceptions seenthe test passes. I can make instances of classes by customizing its attributes without having to make a new class.
I add an assertion for
jane126 # blow = src.person.Person('joe') 127 blow = src.person.Person('joe', last_name='blow') 128 self.assertEqual(blow.last_name, joe.last_name) 129 130 jane = src.person.Person('jane') 131 self.assertEqual(jane.last_name, blow.last_name) 132 133 134# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'doe' != 'blow'I change the expectation
130 jane = src.person.Person('jane') 131 # self.assertEqual(jane.last_name, blow.last_name) 132 self.assertEqual(jane.last_name, doe.last_name) 133 134 135# Exceptions seenthe test passes.
I add an assertion for
john130 jane = src.person.Person('jane') 131 # self.assertEqual(jane.last_name, blow.last_name) 132 self.assertEqual(jane.last_name, doe.last_name) 133 134 john = src.classes.Smith('john') 135 self.assertEqual(john.last_name, 'smith') 136 137 138# Exceptions seenthe terminal shows AttributeError
AttributeError: module 'src.classes' has no attribute 'Smith'I add a class definition for
Smithtoclasses.py19class Blow(src.person.Person): 20 21 def __init__(self, first_name): 22 self.last_name = 'blow' 23 24 25class Smith(src.person.Person): passthe terminal is my friend, and shows AssertionError
AssertionError: 'doe' != 'smith'because this happens when
john = src.classes.Smith('john')runsjohn = src.classes.Smith('john') Smith # Smith has no __init__, call Person Person.__init__('john') Person.__init__('john', last_name='doe') self.last_name = 'doe' # use the default valueI add the
__init__method inSmith25# class Smith(src.person.Person): pass 26class Smith(src.person.Person): 27 28 def __init__(self): 29 self.last_name = 'smith'TypeError: Smith.__init__() takes 1 positional argument but 2 were givenbecause this happens when
john = src.classes.Smith('john')runsjohn = src.classes.Smith('john') Smith.__init__('john')the definition for the
__init__method only allows one input (self) and it got called with two (selfandfirst_name)I add
first_namein parentheses25# class Smith(src.person.Person): pass 26class Smith(src.person.Person): 27 28 # def __init__(self): 29 def __init__(self, first_name): 30 self.last_name = 'smith'the test passes because this happens when
john = src.classes.Smith('john')runsjohn = src.classes.Smith('john') Smith.__init__('john') self.last_name = 'smith'I remove the commented lines
19class Blow(src.person.Person): 20 21 def __init__(self, first_name): 22 self.last_name = 'blow' 23 24 25class Smith(src.person.Person): 26 27 def __init__(self, first_name): 28 self.last_name = 'smith'the test passes.
I add another assertion to test_classes_w_one_parent in
test_classes.py134 john = src.classes.Smith('john') 135 self.assertEqual(john.last_name, 'smith') 136 137 smith = src.person.Person('john', 'smith') 138 self.assertEqual(smith.last_name, doe.last_name) 139 140 141# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'smith' != 'doe'I change the expectation
137 smith = src.person.Person('john', 'smith') 138 # self.assertEqual(smith.last_name, doe.last_name) 139 self.assertEqual(smith.last_name, john.last_name) 140 141 142# Exceptions seenthe test passes.
I remove the commented lines
112 def test_classes_w_one_parent(self): 113 doe = src.classes.Doe('doe') 114 self.assertEqual(doe.last_name, 'doe') 115 116 joe = src.classes.Blow('joe') 117 self.assertEqual(joe.last_name, 'blow') 118 119 blow = src.person.Person('joe', last_name='blow') 120 self.assertEqual(blow.last_name, joe.last_name) 121 122 jane = src.person.Person('jane') 123 self.assertEqual(jane.last_name, doe.last_name) 124 125 john = src.classes.Smith('john') 126 self.assertEqual(john.last_name, 'smith') 127 128 smith = src.person.Person('john', 'smith') 129 self.assertEqual(smith.last_name, john.last_name) 130 131 132# Exceptions seenthis happens when an instance of
Doeis madeinstance = src.classes.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 valuethis happens when an instance of
SmithandBloware madeinstance = src.classes.ClassName('first_name') ClassName.__init__('first_name') self.last_name = 'last_name'this happens when instances of the
Personclass are madeinstance = 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
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?
RED: make it fail
I go back to the terminal that is running the tests
I add a test with an assertion for
jane133 smith = src.person.Person('john', 'smith') 134 self.assertEqual(smith.last_name, john.last_name) 135 136 def test_classes_w_multiple_parents(self): 137 jane = src.classes.Jane() 138 self.assertEqual(jane.first_name, 'jane') 139 140 141# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.classes' has no attribute 'Jane'
GREEN: make it pass
I add a class for
Janetoclasses.py25class Smith(src.person.Person): 26 27 def __init__(self, first_name): 28 self.last_name = 'smith' 29 30 31class Jane(src.person.Person): passTypeError: Person.__init__() missing 1 required positional argument: 'first_name'because this happens when
jane = src.classes.Jane()runsjane = src.classes.Jane() Jane # Jane has no __init__, call Person Person.__init__()which raises TypeError since the
__init__method ofPersonrequires one positional argument (first_name) and it got called with zeroI add the
__init__method to the definition ofJane31# class Jane(src.person.Person): pass 32class Jane(src.person.Person): 33 34 def __init__(self): 35 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 definition31# class Jane(src.person.Person): pass 32class Jane(src.person.Person): 33 34 def __init__(self): 35 self.first_name = 'jane' 36 return None
the test passes.
REFACTOR: make it better
I add an assertion for the last name of
janeto test_classes_w_multiple_parents intest_classes.py136 def test_classes_w_multiple_parents(self): 137 jane = src.classes.Jane() 138 self.assertEqual(jane.first_name, 'jane') 139 self.assertEqual(jane.last_name, 'doe') 140 141 142# 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_nametoJaneinclasses.py31# class Jane(src.person.Person): pass 32class Jane(src.person.Person): 33 34 def __init__(self): 35 self.first_name = 'jane' 36 self.last_name = 'doe' 37 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_classes.py136 def test_classes_w_multiple_parents(self): 137 jane = src.classes.Jane() 138 self.assertEqual(jane.first_name, 'jane') 139 self.assertEqual(jane.last_name, 'doe') 140 self.assertIsSubclass( 141 src.classes.Jane, src.classes.Doe 142 ) 143 144 145# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'src.classes.Jane'> is not a subclass of <class 'src.classes.Doe'>I change the parent of
Janeinclasses.py31# class Jane(src.person.Person): pass 32# class Jane(src.person.Person): 33class Jane(Doe): 34 35 def __init__(self): 36 self.first_name = 'jane' 37 self.last_name = 'doe' 38 return Nonethe test passes
I add a call to the super built-in function to use to remove the repetition of
last_name31# class Jane(src.person.Person): pass 32# class Jane(src.person.Person): 33class Jane(Doe): 34 35 def __init__(self): 36 super().__init__() 37 # self.first_name = 'jane' 38 # self.last_name = 'doe' 39 return NoneTypeError: Doe.__init__() missing 1 required positional argument: 'first_name'because this happens when
jane = src.classes.Jane()runsjane = src.classes.Jane() Jane.__init__() super().__init__() Doe.__init__()which raises TypeError since the
__init__method ofDoerequires two positional arguments (selfandfirst_name) and it got called with one (self)I add
janeas the value forfirst_namein the call to the parent31# class Jane(src.person.Person): pass 32# class Jane(src.person.Person): 33class Jane(Doe): 34 35 def __init__(self): 36 # super().__init__() 37 super().__init__('jane') 38 # self.first_name = 'jane' 39 # self.last_name = 'doe' 40 return Nonethe test is green again because this happens when
jane = src.classes.Jane()runsjane = src.classes.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 valueI add an assertion for
mary, another instance ofJaneto test_classes_w_multiple_parents intest_classes.py136 def test_classes_w_multiple_parents(self): 137 jane = src.classes.Jane() 138 self.assertEqual(jane.first_name, 'jane') 139 self.assertEqual(jane.last_name, 'doe') 140 self.assertIsSubclass( 141 src.classes.Jane, src.classes.Doe 142 ) 143 144 mary = src.classes.Jane('mary') 145 self.assertEqual(mary.first_name, 'mary') 146 147 148# 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.classes.Jane('mary')runsmary = src.classes.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 ofJaneinclasses.py31# class Jane(src.person.Person): pass 32# class Jane(src.person.Person): 33class Jane(Doe): 34 35 # def __init__(self): 36 def __init__(self, first_name): 37 # super().__init__() 38 super().__init__('jane') 39 # self.first_name = 'jane' 40 # self.last_name = 'doe' 41 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.classes.Jane()runsjane = src.classes.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_nameoptional31# class Jane(src.person.Person): pass 32# class Jane(src.person.Person): 33class Jane(Doe): 34 35 # def __init__(self): 36 # def __init__(self, first_name): 37 def __init__(self, first_name='jane'): 38 # super().__init__() 39 super().__init__('jane') 40 # self.first_name = 'jane' 41 # self.last_name = 'doe' 42 return Nonethe terminal is my friend, and shows AssertionError
AssertionError: 'jane' != 'mary'because this happens when
mary = src.classes.Jane('mary')runsI change the call to the super built-in function to use the name instead of a fixed value
31# class Jane(src.person.Person): pass 32# class Jane(src.person.Person): 33class Jane(Doe): 34 35 # def __init__(self): 36 # def __init__(self, first_name): 37 def __init__(self, first_name='jane'): 38 # super().__init__() 39 # super().__init__('jane') 40 super().__init__(first_name) 41 # self.first_name = 'jane' 42 # self.last_name = 'doe' 43 returnthe test passes.
I remove the commented lines and
return None25class Smith(src.person.Person): 26 27 def __init__(self, first_name): 28 self.last_name = 'smith' 29 30 31class Jane(Doe): 32 33 def __init__(self, first_name='jane'): 34 super().__init__(first_name)I add an assertion that will fail, for the last name of
maryin test_classes_w_multiple_parents intest_classes.py144 mary = src.classes.Jane('mary') 145 self.assertEqual(mary.first_name, 'mary') 146 self.assertEqual(mary.last_name, mary.first_name) 147 148 149# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'doe' != 'mary'I change the expectation to match reality
144 mary = src.classes.Jane('mary') 145 self.assertEqual(mary.first_name, 'mary') 146 # self.assertEqual(mary.last_name, mary.first_name) 147 self.assertEqual(mary.last_name, jane.last_name) 148 149 150# Exceptions seenthe test passes because
maryandjaneare instances ofJane
I add an assertion for
joe136 def test_classes_w_multiple_parents(self): 137 joe = src.classes.Joe() 138 self.assertEqual(joe.first_name, 'joe') 139 140 jane = src.classes.Jane() 141 self.assertEqual(jane.first_name, 'jane') 142 self.assertEqual(jane.last_name, 'doe') 143 self.assertIsSubclass( 144 src.classes.Jane, src.classes.Doe 145 ) 146 147 mary = src.classes.Jane('mary') 148 self.assertEqual(mary.first_name, 'mary') 149 # self.assertEqual(mary.last_name, mary.first_name) 150 self.assertEqual(mary.last_name, jane.last_name) 151 152 153# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.classes' has no attribute 'Joe'. Did you mean: 'Doe'?I add a definition for the
Joeclass toclasses.py31class Jane(Doe): 32 33 def __init__(self, first_name='jane'): 34 super().__init__(first_name) 35 36 37class 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.classes.Joe()runsjoe = src.classes.Joe() Person.__init__()which raises TypeError since the
__init__method takes two required positional argument (selfandfirst_name) and it was called with one (self)I add the
__init__method toJoe37# class Joe(src.person.Person): pass 38class Joe(src.person.Person): 39 40 def __init__(self): 41 return Nonethe terminal is my friend, and shows AttributeError
AttributeError: 'Joe' object has no attribute 'first_name'I add
self.first_nametoJoewith a value37# class Joe(src.person.Person): pass 38class Joe(src.person.Person): 39 40 def __init__(self): 41 self.first_name = 'joe' 42 return Nonethe test passes.
I add an assertion to test_classes_w_multiple_parents to make sure that
joeis aBlow, intest_classes.py131 def test_classes_w_multiple_parents(self): 132 joe = src.classes.Joe() 133 # self.assertEqual(joe.first_name, 'mary') 134 self.assertEqual(joe.first_name, 'joe') 135 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 ofJoeinclasses.py37# class Joe(src.person.Person): pass 38class Joe(src.person.Person): 39 40 def __init__(self): 41 self.first_name = 'joe' 42 self.last_name = 'blow' 43 return Nonethe test passes. I cheated, which means I need a better test.
I add issubclass_ to test_classes_w_multiple_parents to make sure
Joeis a child (subclass) ofBlow, intest_classes.py131 def test_classes_w_multiple_parents(self): 132 joe = src.classes.Joe() 133 self.assertEqual(joe.first_name, 'joe') 134 self.assertEqual(joe.last_name, 'blow') 135 assert issubclass( 136 src.classes.Joe, src.classes.Blow 137 )the terminal is my friend, and shows AssertionError
AssertionError: assert FalseI change the parent of
JoetoBlowinclasses.py37# class Joe(src.person.Person): pass 38# class Joe(src.person.Person): 39class Joe(Blow): 40 41 def __init__(self): 42 self.first_name = 'joe' 43 self.last_name = 'blow' 44 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 function37# class Joe(src.person.Person): pass 38# class Joe(src.person.Person): 39class Joe(Blow): 40 41 def __init__(self): 42 super().__init__('joe') 43 # self.first_name = 'joe' 44 # self.last_name = 'blow' 45 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.classes.Joe()runsjoe = src.classes.Joe() Joe.__init__() super().__init__('joe') Blow.__init__('joe') self.last_name = 'blow'there is no assignment of a value to the
first_nameattribute inBlowI add
self.first_nametoBlow19class Blow(src.person.Person): 20 21 def __init__(self, first_name): 22 self.first_name = first_name 23 self.last_name = 'blow'the test passes because this happens when
joe = src.classes.Joe()runsjoe = src.classes.Joe() Joe.__init__() super().__init__('joe') Blow.__init__('joe') self.first_name = 'joe' self.last_name = 'blow'I remove the commented lines and
return NonefromJoe32class Jane(Doe): 33 34 def __init__(self, first_name='jane'): 35 super().__init__(first_name) 36 37 38class Joe(Blow): 39 40 def __init__(self): 41 super().__init__('joe')I add a call to the `assertNotIsSubclass method`_ in test_classes_w_multiple_parents in
test_classes.py131 def test_classes_w_multiple_parents(self): 132 joe = src.classes.Joe() 133 self.assertEqual(joe.first_name, 'joe') 134 self.assertEqual(joe.last_name, 'blow') 135 assert issubclass( 136 src.classes.Joe, src.classes.Blow 137 ) 138 self.assertNotIsSubclass( 139 src.classes.Joe, src.classes.Blow 140 )the terminal is my friend, and shows AssertionError
AssertionError: <src.classes.Joe object at 0xffffabcdef80> is a subclass of <class 'src.classes.Blow'>I change assertNotIsSubclass_ to assertIsSubclass_ to make the statement True
136 def test_classes_w_multiple_parents(self): 137 joe = src.classes.Joe() 138 self.assertEqual(joe.first_name, 'joe') 139 self.assertEqual(joe.last_name, 'blow') 140 assert issubclass( 141 src.classes.Joe, src.classes.Blow 142 ) 143 # self.assertNotIsSubclass( 144 self.assertIsSubclass( 145 src.classes.Joe, src.classes.Blow 146 )the test passes.
I change
maryto be an instance ofMary, a child (subclass) ofJane155 # mary = src.classes.Jane('mary') 156 mary = src.classes.Mary() 157 self.assertEqual(mary.first_name, 'mary') 158 # self.assertEqual(mary.last_name, mary.first_name) 159 self.assertEqual(mary.last_name, jane.last_name) 160 161 162# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.classes' has no attribute 'Mary'I add a class definition for
Marytoclasses.py38class Joe(Blow): 39 40 def __init__(self): 41 super().__init__('joe') 42 43 44class Mary(Jane): passthe terminal is my friend, and shows AssertionError
AssertionError: 'jane' != 'mary'because this happens when
mary = src.classes.Mary()runsmary = src.classes.Mary() Mary # has no __init__ call 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 toMary44# class Mary(Jane): pass 45class Mary(Jane): 46 47 def __init__(self): 48 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.classes.Mary()runsmary = src.classes.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.classes.Mary()runsmary = src.classes.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 an assertion with the `issubclass built-in function`_ to test_classes_w_multiple_parents in
test_classes.py155 # mary = src.classes.Jane('mary') 156 mary = src.classes.Mary() 157 self.assertEqual(mary.first_name, 'mary') 158 # self.assertEqual(mary.last_name, mary.first_name) 159 self.assertEqual(mary.last_name, jane.last_name) 160 assert not issubclass( 161 src.classes.Mary, src.classes.Jane 162 ) 163 164 165# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: assert not TrueI change the assertion to make it True
155 # mary = src.classes.Jane('mary') 156 mary = src.classes.Mary() 157 self.assertEqual(mary.first_name, 'mary') 158 # self.assertEqual(mary.last_name, mary.first_name) 159 self.assertEqual(mary.last_name, jane.last_name) 160 # assert not issubclass( 161 assert issubclass( 162 src.classes.Mary, src.classes.Jane 163 ) 164 165 166# Exceptions seenthe test passes.
I add a call to assertNotIsSubclass_
155 # mary = src.classes.Jane('mary') 156 mary = src.classes.Mary() 157 self.assertEqual(mary.first_name, 'mary') 158 # self.assertEqual(mary.last_name, mary.first_name) 159 self.assertEqual(mary.last_name, jane.last_name) 160 # assert not issubclass( 161 assert issubclass( 162 src.classes.Mary, src.classes.Jane 163 ) 164 self.assertNotIsSubclass( 165 src.classes.Mary, src.classes.Jane 166 ) 167 168 169# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'src.classes.Mary'> is a subclass of <class 'src.classes.Jane'>I change assertNotIsSubclass_ to the `assertIsSubclass method`_
155 # mary = src.classes.Jane('mary') 156 mary = src.classes.Mary() 157 self.assertEqual(mary.first_name, 'mary') 158 # self.assertEqual(mary.last_name, mary.first_name) 159 self.assertEqual(mary.last_name, jane.last_name) 160 # assert not issubclass( 161 assert issubclass( 162 src.classes.Mary, src.classes.Jane 163 ) 164 # self.assertNotIsSubclass( 165 self.assertIsSubclass( 166 src.classes.Mary, src.classes.Jane 167 ) 168 169 170# Exceptions seenthe test passes.
what happens when the child has more than one parent?
I add an assertion to test if I can make
JoeandJaneboth be parents ofMary?155 # mary = src.classes.Jane('mary') 156 mary = src.classes.Mary() 157 self.assertEqual(mary.first_name, 'mary') 158 # self.assertEqual(mary.last_name, mary.first_name) 159 self.assertEqual(mary.last_name, jane.last_name) 160 # assert not issubclass( 161 assert issubclass( 162 src.classes.Mary, src.classes.Jane 163 ) 164 # self.assertNotIsSubclass( 165 self.assertIsSubclass( 166 src.classes.Mary, src.classes.Jane 167 ) 168 assert issubclass( 169 src.classes.Mary, src.classes.Joe 170 ) 171 172 173# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: assert Falsebecause
Maryis not a child (subclass) ofJoeI add
Joeas a parent ofMaryinclasses.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.classes.Mary()runsmary = src.classes.Mary() Mary.__init__() super().__init__('mary') Jane.__init__('mary') super().__init__(first_name) Joe.__init__('mary')which raises TypeError since the
__init__method ofJoeonly takes one positional argument (self) and it got called with two (selfandmary)I change the
__init__method inJoeto take afirst_nameargument38class Joe(Blow): 39 40 # def __init__(self): 41 def __init__(self, first_name): 42 super().__init__('joe')the terminal is my friend, and shows TypeError
TypeError: Joe.__init__() missing 1 required positional argument: 'first_name'I broke the call that makes
joe = src.classes.Joe()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 the first name of
marybecause this happens whenmary = src.classes.Mary()runsmary = src.classes.Mary() Mary.__init__() super().__init__('mary') Jane.__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 inJoe38 class Joe(Blow): 39 40 # def __init__(self): 41 # def __init__(self, first_name): 42 def __init__(self, first_name='joe'): 43 # super().__init__('joe') 44 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_classes.py148 # mary = src.classes.Jane('mary') 149 mary = src.classes.Mary() 150 self.assertEqual(mary.first_name, 'mary') 151 # self.assertEqual(mary.last_name, mary.first_name) 152 # self.assertEqual(mary.last_name, jane.last_name) 153 self.assertEqual(mary.last_name, joe.last_name) 154 # assert not issubclass( 155 assert issubclass( 156 src.classes.Mary, src.classes.Jane 157 ) 158 # self.assertNotIsSubclass( 159 self.assertIsSubclass( 160 src.classes.Mary, src.classes.Jane 161 ) 162 assert issubclass( 163 src.classes.Mary, src.classes.Joe 164 ) 165 166 167# Exceptions seenthe test passes.
I add a call to the `assertNotIsSubclass method`_
148 # mary = src.classes.Jane('mary') 149 mary = src.classes.Mary() 150 self.assertEqual(mary.first_name, 'mary') 151 # self.assertEqual(mary.last_name, mary.first_name) 152 # self.assertEqual(mary.last_name, jane.last_name) 153 self.assertEqual(mary.last_name, joe.last_name) 154 self.assertEqual(mary.eye_color, jane.eye_color) 155 # assert not issubclass( 156 assert issubclass( 157 src.classes.Mary, src.classes.Jane 158 ) 159 # self.assertNotIsSubclass( 160 self.assertIsSubclass( 161 src.classes.Mary, src.classes.Jane 162 ) 163 assert issubclass( 164 src.classes.Mary, src.classes.Joe 165 ) 166 self.assertNotIsSubclass( 167 src.classes.Mary, src.classes.Joe 168 ) 169 170 171# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'src.classes.Mary'> is a subclass of <class 'src.classes.Joe'>I change assertNotIsSubclass_ to assertIsSubclass_
148 # mary = src.classes.Jane('mary') 149 mary = src.classes.Mary() 150 self.assertEqual(mary.first_name, 'mary') 151 # self.assertEqual(mary.last_name, mary.first_name) 152 # self.assertEqual(mary.last_name, jane.last_name) 153 self.assertEqual(mary.last_name, joe.last_name) 154 self.assertEqual(mary.eye_color, jane.eye_color) 155 # assert not issubclass( 156 assert issubclass( 157 src.classes.Mary, src.classes.Jane 158 ) 159 # self.assertNotIsSubclass( 160 self.assertIsSubclass( 161 src.classes.Mary, src.classes.Jane 162 ) 163 assert issubclass( 164 src.classes.Mary, src.classes.Joe 165 ) 166 # self.assertNotIsSubclass( 167 self.assertIsSubclass( 168 src.classes.Mary, src.classes.Joe 169 ) 170 171# Exceptions seenthe test passes.
I change the order of the parents of
Maryto see what it does to the value oflast_nameinclasses.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.classes.Mary()runsmary = src.classes.Mary() Mary.__init__() super().__init__('mary') Joe.__init__('mary') super().__init__(first_name) Blow.__init__('joe') self.first_name = 'joe' self.last_name = 'blow'the
__init__method ofJanenever gets called even though it is a parent ofMaryI add an assertion to test_classes_w_multiple_parents in
classes.py148 jane = src.classes.Jane() 149 self.assertEqual(jane.first_name, 'jane') 150 self.assertEqual(jane.last_name, 'doe') 151 self.assertEqual(jane.eye_color, 'brown') 152 self.assertIsSubclass( 153 src.classes.Jane, src.classes.Doe 154 )the terminal is my friend, and shows AssertionError
AttributeError: 'Jane' object has no attribute 'eye_color'I add a class attribute to
Janeinclasses.py32class Jane(Doe): 33 34 def __init__(self, first_name='jane'): 35 super().__init__(first_name) 36 self.eye_color = 'brown'the test passes.
I add an assertion for the
eye_colorattribute ofmarryin test_classes_w_multiple_parents intest_classes.py156 # mary = src.classes.Jane('mary') 157 mary = src.classes.Mary() 158 self.assertEqual(mary.first_name, 'mary') 159 # self.assertEqual(mary.last_name, mary.first_name) 160 # self.assertEqual(mary.last_name, jane.last_name) 161 self.assertEqual(mary.last_name, joe.last_name) 162 self.assertEqual(mary.eye_color, jane.eye_color) 163 # assert not issubclass( 164 assert issubclass( 165 src.classes.Mary, src.classes.Jane 166 ) 167 # self.assertNotIsSubclass( 168 self.assertIsSubclass( 169 src.classes.Mary, src.classes.Jane 170 ) 171 assert issubclass( 172 src.classes.Mary, src.classes.Joe 173 ) 174 # self.assertNotIsSubclass( 175 self.assertIsSubclass( 176 src.classes.Mary, src.classes.Joe 177 ) 178 179# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: 'Mary' object has no attribute 'eye_color'I change the order of the parents of
Maryfrom(Joe, Jane)to(Jane, Joe)inclasses.py48# class Mary(Jane): pass 49# class Mary(Jane): 50class Mary(Jane, Joe): 51# class Mary(Joe, Jane): 52 53 def __init__(self): 54 super().__init__('mary') 55 # self.first_name = 'mary' 56 # self.last_name = 'doe'the test passes because this happens when
mary = src.classes.Mary()runsmary = src.classes.Mary() Mary.__init__() super().__init__('mary') Jane.__init__('mary') super().__init__(first_name) self.eye_color = 'brown' Joe.__init__('mary') super().__init__('joe') # the problem Blow.__init__('joe') self.first_name = 'joe' self.last_name = 'blow'the order of the parents matters.
I add
johnto test_classes_w_multiple_parents intest_classes.py156 # mary = src.classes.Jane('mary') 157 mary = src.classes.Mary() 158 self.assertEqual(mary.first_name, 'mary') 159 # self.assertEqual(mary.last_name, mary.first_name) 160 # self.assertEqual(mary.last_name, jane.last_name) 161 self.assertEqual(mary.last_name, joe.last_name) 162 self.assertEqual(mary.eye_color, jane.eye_color) 163 # assert not issubclass( 164 assert issubclass( 165 src.classes.Mary, src.classes.Jane 166 ) 167 # self.assertNotIsSubclass( 168 self.assertIsSubclass( 169 src.classes.Mary, src.classes.Jane 170 ) 171 assert issubclass( 172 src.classes.Mary, src.classes.Joe 173 ) 174 # self.assertNotIsSubclass( 175 self.assertIsSubclass( 176 src.classes.Mary, src.classes.Joe 177 ) 178 179 john = src.classes.John() 180 self.assertEqual(john.first_name, 'john') 181 182 183# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.classes' has no attribute 'John'I add a class definition for
Johntoclasses.py48# class Mary(Jane): pass 49# class Mary(Jane): 50class Mary(Jane, Joe): 51# class Mary(Joe, Jane): 52 53 def __init__(self): 54 super().__init__('mary') 55 # self.first_name = 'mary' 56 # self.last_name = 'doe' 57 58 59class 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.classes.John()runsjohn = src.classes.John() Person.__init__()which raises TypeError since the
__init__method ofPersontakes two positional arguments (selfandfirst_name) and it got called with one (self)I add the
__init__method toJohninclasses.py59# class John(src.person.Person): pass 60class John(src.person.Person): 61 62 def __init__(self): 63 self.first_name = 'john'the test passes.
I add an assertion to make sure that
Johnis a child (subclass) ofSmith179 john = src.classes.John() 180 self.assertEqual(john.first_name, 'john') 181 assert issubclass( 182 src.classes.John, src.classes.Smith 183 ) 184 185 186# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: assert Falseno cheating this time.
I change the parent of
JohntoSmithinclasses.py59# class John(src.person.Person): pass 60# class John(src.person.Person): 61class John(Smith): 62 63 def __init__(self): 64 self.first_name = 'john'the test passes.
I add a call to `assertNotIsSubclass`_ in test_classes_w_multiple_parents in
test_classes.py179 john = src.classes.John() 180 self.assertEqual(john.first_name, 'john') 181 assert issubclass( 182 src.classes.John, src.classes.Smith 183 ) 184 self.assertNotIsSubclass( 185 src.classes.John, src.classes.Smith 186 ) 187 188 189# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'src.classes.John'> is a subclass of <class 'src.classes.Smith'>I change the call to `assertNotIsSubclass`_ to the `assertIsSubclass method`_
179 john = src.classes.John() 180 self.assertEqual(john.first_name, 'john') 181 assert issubclass( 182 src.classes.John, src.classes.Smith 183 ) 184 # self.assertNotIsSubclass( 185 self.assertIsSubclass( 186 src.classes.John, src.classes.Smith 187 ) 188 189 190# Exceptions seenthe test passes.
I add an assertion for the
last_nameattribute179 john = src.classes.John() 180 self.assertEqual(john.first_name, 'john') 181 self.assertEqual(john.last_name, 'smith') 182 assert issubclass( 183 src.classes.John, src.classes.Smith 184 ) 185 # self.assertNotIsSubclass( 186 self.assertIsSubclass( 187 src.classes.John, src.classes.Smith 188 ) 189 190 191# 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_nameinJohninclasses.py59# class John(src.person.Person): pass 60# class John(src.person.Person): 61class John(Smith): 62 63 def __init__(self): 64 self.first_name = 'john' 65 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 attribute59# class John(src.person.Person): pass 60# class John(src.person.Person): 61class John(Smith): 62 63 def __init__(self): 64 super().__init__('john') 65 # self.first_name = 'john' 66 # 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 attribute to
Smith26class Smith(src.person.Person): 27 28 def __init__(self, first_name): 29 self.first_name = first_name 30 self.last_name = 'smith'the test passes because this happens when
john = src.classes.John()runsjohn = src.classes.John() John.__init__() super().__init__('john') Smith.__init__('john') self.first_name = 'john' self.last_name = 'smith'
I add another person, a child (subclass) of
Johnto test_classes_w_multiple_parents intest_classes.py179 john = src.classes.John() 180 self.assertEqual(john.first_name, 'john') 181 self.assertEqual(john.last_name, 'smith') 182 assert issubclass( 183 src.classes.John, src.classes.Smith 184 ) 185 # self.assertNotIsSubclass( 186 self.assertIsSubclass( 187 src.classes.John, src.classes.Smith 188 ) 189 190 lil = src.classes.Lil() 191 assert issubclass( 192 src.classes.Lil, src.classes.John 193 ) 194 195 196# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.classes' has no attribute 'Lil'I add a class definition for
Liltoclasses.py60# class John(src.person.Person): pass 61# class John(src.person.Person): 62class John(Smith): 63 64 def __init__(self): 65 super().__init__('john') 66 # self.first_name = 'john' 67 # self.last_name = 'smith' 68 69 70class Lil(John): passthe test passes.
I add a call to the `assertNotIsSubclass method`_ in test_classes_w_multiple_parents in
test_classes.py190 lil = src.classes.Lil() 191 assert issubclass( 192 src.classes.Lil, src.classes.John 193 ) 194 self.assertNotIsSubclass( 195 src.classes.Lil, src.classes.John 196 ) 197 198 199# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <class 'src.classes.Lil'> is a subclass of <class 'src.classes.John'>I change assertNotIsSubclass_ to assertIsSubclass_
190 lil = src.classes.Lil() 191 assert issubclass( 192 src.classes.Lil, src.classes.John 193 ) 194 # self.assertNotIsSubclass( 195 self.assertIsSubclass( 196 src.classes.Lil, src.classes.John 197 ) 198 199 200# Exceptions seenthe test passes
I add an assertion to test
JohnandMaryas parents ofLil?190 lil = src.classes.Lil() 191 assert issubclass( 192 src.classes.Lil, src.classes.John 193 ) 194 # self.assertNotIsSubclass( 195 self.assertIsSubclass( 196 src.classes.Lil, src.classes.John 197 ) 198 assert issubclass( 199 src.classes.Lil, src.classes.Mary 200 ) 201 202 203# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: assert FalseI add
Maryas a parent toLilinclasses.py70# class Lil(John): pass 71class Lil(John, Mary): passthe test passes.
I add an assertion for the
first_nameattribute oflilintest_classes.py190 lil = src.classes.Lil() 191 self.assertEqual(lil.first_name, 'lil') 192 assert issubclass( 193 src.classes.Lil, src.classes.John 194 ) 195 # self.assertNotIsSubclass( 196 self.assertIsSubclass( 197 src.classes.Lil, src.classes.John 198 ) 199 assert issubclass( 200 src.classes.Lil, src.classes.Mary 201 ) 202 203 204# Exceptions seenthe terminal shows AssertionError
AssertionError: 'john' != 'lil'because this happens when
lil = src.classes.Lil()runslil = src.classes.Lil() Lil # has no __init__, call 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 thefirst_nameattribute inLilinclasses.py70# class Lil(John): pass 71# class Lil(John, Mary): pass 72class Lil(John, Mary): 73 74 def __init__(self): 75 self.first_name = 'lil'the test passes.
I add an assertion for the
last_nameattribute oflil, in test_classes_w_multiple_parents intest_classes.py190 lil = src.classes.Lil() 191 self.assertEqual(lil.first_name, 'lil') 192 self.assertEqual(lil.last_name, mary.last_name) 193 assert issubclass( 194 src.classes.Lil, src.classes.John 195 ) 196 # self.assertNotIsSubclass( 197 self.assertIsSubclass( 198 src.classes.Lil, src.classes.John 199 ) 200 assert issubclass( 201 src.classes.Lil, src.classes.Mary 202 ) 203 204 205# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: 'Lil' object has no attribute 'last_name'. Did you mean: 'first_name'?I add a value for
last_nametoLilinclasses.py70# class Lil(John): pass 71# class Lil(John, Mary): pass 72class Lil(John, Mary): 73 74 def __init__(self): 75 self.first_name = 'lil' 76 self.last_name = 'blow'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
70# class Lil(John): pass 71# class Lil(John, Mary): pass 72class Lil(John, Mary): 73 74 def __init__(self): 75 super().__init__('lil') 76 # self.first_name = 'lil' 77 # self.last_name = 'blow'TypeError: John.__init__() takes 1 positional argument but 2 were givenbecause this happens when
lil = src.classes.Lil()runslil = src.classes.Lil() Lil.__init__() super().__init__('lil') John.__init__()which raises TypeError since the
__init__method ofJohntakes one positional argument (self) and it was called with two (selfandlil)I change the
__init__method inJohnto take in a parameter forfirst_namewith a default value to make it optional60# class John(src.person.Person): pass 61# class John(src.person.Person): 62class John(Smith): 63 64 # def __init__(self): 65 def __init__(self, first_name='john'): 66 # super().__init__('john') 67 super().__init__(first_name) 68 # self.first_name = 'john' 69 # self.last_name = 'smith'the terminal shows AssertionError
because this happens when
lil = src.classes.Lil()runslil = src.classes.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_nameno other
__init__methods get called for the parents ofLilI add a call to the super built-in function in
Smithto see what will happen26class Smith(src.person.Person): 27 28 def __init__(self, first_name): 29 super().__init__( 30 first_name=first_name, 31 last_name='smith', 32 ) 33 # self.first_name = first_name 34 # 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.classes.Lil()runslil = src.classes.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')which raises TypeError since the
__init__method ofMarywas called with a keyword argument notselfI add
first_namewith a default value to the__init__method ofMary50# class Mary(Jane): pass 51# class Mary(Jane): 52class Mary(Jane, Joe): 53# class Mary(Joe, Jane): 54 55 # def __init__(self): 56 def __init__(self, first_name='mary'): 57 # super().__init__('mary') 58 super().__init__(first_name) 59 # self.first_name = 'mary' 60 # self.last_name = 'doe'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__method50# class Mary(Jane): pass 51# class Mary(Jane): 52class Mary(Jane, Joe): 53# class Mary(Joe, Jane): 54 55 # def __init__(self): 56 # def __init__(self, first_name='mary'): 57 def __init__(self, first_name='mary', last_name): 58 # super().__init__('mary') 59 super().__init__(first_name) 60 # self.first_name = 'mary' 61 # self.last_name = 'doe'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
this is a problem, I just broke the
mary = src.classes.Mary()which was working before.I add a default value for
last_name53# class Mary(Jane): pass 54# class Mary(Jane): 55class Mary(Jane, Joe): 56# class Mary(Joe, Jane): 57 58 # def __init__(self): 59 # def __init__(self, first_name='mary'): 60 # def __init__(self, first_name='mary', last_name): 61 def __init__( 62 self, first_name='mary', 63 last_name=None, 64 ): 65 # super().__init__('mary') 66 super().__init__(first_name) 67 # self.first_name = 'mary' 68 # self.last_name = 'doe'because this happens when
lil = src.classes.Lil()runslil = src.classes.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) Jane.__init__('lil') super().__init__(first_name) self.eye_color = 'brown' Joe.__init__('lil') super().__init__('lil') Blow.__init__('lil') self.first_name = 'lil' self.last_name = 'blow'I change the order of the parents of
Lilto(Mary, John)to see if the value will change tojohn.last_name83# class Lil(John): pass 84# class Lil(John, Mary): pass 85# class Lil(John, Mary): 86class Lil(Mary, John): 87 88 def __init__(self): 89 super().__init__('lil') 90 # self.first_name = 'lil' 91 # self.last_name = 'blow'the test is still green because this happens when
lil = src.classes.Lil()runslil = src.classes.Lil() Lil.__init__() super().__init__('lil') Mary.__init__('lil') Mary.__init__('lil', last_name=None) super().__init__(first_name) Jane.__init__('lil') super().__init__(first_name) self.eye_color = 'brown' Joe.__init__('lil') super().__init__('lil') Blow.__init__('lil') self.first_name = 'lil' self.last_name = 'blow'no other
__init__methods get called for the parents ofLilI add a call to the super built-in function in
Blow19class Blow(src.person.Person): 20 21 def __init__(self, first_name): 22 super().__init__( 23 first_name=first_name, 24 last_name='blow', 25 ) 26 # self.first_name = first_name 27 # self.last_name = 'blow'the terminal is my friend, and shows TypeError
TypeError: John.__init__() got an unexpected keyword argument 'last_name'. Did you mean 'first_name'?because this happens when
lil = src.classes.Lil()runslil = src.classes.Lil() Lil.__init__() super().__init__('lil') Mary.__init__('lil') Mary.__init__('lil', last_name=None) super().__init__(first_name) Jane.__init__('lil') super().__init__(first_name) self.eye_color = 'brown' Doe.__init__('lil') super().__init__(first_name) Joe.__init__('lil') super().__init__('lil') Blow.__init__('lil') super().__init__( first_name=first_name, last_name='blow', ) John.__init__( first_name='lil', last_name='blow', )which raises TypeError since the
__init__method ofJohndoes not have a parameter namedlast_nameI add
last_nametoJohn75# 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 # super().__init__('john') 83 super().__init__(first_name) 84 # self.first_name = 'john' 85 # self.last_name = 'smith'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 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: 'smith' != 'blow'I change the expectation of the assertion for
lil.last_namein test_classes_w_multiple_parents190 lil = src.classes.Lil() 191 self.assertEqual(lil.first_name, 'lil') 192 # self.assertEqual(lil.last_name, mary.last_name) 193 self.assertEqual(lil.last_name, john.last_name) 194 assert issubclass( 195 src.classes.Lil, src.classes.John 196 ) 197 # self.assertNotIsSubclass( 198 self.assertIsSubclass( 199 src.classes.Lil, src.classes.John 200 ) 201 assert issubclass( 202 src.classes.Lil, src.classes.Mary 203 ) 204 205 206# Exceptions seenthe test passes because this happens when
lil = src.classes.Lil()runslil = src.classes.Lil() Lil.__init__() super().__init__('lil') Mary.__init__('lil') Mary.__init__('lil', last_name=None) super().__init__(first_name) Jane.__init__('lil') super().__init__(first_name) self.eye_color = 'brown' Doe.__init__('lil') super().__init__(first_name) Joe.__init__('lil') super().__init__('lil') Blow.__init__('lil') super().__init__( first_name=first_name, last_name='blow', ) John.__init__( first_name='lil', last_name='blow', ) 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 add an assertion for
lil.eye_colorto test if instance ofLilinheriteye_colorfromJane, the parent ofMary190 lil = src.classes.Lil() 191 self.assertEqual(lil.first_name, 'lil') 192 # self.assertEqual(lil.last_name, mary.last_name) 193 self.assertEqual(lil.last_name, john.last_name) 194 self.assertEqual(lil.eye_color, '') 195 assert issubclass( 196 src.classes.Lil, src.classes.John 197 ) 198 # self.assertNotIsSubclass( 199 self.assertIsSubclass( 200 src.classes.Lil, src.classes.John 201 ) 202 assert issubclass( 203 src.classes.Lil, src.classes.Mary 204 ) 205 206 207# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'brown' != ''I change the expectation of the assertion
190 lil = src.classes.Lil() 191 self.assertEqual(lil.first_name, 'lil') 192 # self.assertEqual(lil.last_name, mary.last_name) 193 self.assertEqual(lil.last_name, john.last_name) 194 # self.assertEqual(lil.eye_color, '') 195 self.assertEqual(lil.eye_color, jane.eye_color) 196 assert issubclass( 197 src.classes.Lil, src.classes.John 198 ) 199 # self.assertNotIsSubclass( 200 self.assertIsSubclass( 201 src.classes.Lil, src.classes.John 202 ) 203 assert issubclass( 204 src.classes.Lil, src.classes.Mary 205 ) 206 207 208# Exceptions seeninstances of
LilandMarygeteye_colorfromJaneifJaneis an ancestor of the first parent in the order of parents.
I want to see what happens when I add the
eye_colorattribute toMaryinclasses.py57# class Mary(Jane): pass 58# class Mary(Jane): 59class Mary(Jane, Joe): 60# class Mary(Joe, Jane): 61 62 # def __init__(self): 63 # def __init__(self, first_name='mary'): 64 # def __init__(self, first_name='mary', last_name): 65 def __init__( 66 self, first_name='mary', 67 last_name=None, 68 ): 69 # super().__init__('mary') 70 super().__init__(first_name) 71 self.eye_color = 'red' 72 # self.first_name = 'mary' 73 # self.last_name = 'doe'the terminal is my friend, and shows AssertionError
AssertionError: 'red' != 'brown'for
mary.eye_colorbecause instances of classes can override the attributes and methods they inheritI change the expectation of the assertion for
mary.eye_colorin test_classes_w_multiple_parents intest_classes.py156 # mary = src.classes.Jane('mary') 157 mary = src.classes.Mary() 158 self.assertEqual(mary.first_name, 'mary') 159 # self.assertEqual(mary.last_name, mary.first_name) 160 # self.assertEqual(mary.last_name, jane.last_name) 161 self.assertEqual(mary.last_name, joe.last_name) 162 # self.assertEqual(mary.eye_color, jane.eye_color) 163 self.assertEqual(mary.eye_color, 'red') 164 # assert not issubclass( 165 assert issubclass( 166 src.classes.Mary, src.classes.Jane 167 ) 168 # self.assertNotIsSubclass( 169 self.assertIsSubclass( 170 src.classes.Mary, src.classes.Jane 171 ) 172 assert issubclass( 173 src.classes.Mary, src.classes.Joe 174 ) 175 # self.assertNotIsSubclass( 176 self.assertIsSubclass( 177 src.classes.Mary, src.classes.Joe 178 )the terminal is my friend, and shows AssertionError
AssertionError: 'red' != 'brown'for
lil.eye_colorbecause this happens whenlil = src.classes.Lil()runslil = src.classes.Lil() Lil.__init__() super().__init__('lil') Mary.__init__('lil') Mary.__init__('lil', last_name=None) super().__init__(first_name) self.eye_color = 'red' Jane.__init__('lil') super().__init__(first_name) # self.eye_color = 'brown' does not affect instance Doe.__init__('lil') super().__init__(first_name) Joe.__init__('lil') super().__init__('lil') Blow.__init__('lil') super().__init__( first_name=first_name, last_name='blow', ) John.__init__( first_name='lil', last_name='blow', ) 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
eye_colorattribute ofJanenever gets set for instances ofMaryI change the expectation of the assertion for
lil.eye_colorin test_classes_w_multiple_parents191 lil = src.classes.Lil() 192 self.assertEqual(lil.first_name, 'lil') 193 # self.assertEqual(lil.last_name, mary.last_name) 194 self.assertEqual(lil.last_name, john.last_name) 195 # self.assertEqual(lil.eye_color, '') 196 # self.assertEqual(lil.eye_color, jane.eye_color) 197 self.assertEqual(lil.eye_color, mary.eye_color) 198 assert issubclass( 199 src.classes.Lil, src.classes.John 200 ) 201 # self.assertNotIsSubclass( 202 self.assertIsSubclass( 203 src.classes.Lil, src.classes.John 204 ) 205 assert issubclass( 206 src.classes.Lil, src.classes.Mary 207 ) 208 209 210# Exceptions seenthe test passes.
I change the order of the parents of
Lilinclasses.py93# class Lil(John): pass 94# class Lil(John, Mary): pass 95class Lil(John, Mary): 96# class Lil(Mary, John): 97 98 def __init__(self): 99 super().__init__('lil') 100 # self.first_name = 'lil' 101 # self.last_name = 'blow'the terminal is my friend, and shows AssertionError
AssertionError: 'blow' != 'smith'because the order of the parents has an effect on the
last_nameattribute.I change the expectation of the assertion for
lil.last_name191 lil = src.classes.Lil() 192 self.assertEqual(lil.first_name, 'lil') 193 self.assertEqual(lil.last_name, mary.last_name) 194 # self.assertEqual(lil.last_name, john.last_name) 195 # self.assertEqual(lil.eye_color, '') 196 # self.assertEqual(lil.eye_color, jane.eye_color) 197 self.assertEqual(lil.eye_color, mary.eye_color) 198 assert issubclass( 199 src.classes.Lil, src.classes.John 200 ) 201 # self.assertNotIsSubclass( 202 self.assertIsSubclass( 203 src.classes.Lil, src.classes.John 204 ) 205 assert issubclass( 206 src.classes.Lil, src.classes.Mary 207 )the test passes.
I add an assertion for
john.eye_color180 john = src.classes.John() 181 self.assertEqual(john.first_name, 'john') 182 self.assertEqual(john.last_name, 'smith') 183 self.assertEqual(john.eye_color, 'orange') 184 assert issubclass( 185 src.classes.John, src.classes.Smith 186 ) 187 # self.assertNotIsSubclass( 188 self.assertIsSubclass( 189 src.classes.John, src.classes.Smith 190 )the terminal is my friend, and shows AttributeError
AttributeError: 'John' object has no attribute 'eye_color'I add a value for the
eye_colorattribute toSmithinclasses.py30class Smith(src.person.Person): 31 32 def __init__(self, first_name): 33 super().__init__( 34 first_name=first_name, 35 last_name='smith', 36 ) 37 self.eye_color = 'orange' 38 # self.first_name = first_name 39 # self.last_name = 'smith'the terminal is my friend, and shows AssertionError
AssertionError: 'orange' != 'red'because if the parents of
Lilare(John, Mary), this happens whenlil = src.classes.Lil()runslil = src.classes.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', ) self.eye_color = 'orange' Mary.__init__('lil', 'smith') super().__init__(first_name) # self.eye_color = 'red' does not affect instance Jane.__init__('lil') super().__init__(first_name) # self.eye_color = 'brown' does not affect instance Joe.__init__('lil') super().__init__('lil') Blow.__init__('lil') self.first_name = 'lil' self.last_name = 'blow'
I add an assertion for the
first_name, in test_classes_w_multiple_parents intest_classes.py164 lil = src.classes.Lil() 165 self.assertIsInstance(lil, src.classes.John) 166 self.assertEqual(lil.first_name, 'lil') 167 168 169# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'john' != 'lil'I add the
__init__method in the definition ofLilinclasses.py57# class Lil(John): pass 58class Lil(John): 59 60 def __init__(self, first_name='lil'): 61 super().__init__(first_name=first_name)the test passes.
I add an assertion for the last name of
lil, in test_classes_w_multiple_parents intest_classes.py164 lil = src.classes.Lil() 165 self.assertIsInstance(lil, src.classes.John) 166 self.assertEqual(lil.first_name, 'lil') 167 self.assertEqual(lil.last_name, lil.first_name) 168 169 170# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: 'smith' != 'lil'I change the expectation
164 lil = src.classes.Lil() 165 self.assertIsInstance(lil, src.classes.John) 166 self.assertEqual(lil.first_name, 'lil') 167 # self.assertEqual(lil.last_name, lil.first_name) 168 self.assertEqual(lil.last_name, john.last_name) 169 170 171# Exceptions seenthe test passes because Python makes the following calls to resolve the call to make an instance of the
Lilclass whenJohnis the parentlil = src.classes.Lil() Lil.__init__(first_name='lil') super().__init__(first_name=first_name) = John.__init__(first_name='lil') super().__init__(first_name=first_name) = Smith.__init__('lil') super().__init__(first_name, last_name='smith') = Person.__init__('lil', last_name='smith') self.first_name = 'lil' self.last_name = 'smith'I add assertIsInstance_ to test if
Lilis an instance ofMary164 lil = src.classes.Lil() 165 self.assertIsInstance(lil, src.classes.John) 166 self.assertIsInstance(lil, src.classes.Mary) 167 self.assertEqual(lil.first_name, 'lil') 168 # self.assertEqual(lil.last_name, lil.first_name) 169 self.assertEqual(lil.last_name, john.last_name) 170 171 172# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: <src.classes.Lil object at 0xffffaaaaaaaa> is not an instance of <class 'src.classes.Mary'>because
Lilis not a child ofMary, yet.I add
Maryas a parent ofLilbeforeJohnto see if it will change thelast_namevalue, inclasses.py57# class Lil(John): pass 58# class Lil(John): 59class Lil(Mary, John): 60 61 def __init__(self, first_name='lil'): 62 super().__init__(first_name=first_name)the terminal is my friend, and shows TypeError
TypeError: John.__init__() got an unexpected keyword argument 'last_name'. Did you mean 'first_name'?because Python makes the following calls to resolve the call to make an instance of the
Lilclass if the parents are(Mary, John)first it makes these calls for the
Maryparent, to resolve the attributeslil = src.classes.Lil() Lil.__init__(first_name='lil') super().__init__(first_name=first_name) = Mary.__init__(first_name='lil') super().__init__(first_name=first_name) = Jane.__init__(first_name='lil', **kwargs) super().__init__(first_name=first_name) = Doe # Doe has no __init__, skip to Joe = Joe.__init__(first_name='lil') super().__init__(first_name=first_name) = Blow.__init__('lil') super().__init__(first_name, last_name='blow')then it makes this call for the
Johnparent, to resolve the attributeslil = John.__init__(first_name='lil', last_name='blow')which raises TypeError since the
__init__method ofJohnonly takes one keyword_argument (first_name) and the call provides two (first_nameandlast_name)I add a double starred expression to
Johnso it can take any number of keyword arguments50# class John(src.person.Person): 51class John(Smith): 52 53 # def __init__(self, first_name='john'): 54 def __init__(self, first_name='john', **kwargs): 55 super().__init__(first_name=first_name)the test passes Python makes this call for the
Johnparent after it gets values from theMaryparent, to resolve the attributeslil = John.__init__(first_name='lil', last_name='blow') super().__init__(first_name=first_name) = Smith.__init__(first_name='lil') super().__init__(first_name, last_name='smith') = Person.__init__('lil', last_name='smith') self.first_name = 'lil' self.last_name = 'smith'
I change the order of the parents of
Lil58# class Lil(John): pass 59# class Lil(John): 60# class Lil(Mary, John): 61class Lil(John, Mary): 62 63 def __init__(self, first_name='lil'): 64 super().__init__(first_name=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'?same problem, same solution
I add a double starred expression to
Maryso it can take any number of keyword arguments41# class Mary(Jane): pass 42# class Mary(Joe, Jane): pass 43# class Mary(Joe, Jane): 44class Mary(Jane, Joe): 45 46 # def __init__(self, first_name='mary'): 47 def __init__(self, first_name='mary', **kwargs): 48 super().__init__(first_name=first_name)the terminal is my friend, and shows AssertionError
AssertionError: 'blow' != 'smith'the order of the parents matters because Python makes the following calls to resolve the call to make an instance of the
Lilclass if the parents are(John, Mary)first it makes these calls for the
Johnparent, to resolve the attributeslil = src.classes.Lil() Lil.__init__(first_name='lil') super().__init__(first_name=first_name) = John.__init__(first_name='lil', **kwargs) super().__init__(first_name=first_name) = Smith.__init__(first_name='lil') super().__init__(first_name, last_name='smith')then it makes these calls for the
Maryparent, to resolve the attributeslil = Mary.__init__(first_name='lil', **kwargs) super().__init__(first_name=first_name) = Jane.__init__(first_name='lil', **kwargs) super().__init__(first_name=first_name) = Doe # Doe has no __init__, skip to Joe = Joe.__init__(first_name='lil') super().__init__(first_name=first_name) = Blow.__init__('lil') super().__init__(first_name, last_name='blow') = Person.__init__(first_name='lil', last_name='blow') self.first_name = 'lil' self.last_name = 'blow'JaneandMarydo not pass on the value they receive forlast_nameto their parents when they callsuper().__init__which means the method uses the default value for the parameter because it is called without the parameterBlowalways callsPersonwithblowas the value forlast_nameit does not matter if I send a different valueSmithalways callsPersonwithsmithas the value forlast_nameit does not matter if I send a different valuewhichever parent calls
Personlast will be the values that the instance gets
I change the order of the parents of
Lilback to(Mary, John)59# class Lil(John): pass 60# class Lil(John): 61class Lil(Mary, John): 62# class Lil(John, Mary): 63 64 def __init__(self, first_name='lil'): 65 super().__init__(first_name=first_name)the test is green again. The test shows that
if the parents of
Lilare defined as(Mary, John)the default value forlast_nameis the value forlast_nameofJohnif the parents of
Lilare defined as(John, Mary)the default value forlast_nameis the value for thelast_nameofMary
I remove the commented lines
13class Doe(src.person.Person): pass 14 15 16class Blow(src.person.Person): 17 18 def __init__(self, first_name): 19 super().__init__(first_name, last_name='blow') 20 21 22class Smith(src.person.Person): 23 24 def __init__(self, first_name): 25 super().__init__(first_name, last_name='smith') 26 27 28class Jane(Doe): 29 30 def __init__(self, first_name='jane', **kwargs): 31 super().__init__(first_name=first_name) 32 33 34class Joe(Blow): 35 36 def __init__(self, first_name='joe'): 37 super().__init__(first_name=first_name) 38 39 40class Mary(Jane, Joe): 41 42 def __init__(self, first_name='mary', **kwargs): 43 super().__init__(first_name=first_name) 44 45 46class John(Smith): 47 48 def __init__(self, first_name='john', **kwargs): 49 super().__init__(first_name=first_name) 50 51 52class Lil(Mary, John): 53 54 def __init__(self, first_name='lil'): 55 super().__init__(first_name=first_name)
I remove the commented lines from test_classes_w_multiple_parents in
test_classes.py131 def test_classes_w_multiple_parents(self): 132 joe = src.classes.Joe() 133 self.assertEqual(joe.first_name, 'joe') 134 self.assertEqual(joe.last_name, 'blow') 135 self.assertIsInstance(joe, src.classes.Blow) 136 137 jane = src.classes.Jane() 138 self.assertEqual(jane.first_name, 'jane') 139 self.assertEqual(jane.last_name, 'doe') 140 self.assertIsInstance(jane, src.classes.Doe) 141 142 mary = src.classes.Mary() 143 self.assertEqual(mary.first_name, 'mary') 144 self.assertEqual(mary.last_name, joe.last_name) 145 self.assertIsInstance(mary, src.classes.Jane) 146 self.assertIsInstance(mary, src.classes.Doe) 147 self.assertIsInstance(mary, src.classes.Joe) 148 149 john = src.classes.John() 150 self.assertEqual(john.first_name, 'john') 151 self.assertEqual(john.last_name, 'smith') 152 self.assertIsInstance(john, src.classes.Smith) 153 154 lil = src.classes.Lil() 155 self.assertIsInstance(lil, src.classes.John) 156 self.assertIsInstance(lil, src.classes.Mary) 157 self.assertEqual(lil.first_name, 'lil') 158 self.assertEqual(lil.last_name, john.last_name) 159 160 161# Exceptions seenI 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 it classes.py and it would not have given me the chance to practice making classes with multiple parents and seeing how Python resolves the order - this is called Method Resolution Order
joe = src.classes.Joe()
joe = src.person.Person('joe', last_name='blow')
jane = src.classes.Jane()
jane = src.person.Person('jane')
mary = src.classes.Mary()
mary = src.person.Person('mary', 'blow')
john = src.classes.John()
john = src.person.Person('john', 'smith')
lil = src.person.Lil()
lil = src.person.Person('lil', 'smith')
which would have just been Python making this call to make instances 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
review
I can make a class with
close the project
I close the file(s) I have open in the editor(s)
I click in the terminal where the tests are running, then 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?
you have gone through a lot of things and know
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.