truth table: Binary Operations 2
requirements
preview
Here are the tests I have at the end of this chapter
1import src.truth_table
2import unittest
3
4
5class TestBinaryOperations(unittest.TestCase):
6
7 def test_contradiction(self):
8 self.assertFalse(
9 src.truth_table.contradiction(True, True)
10 )
11 self.assertFalse(
12 src.truth_table.contradiction(True, False)
13 )
14 self.assertFalse(
15 src.truth_table.contradiction(False, True)
16 )
17 self.assertFalse(
18 src.truth_table.contradiction(False, False)
19 )
20
21 def test_logical_conjunction(self):
22 self.assertTrue(
23 src.truth_table.logical_conjunction(True, True)
24 )
25 self.assertFalse(
26 src.truth_table.logical_conjunction(True, False)
27 )
28 self.assertFalse(
29 src.truth_table.logical_conjunction(False, True)
30 )
31 self.assertFalse(
32 src.truth_table.logical_conjunction(False, False)
33 )
34
35 def test_project_second(self):
36 self.assertTrue(
37 src.truth_table.project_second(True, True)
38 )
39 self.assertFalse(
40 src.truth_table.project_second(True, False)
41 )
42 self.assertTrue(
43 src.truth_table.project_second(False, True)
44 )
45 self.assertFalse(
46 src.truth_table.project_second(False, False)
47 )
48
49 def test_converse_non_implication(self):
50 self.assertFalse(
51 src.truth_table.converse_non_implication(True, True)
52 )
53 self.assertFalse(
54 src.truth_table.converse_non_implication(True, False)
55 )
56 self.assertTrue(
57 src.truth_table.converse_non_implication(False, True)
58 )
59 self.assertFalse(
60 src.truth_table.converse_non_implication(False, False)
61 )
62
63 def test_negate_first(self):
64 self.assertFalse(src.truth_table.negate_first(True, True))
65 self.assertFalse(src.truth_table.negate_first(True, False))
66 self.assertTrue(src.truth_table.negate_first(False, True))
67 self.assertTrue(src.truth_table.negate_first(False, False))
68
69 def test_logical_nand(self):
70 self.assertFalse(src.truth_table.logical_nand(True, True))
71 self.assertTrue(src.truth_table.logical_nand(True, False))
72 self.assertTrue(src.truth_table.logical_nand(False, True))
73 self.assertTrue(src.truth_table.logical_nand(False, False))
74
75 def test_tautology(self):
76 self.assertTrue(src.truth_table.tautology(True, True))
77 self.assertTrue(src.truth_table.tautology(True, False))
78 self.assertTrue(src.truth_table.tautology(False, True))
79 self.assertTrue(src.truth_table.tautology(False, False))
80
81 def test_logical_disjunction(self):
82 self.assertTrue(
83 src.truth_table.logical_disjunction(True, True)
84 )
85 self.assertTrue(
86 src.truth_table.logical_disjunction(True, False)
87 )
88 self.assertTrue(
89 src.truth_table.logical_disjunction(False, True)
90 )
91 self.assertFalse(
92 src.truth_table.logical_disjunction(False, False)
93 )
94
95
96# Exceptions seen
97# AttributeError
98# TypeError
99# AssertionError
100# SyntaxError
continue the project
Make sure you are in the
pumping_pythonfolder with pwd in the terminalpwdif the terminal shows anything other than
.../pumping_pythonchange directory to the
pumping_pythonfolderOnce in
pumping_python, change directory to the projectcd truth_tablethe terminal shows
.../pumping_python/truth_tableI run the tests with pytest-watcher
uv run pytest-watcher . --nowthe terminal shows
rootdir: .../pumping_python/truth_table configfile: pyproject.toml collected 8 items tests/test_binary.py .... [ 50%] tests/test_nullary_unary.py .... [100%] ======================== 8 passed in G.HIs =========================I hold ctrl (Windows) or option (MacOS) on the keyboard, then click on
tests/test_binary.pywith the mouse to open it in the editor
test_negate_first
RED: make it fail
I add a new test for negate_first in test_binary.py
49 def test_converse_non_implication(self):
50 self.assertFalse(
51 src.truth_table.converse_non_implication(True, True)
52 )
53 self.assertFalse(
54 src.truth_table.converse_non_implication(True, False)
55 )
56 self.assertTrue(
57 src.truth_table.converse_non_implication(False, True)
58 )
59 self.assertFalse(
60 src.truth_table.converse_non_implication(False, False)
61 )
62
63 def test_negate_first(self):
64 self.assertFalse(src.truth_table.negate_first(True, True))
65
66
67# Exceptions seen
the terminal shows AttributeError
AttributeError: module 'src.truth_table' has no attribute 'negate_first'
there is no definition for negate_first in truth_table.py
GREEN: make it pass
I add the function in
truth_table.py29def converse_non_implication(first_input, second_input): 30 return logical_conjunction(not first_input, second_input) 31 return not first_input and second_input 32 33 34def negate_first(first_input, second_input): 35 return Falsethe test passes.
negate_first returns False, if the first input is True and the second input is True
REFACTOR: make it better
I add the second case - when the first input is True and the second input is False, to
test_binary.py63 def test_negate_first(self): 64 self.assertFalse(src.truth_table.negate_first(True, True)) 65 self.assertFalse(src.truth_table.negate_first(True, False))the test is still green.
negate_firstreturnsI add the next case - when the first input is False and the second input is True
63 def test_negate_first(self): 64 self.assertFalse(src.truth_table.negate_first(True, True)) 65 self.assertFalse(src.truth_table.negate_first(True, False)) 66 self.assertTrue(src.truth_table.negate_first(False, True))the terminal shows AssertionError
AssertionError: False is not trueI add if statements for this case to
negate_firstintruth_table.py34def negate_first(first_input, second_input): 35 if first_input == False: 36 if second_input == True: 37 return True 38 return Falsethe test passes.
negate_firstreturnsI add the last case - when the first input is False and the second input is False to
test_binary.py63 def test_negate_first(self): 64 self.assertFalse(src.truth_table.negate_first(True, True)) 65 self.assertFalse(src.truth_table.negate_first(True, False)) 66 self.assertTrue(src.truth_table.negate_first(False, True)) 67 self.assertTrue(src.truth_table.negate_first(False, False)) 68 69 70# Exceptions seenthe terminal shows AssertionError
AssertionError: False is not trueI add an if statement for it in
truth_table.py34def negate_first(first_input, second_input): 35 if first_input == False: 36 if second_input == False: 37 return True 38 if second_input == True: 39 return True 40 return Falsethe test passes.
negate_firstreturnsTrue, if the first input is False and the second input is False
True, if the first input is False and the second input is True
oh! It returns the logical negation of the first input
I add a return statement
34def negate_first(first_input, second_input): 35 return not first_input 36 if first_input == False: 37 if second_input == False: 38 return True 39 if second_input == True: 40 return True 41 return Falsethe test is still green
I remove the other statements
34def negate_first(first_input, second_input): 35 return not first_inputstill green, no need for if statements here.
Negate First always returns
not first_inputthe opposite (Logical Negation) of the first input in all cases, it does not care about the second input
test_logical_nand
RED: make it fail
I add a new test to test_binary.py
63 def test_negate_first(self):
64 self.assertFalse(src.truth_table.negate_first(True, True))
65 self.assertFalse(src.truth_table.negate_first(True, False))
66 self.assertTrue(src.truth_table.negate_first(False, True))
67 self.assertTrue(src.truth_table.negate_first(False, False))
68
69 def test_logical_nand(self):
70 self.assertFalse(src.truth_table.logical_nand(True, True))
71
72
73# Exceptions seen
the terminal shows AttributeError
AttributeError: module 'src.truth_table' has no attribute 'logical_nand'. Did you mean: 'logical_false'?
there is no definition for logical_nand in truth_table.py
GREEN: make it pass
I add the function to truth_table.py
34def negate_first(first_input, second_input):
35 return not first_input
36
37
38def logical_nand(first_input, second_input):
39 return False
the test passes. logical_nand returns False, if the first input is True and the second input is True
REFACTOR: make it better
I add the second case - when the first input is True and the second input is False, in
test_binary.py69 def test_logical_nand(self): 70 self.assertFalse(src.truth_table.logical_nand(True, True)) 71 self.assertTrue(src.truth_table.logical_nand(True, False))the terminal shows AssertionError
AssertionError: False is not trueI add if statements to logical_nand in
truth_table.py38def logical_nand(first_input, second_input): 39 if first_input == True: 40 if second_input == False: 41 return True 42 return Falsethe test passes. logical_nand returns
I add another case, where the first input is False and the second input is True, to test_logical_nand in
test_binary.py69 def test_logical_nand(self): 70 self.assertFalse(src.truth_table.logical_nand(True, True)) 71 self.assertTrue(src.truth_table.logical_nand(True, False)) 72 self.assertTrue(src.truth_table.logical_nand(False, True))the terminal shows AssertionError
AssertionError: False is not trueI add if statements to logical_nand in
truth_table.py38def logical_nand(first_input, second_input): 39 if first_input == False: 40 if second_input == True: 41 return True 42 if first_input == True: 43 if second_input == False: 44 return True 45 return Falsethe test passes. logical_nand returns
I add the last case - when the first input is False and the second input is False, to test_logical_nand in
test_binary.py69 def test_logical_nand(self): 70 self.assertFalse(src.truth_table.logical_nand(True, True)) 71 self.assertTrue(src.truth_table.logical_nand(True, False)) 72 self.assertTrue(src.truth_table.logical_nand(False, True)) 73 self.assertTrue(src.truth_table.logical_nand(False, False)) 74 75 76# Exceptions seenthe terminal shows AssertionError
AssertionError: False is not trueI add an if statement to logical_nand in
truth_table.py38def logical_nand(first_input, second_input): 39 if first_input == False: 40 if second_input == False: 41 return True 42 if second_input == True: 43 return True 44 if first_input == True: 45 if second_input == False: 46 return True 47 return Falsethe test passes. logical_nand returns
I add an if statement for the one case where it returns False with an else clause for the other 3 cases
38def logical_nand(first_input, second_input): 39 if first_input == True: 40 if second_input == True: 41 return False 42 else: 43 return True 44 if first_input == False: 45 if second_input == False: 46 return True 47 if second_input == True: 48 return True 49 if first_input == True: 50 if second_input == False: 51 return True 52 return Falsethe test is still green
I remove the other statements and put the two if statements together
38def logical_nand(first_input, second_input): 39 # if first_input == True: 40 # if second_input == True: 41 if first_input == True and second_input == True: 42 return False 43 else: 44 return Truestill green
I remove the comments and use bool
38def logical_nand(first_input, second_input): 39 # if first_input == True and second_input == True: 40 if bool(first_input) == True and bool(second_input) == True: 41 return False 42 else: 43 return Truegreen
I remove the commented line and
== True38def logical_nand(first_input, second_input): 39 # if bool(first_input) == True and bool(second_input) == True: 40 if bool(first_input) and bool(second_input): 41 return False 42 else: 43 return Truestill green
I remove bool
38def logical_nand(first_input, second_input): 39 # if bool(first_input) and bool(second_input): 40 if first_input and second_input: 41 return False 42 else: 43 returnthe test is still green
I want to use one return statement (a conditional expression) for everything, which means I need an if statement that returns True. I use logical negation (not) to change the else clause to the opposite of the if statement
38def logical_nand(first_input, second_input): 39 if first_input and second_input: 40 return False 41 # else: 42 if not (first_input and second_input): 43 return Truestill green
I move the new if statement to the top
38def logical_nand(first_input, second_input): 39 if not (first_input and second_input): 40 return True 41 if first_input and second_input: 42 return Falsegreen
I change the second if statement to an else clause
38def logical_nand(first_input, second_input): 39 if not (first_input and second_input): 40 return True 41 # if first_input and second_input: 42 else: 43 return Falsegreen, green, green again 🎶
I add a conditional expression
38def logical_nand(first_input, second_input): 39 return True if not (first_input and second_input) else False 40 if not (first_input and second_input): 41 return True 42 else: 43 return Falsestill green
I remove the if statement and use the simpler form of the ternary operator
38def logical_nand(first_input, second_input): 39 return not (first_input and second_input) 40 return True if not (first_input and second_input) else Falsethe test is still green
I remove the second return statement
38def logical_nand(first_input, second_input): 39 return not (first_input and second_input)this is the opposite (Logical Negation) of logical_conjunction
I add a return statement to make sure
38def logical_nand(first_input, second_input): 39 return not logical_conjunction(first_input, second_input) 40 return not (first_input and second_input)green all the way
returns False, if the first input is True and the second input is True
returns
not (first_input and second_input)which is the opposite (Logical Negation) of the Logical Conjunction of the first input and the second input, many wordsis the opposite of Logical Conjunction which only returns True, if the first input is True and second input is True or returns
first_input and second_inputis the not of the and of the first input and second input, confusing?
Note
When there is only one if statement that returns False with an else clause
if something:
return False
else:
return True
I can change it with its logical negation (not)
if not something:
return True
else:
return False
I can then write it as a ternary operator (conditional expression)
return True if not (something) else False
which can be made simpler as
return not (something)
this means
if something: return Falseis the same asreturn not (something), just likeif something: return Trueis the same asreturn something
test_tautology
RED: make it fail
I add a test for the next Binary Operation in test_binary.py
69 def test_logical_nand(self):
70 self.assertFalse(src.truth_table.logical_nand(True, True))
71 self.assertTrue(src.truth_table.logical_nand(True, False))
72 self.assertTrue(src.truth_table.logical_nand(False, True))
73 self.assertTrue(src.truth_table.logical_nand(False, False))
74
75 def test_tautology(self):
76 self.assertTrue(src.truth_table.tautology(True, True))
77
78
79# Exceptions seen
the terminal shows AttributeError
AttributeError: module 'src.truth_table' has no attribute 'tautology'
truth_table.py does not have tautology in it
GREEN: make it pass
I add the function to truth_table.py
38def logical_nand(first_input, second_input):
39 return not logical_conjunction(first_input, second_input)
40 return not (first_input and second_input)
41
42
43def tautology(first_input, second_input):
44 return True
the test passes. tautology returns True, if the first input is True and the second input is True
REFACTOR: make it better
I add the next case, where the first input is True and the second input is False, to test_tautology in
test_binary.py75 def test_tautology(self): 76 self.assertTrue(src.truth_table.tautology(True, True)) 77 self.assertTrue(src.truth_table.tautology(True, False))the test is still green. tautology returns
I add the next case - when the first input is False and the second input is True
75 def test_tautology(self): 76 self.assertTrue(src.truth_table.tautology(True, True)) 77 self.assertTrue(src.truth_table.tautology(True, False)) 78 self.assertTrue(src.truth_table.tautology(False, True))I add the last case - when the first input is False and the second input is False
75 def test_tautology(self): 76 self.assertTrue(src.truth_table.tautology(True, True)) 77 self.assertTrue(src.truth_table.tautology(True, False)) 78 self.assertTrue(src.truth_table.tautology(False, True)) 79 self.assertTrue(src.truth_table.tautology(False, False)) 80 81 82# Exceptions seenstill green, there is only one result for this operation.
Tautology always returns True, it does not care about the inputs. It is the opposite of contradiction which always returns False
test_logical_disjunction
RED: make it fail
I add another test to test_binary.py
75 def test_tautology(self):
76 self.assertTrue(src.truth_table.tautology(True, True))
77 self.assertTrue(src.truth_table.tautology(True, False))
78 self.assertTrue(src.truth_table.tautology(False, True))
79 self.assertTrue(src.truth_table.tautology(False, False))
80
81 def test_logical_disjunction(self):
82 self.assertTrue(
83 src.truth_table.logical_disjunction(True, True)
84 )
85
86
87# Exceptions seen
the terminal shows AttributeError
AttributeError: module 'src.truth_table' has no attribute 'logical_disjunction'. Did you mean: 'logical_conjunction'?
there is no logical_disjunction in truth_table.py in the src folder, yet
GREEN: make it pass
I add the function to truth_table.py
41def tautology(first_input, second_input):
42 return True
43
44
45def logical_disjunction(first_input, second_input):
46 return True
the test passes. logical_disjunction returns True, if the first input is True and the second input is True
REFACTOR: make it better
I add the next case - when the first input is True and the second input is False, to test_logical_disjunction in
test_binary.py81 def test_logical_disjunction(self): 82 self.assertTrue( 83 src.truth_table.logical_disjunction(True, True) 84 ) 85 self.assertTrue( 86 src.truth_table.logical_disjunction(True, False) 87 )the test is still green. logical_disjunction returns
True, if the first input is True and the second input is False
True, if the first input is True and the second input is True
so far this is the same as Tautology
I add the next case - when the first input is False and the second input is True
81 def test_logical_disjunction(self): 82 self.assertTrue( 83 src.truth_table.logical_disjunction(True, True) 84 ) 85 self.assertTrue( 86 src.truth_table.logical_disjunction(True, False) 87 ) 88 self.assertTrue( 89 src.truth_table.logical_disjunction(False, True) 90 )the test is still green. logical_disjunction still looks like Tautology, it returns
I add the fourth case, where the first input is False and the second input is False
81 def test_logical_disjunction(self): 82 self.assertTrue( 83 src.truth_table.logical_disjunction(True, True) 84 ) 85 self.assertTrue( 86 src.truth_table.logical_disjunction(True, False) 87 ) 88 self.assertTrue( 89 src.truth_table.logical_disjunction(False, True) 90 ) 91 self.assertFalse( 92 src.truth_table.logical_disjunction(False, False) 93 ) 94 95 96# Exceptions seenthe terminal shows AssertionError
AssertionError: True is not falseI add if statements for the new case to logical_disjunction in
truth_table.py47def logical_disjunction(first_input, second_input): 48 if first_input == False: 49 if second_input == False: 50 return False 51 return Truethe test passes. logical_disjunction returns
I change the two if statements to one if statement with logical conjunction (and)
47def logical_disjunction(first_input, second_input): 48 # if first_input == False: 49 # if second_input == False: 50 if first_input == False and second_input == False: 51 return False 52 return Truethe test is still green
I use not to write the statements with True
47def logical_disjunction(first_input, second_input): 48 # if first_input == False and second_input == False: 49 if (not first_input == True) and (not second_input == True): 50 return False 51 return Truestill green
I use bool
47def logical_disjunction(first_input, second_input): 48 # if (not first_input == True) and (not second_input == True): 49 if ( 50 (not bool(first_input) == True) 51 and 52 (not bool(second_input) == True) 53 ): 54 return False 55 return Truegreen
I remove
== True47def logical_disjunction(first_input, second_input): 48 # if ( 49 # (not bool(first_input) == True) 50 # and 51 # (not bool(second_input) == True) 52 # ): 53 if (not bool(first_input)) and (not bool(second_input)): 54 return False 55 return Truestill green
I use a simpler if statement
47def logical_disjunction(first_input, second_input): 48 # if (not bool(first_input)) and (not bool(second_input)): 49 if (not first_input) and (not second_input): 50 return False 51 return Truehow many green bottles standing on a wall?
I add a second if statement for the opposite (logical negation) of the statement I have, like I did with Logical NAND
47def logical_disjunction(first_input, second_input): 48 if (not first_input) and (not second_input): 49 return False 50 if not ((not first_input) and (not second_input)): 51 return Truethe test is still green, that is a lot of nots
I move the new if statement to the top
47def logical_disjunction(first_input, second_input): 48 if not ((not first_input) and (not second_input)): 49 return True 50 if (not first_input) and (not second_input): 51 return Falsestill green
I change the second if statement to an else clause
47def logical_disjunction(first_input, second_input): 48 if not ((not first_input) and (not second_input)): 49 return True 50 # if (not first_input) and (not second_input): 51 else: 52 return Falsegreen
I add a conditional expression
47def logical_disjunction(first_input, second_input): 48 return True if not ( 49 (not first_input) and (not second_input) 50 ) else False 51 if not ((not first_input) and (not second_input)): 52 return True 53 else: 54 return Falsegreen again 🎶
I make the return statement simpler
47def logical_disjunction(first_input, second_input): 48 return not ((not first_input) and (not second_input)) 49 return True if not ( 50 (not first_input) and (not second_input) 51 ) else Falsethe test is still green. A reminder that I can return the Logical Negation (not) of an if statement that returns False like I did with Logical NAND
Note
return not ((not first_input) and (not second_input))returns the opposite (Logical Negation) of the Logical Conjunction of the Logical Negation offirst_input, and the Logical Negation ofsecond_input. This means that in the 4 casesif the first input is True and the second input is True, logical_disjunction returns
not ((not first_input) and (not second_input)) not ((not True) and (not True)) not (False and False) not False Trueif the first input is True and the second input is False, logical_disjunction returns
not ((not first_input) and (not second_input)) not ((not True) and (not False)) not (False and True) not False Trueif the first input is False and the second input is True, logical_disjunction returns
not ((not first_input) and (not second_input)) not ((not False) and (not True)) not (True and False) not False Trueif the first input is False and the second input is False, logical_disjunction returns
not ((not first_input) and (not second_input)) not ((not False) and (not False)) not (True and True) not True False
“not” appears 3 times in this statement, I want to change that. I “multiply” it by each thing inside the parentheses to try to make the statement simpler
47def logical_disjunction(first_input, second_input): 48 return (not not first_input) (not and) (not not second_input) 49 return not ((not first_input) and (not second_input))the terminal shows SyntaxError
SyntaxError: invalid syntaxI add SyntaxError to the list of Exceptions seen in
test_binary.py97# Exceptions seen 98# AttributeError 99# TypeError 100# AssertionError 101# SyntaxErrorI fix the failing line by changing “not and” to “or” in
truth_table.py47def logical_disjunction(first_input, second_input): 48 return (not not first_input) or (not not second_input) 49 return not ((not first_input) and (not second_input))the test passes
I remove
not notfrom the return statement because it cancels out47def logical_disjunction(first_input, second_input): 48 return first_input or second_input 49 return (not not first_input) or (not not second_input)the test is still green. Do two nots make a right?
I remove the second return statement
47def logical_disjunction(first_input, second_input): 48 return first_input or second_inputgreen everywhere
Logical Disjunction also known as “or” returns
close the project
I close
test_binary.pyandtruth_table.pyin the editorI click in the terminal, 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
truth_tablecd ..the terminal shows
.../pumping_pythonI am back in the
pumping_pythondirectory
review
Binary Operations take 2 inputs, each input can be True or False, if the first input is named first_input and the second input is named second_input, the tests show that
-
returns
first_input or second_inputreturns False only if
first_inputis False andsecond_inputis Falseis the opposite (Logical Negation) of Logical NOR which returns True only if
first_inputis False andsecond_inputis False
-
always returns True
never returns False
is the opposite (Logical Negation) of contradiction which always returns False
-
returns
not (first_input and second_input)returns False only if
first_inputis True andsecond_inputis Trueis the opposite (Logical Negation) (not) of Logical Conjunction (and) which returns True only if
first_inputis True andsecond_inputis True
-
always returns
not first_inputis the opposite (Logical Negation) of Project First which returns True only if
first_inputis True
-
returns
not first_input and second_inputreturns True only if
first_inputis False andsecond_inputis Trueis the opposite (Logical Negation) of Converse Implication which returns False if
first_inputis False andsecond_inputis True
-
always returns
second_inputis the opposite (Logical Negation) of Negate Second which returns True only if
second_inputis False
Logical Conjunction returns
returns
first_input and second_inputreturns True only if
first_inputis True andsecond_inputis Trueis the opposite (Logical Negation) of Logical NAND which returns False only if
first_inputis True andsecond_inputis True
-
always returns False
never returns True
is the opposite (Logical Negation) of Tautology which always returns True
and
All the logic statements or conditions have been written with some or all of these 3.
code from the chapter
Do you want to see all the CODE I typed for the Truth Table?
what is next?
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