truth table: Binary Operations part 2
requirements
how to get back to the automated tests
If your tests stopped after the previous chapter, heres’s how to get back to the tests
Make sure you are in the
pumping_pythonfolder with pwd in the terminalpwdif the terminal shows anything other than
.../pumping_pythonyou need to change directory to the
pumping_pythonfolderOnce in the
pumping_pythondirectory, change directory to the projectcd truth_tablethe terminal shows
.../pumping_python/truth_tableactivate the Virtual Environment
source .venv/bin/activateon Windows without Windows Subsystem for Linux use
.venv/scripts/activate.ps1instead ofsource .venv/bin/activate.venv/scripts/activate.ps1when the Virtual Environment is activated, the terminal shows
(.venv) .../pumping_python/truth_tablerun the tests
pytest-watch
test_negate_first
RED: make it fail
I add a test to the TestBinaryOperations class in test_truth_table.py for negate_first
49 self.assertFalse(src.truth_table.converse_non_implication(False, False))
50
51 def test_negate_first(self):
52 self.assertFalse(src.truth_table.negate_first(True, True))
53
54
55# 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 definition in truth_table.py
29def converse_non_implication(first_input, second_input):
30 return not first_input and second_input
31
32
33def negate_first(first_input, second_input):
34 return False
the test passes. negate_first returns False when the first and second inputs are both True
REFACTOR: make it better
I add the second case - where the first input is True and the second input is False, to
test_negate_firstintest_truth_table.py51 def test_negate_first(self): 52 self.assertFalse(src.truth_table.negate_first(True, True)) 53 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
51 def test_negate_first(self): 52 self.assertFalse(src.truth_table.negate_first(True, True)) 53 self.assertFalse(src.truth_table.negate_first(True, False)) 54 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.py33def negate_first(first_input, second_input): 34 if first_input == False: 35 if second_input == True: 36 return True 37 return Falsethe test passes
this is the same as the first if statement in converse_non_implication. I change the two if statements to one if statement with Logical Conjunction (and)
33def negate_first(first_input, second_input): 34 if first_input == False and second_input == True: 35 # if first_input == False: 36 # if second_input == True: 37 return True 38 return Falsethe test is still green
I remove the commented lines and move the first return statement to the left
33def negate_first(first_input, second_input): 34 if first_input == False and second_input == True: 35 return True 36 return Falsenegate_firstreturnsI add the last case - when the first and second inputs are both False, to
test_negate_firstintest_truth_table.py51 def test_negate_first(self): 52 self.assertFalse(src.truth_table.negate_first(True, True)) 53 self.assertFalse(src.truth_table.negate_first(True, False)) 54 self.assertTrue(src.truth_table.negate_first(False, True)) 55 self.assertTrue(src.truth_table.negate_first(False, False)) 56 57 58# Exceptions seenthe terminal shows AssertionError
AssertionError: False is not trueI add if statements for this case to the
negate_firstfunction intruth_table.py33def negate_first(first_input, second_input): 34 if first_input == False: 35 if second_input == False: 36 return True 37 if first_input == False and second_input == True: 38 return True 39 return Falsethe test passes
I change the two if statements to one if statement with and
33def negate_first(first_input, second_input): 34 if first_input == False and second_input == False: 35 # if first_input == False: 36 # if second_input == False: 37 return True 38 if first_input == False and second_input == True: 39 return True 40 return Falsethe test is still green
I remove the commented lines and move the new return statement to the left
33def negate_first(first_input, second_input): 34 if first_input == False and second_input == False: 35 return True 36 if first_input == False and second_input == True: 37 return True 38 return Falsenegate_firstreturnssince the 2 cases where the
negate_firstfunction returns True are when the first input is False. I can write it as an if statement with an else clause33def negate_first(first_input, second_input): 34 if first_input == False: 35 return True 36 else: 37 return False 38 if first_input == False and second_input == False: 39 return True 40 if first_input == False and second_input == True: 41 return True 42 return Falsethe test is still green
I remove the other if statement then use logical_negation (not) to write the first if statement in terms of True
33def negate_first(first_input, second_input): 34 if not first_input == True: 35 # if first_input == False: 36 return True 37 else: 38 return Falsethe test is still passing
I remove the commented line and use bool with the if statement
33def negate_first(first_input, second_input): 34 if not bool(first_input): 35 # if not first_input == True: 36 return True 37 else: 38 return Falsestill green
I remove the commented line and make the if statement simpler
33def negate_first(first_input, second_input): 34 if not first_input: 35 # if not bool(first_input): 36 return True 37 else: 38 return Falsethe test is still green
I remove the commented line then add a ternary operator (conditional expression)
33def negate_first(first_input, second_input): 34 return True if not first_input else False 35 if not first_input: 36 return True 37 else: 38 return Falsestill green
I remove the if statement and else clause, then use the simpler form of the return statement
33def negate_first(first_input, second_input): 34 return not first_input 35 return True if not first_input else Falsethe test is still green
I remove the second return statement
33def negate_first(first_input, second_input): 34 return not first_input
Negate First negates the first input, it always returns
not first_inputthe Logical Negation of the first input
the opposite of the first input
test_logical_nand
RED: make it fail
I add a new test to test_truth_table.py
55 self.assertTrue(src.truth_table.negate_first(False, False))
56
57 def test_logical_nand(self):
58 self.assertFalse(src.truth_table.logical_nand(True, True))
59
60
61# 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 a definition for the function to truth_table.py
33def negate_first(first_input, second_input):
34 return not first_input
35
36
37def logical_nand(first_input, second_input):
38 return False
the test passes.
logical_nand returns False when the first and second inputs are both True
REFACTOR: make it better
I add the second case - where the first input is True and the second input is False, to
test_logical_nandintest_truth_table.py57 def test_logical_nand(self): 58 self.assertFalse(src.truth_table.logical_nand(True, True)) 59 self.assertTrue(src.truth_table.logical_nand(True, False))the terminal shows AssertionError
AssertionError: False is not trueI add if statements to the
logical_nandfunction intruth_table.py37def logical_nand(first_input, second_input): 38 if first_input == True: 39 if second_input == False: 40 return True 41 return Falsethe test passes
I comment out the two if statements, and change them to one if statement
37def logical_nand(first_input, second_input): 38 if first_input == True and second_input == False: 39 # if first_input == True: 40 # if second_input == False: 41 return True 42 return Falsethe test is still green
I remove the commented lines, and move the first return statement to the left
37def logical_nand(first_input, second_input): 38 if first_input == True and second_input == False: 39 return True 40 return Falsethe terminal still shows green. the
logical_nandfunction returnsI add another case, where the first input is False and the second input is True, to
test_logical_nandintest_truth_table.py57 def test_logical_nand(self): 58 self.assertFalse(src.truth_table.logical_nand(True, True)) 59 self.assertTrue(src.truth_table.logical_nand(True, False)) 60 self.assertTrue(src.truth_table.logical_nand(False, True))the terminal shows AssertionError
AssertionError: False is not trueI add two if statements to
logical_nandintruth_table.py37def logical_nand(first_input, second_input): 38 if first_input == False: 39 if second_input == True: 40 return True 41 if first_input == True and second_input == False: 42 return True 43 return Falsethe test passes
I change the two if statements to one if statement with logical_conjunction (and)
37def logical_nand(first_input, second_input): 38 if first_input == False and second_input == True: 39 # if first_input == False: 40 # if second_input == True: 41 return True 42 if first_input == True and second_input == False: 43 return True 44 return Falsethe test is still green
I remove the commented lines and move the new return statement to the left
37def logical_nand(first_input, second_input): 38 if first_input == False and second_input == True: 39 return True 40 if first_input == True and second_input == False: 41 return True 42 return Falsestill green.
logical_nandreturnsI add the last case - where the first and second inputs are both False, to
test_logical_nandintest_truth_table.py57 def test_logical_nand(self): 58 self.assertFalse(src.truth_table.logical_nand(True, True)) 59 self.assertTrue(src.truth_table.logical_nand(True, False)) 60 self.assertTrue(src.truth_table.logical_nand(False, True)) 61 self.assertTrue(src.truth_table.logical_nand(False, False)) 62 63 64# Exceptions seenthe terminal shows AssertionError
AssertionError: False is not trueI add two if statements to
logical_nandintruth_table.py37def logical_nand(first_input, second_input): 38 if first_input == False: 39 if second_input == False: 40 return True 41 if first_input == False and second_input == True: 42 return True 43 if first_input == True and second_input == False: 44 return True 45 return Falsethe test passes
I change the two if statements to one if statement
37def logical_nand(first_input, second_input): 38 if first_input == False and second_input == False: 39 # if first_input == False: 40 # if second_input == False: 41 return True 42 if first_input == False and second_input == True: 43 return True 44 if first_input == True and second_input == False: 45 return True 46 return Falsethe test is still green
I remove the comments and move the new return statement to the left
37def logical_nand(first_input, second_input): 38 if first_input == False and second_input == False: 39 return True 40 if first_input == False and second_input == True: 41 return True 42 if first_input == True and second_input == False: 43 return True 44 return Falsethe terminal still shows green.
logical_nandreturnsI add one if statement for the one case that returns False with an else clause for the other three cases since they all return True
37def logical_nand(first_input, second_input): 38 if first_input == True and second_input == True: 39 return False 40 else: 41 return True 42 if first_input == False and second_input == False: 43 return True 44 if first_input == False and second_input == True: 45 return True 46 if first_input == True and second_input == False: 47 return True 48 return Falsethe test is still green
I remove the other if statement and use bool to change the new if statement
37def logical_nand(first_input, second_input): 38 if bool(first_input) and bool(second_input): 39 # if first_input == True and second_input == True: 40 return False 41 else: 42 return Truethe terminal still shows green
I remove the commented line and use the simpler if statement that checks if the inputs are True behind the scenes
37def logical_nand(first_input, second_input): 38 if first_input and second_input: 39 # if bool(first_input) and bool(second_input): 40 return False 41 else: 42 return Truestill 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
37def logical_nand(first_input, second_input): 38 if first_input and second_input: 39 return False 40 if not (first_input and second_input): 41 # else: 42 return Truethe test is still green
I remove the commented line and move the new if statement to the top
37def logical_nand(first_input, second_input): 38 if not (first_input and second_input): 39 return True 40 if first_input and second_input: 41 return Falsethe terminal still shows green
I change the second if statement to an else clause
37def logical_nand(first_input, second_input): 38 if not (first_input and second_input): 39 return True 40 else: 41 # if first_input and second_input: 42 return Falsegreen, green, green again 🎶
I remove the comment, then add a conditional expression
37def logical_nand(first_input, second_input): 38 return True if not (first_input and second_input) else False 39 if not (first_input and second_input): 40 return True 41 else: 42 return Falsestill green
I remove the if statement and use the simpler form of the ternary operator
37def logical_nand(first_input, second_input): 38 return not (first_input and second_input) 39 return True if not (first_input and second_input) else Falsethe test is still passing
I remove the second return statement
37def logical_nand(first_input, second_input): 38 return not (first_input and second_input)
returns False only when the first input and second input are both True
returns
not (first_input and second_input)which is the Logical Negation of the Logical Conjunction of the first input and the second input, many wordsis the not of the and of the first input and second input, confusing?
it is the opposite of Logical Conjunction which only returns True when the first input and second input are both True or returns
first_input and second_input
Tip
When there is only one if statement that returns False with an else clause, for example
if condition:
return False
else:
return True
I can rewrite it in terms of True with its logical negation with not
if not condition:
return True
else:
return False
I can then write it as a ternary operator (conditional expression)
return True if not (condition) else False
which can be made simpler as
return not (condition)
test_tautology
RED: make it fail
I add a test for the next Binary Operation in test_truth_table.py with the first case where the two inputs are True
61 self.assertTrue(src.truth_table.logical_nand(False, False))
62
63 def test_tautology(self):
64 self.assertTrue(src.truth_table.tautology(True, True))
65
66
67# Exceptions seen
the terminal shows AttributeError
AttributeError: module 'src.truth_table' has no attribute 'tautology'
truth_table.py does not have tautology defined inside it
GREEN: make it pass
I add a function definition in truth_table.py
37def logical_nand(first_input, second_input):
38 return not (first_input and second_input)
39
40
41def tautology(first_input, second_input):
42 return True
the test passes. tatutology returns True when the two inputs are True
REFACTOR: make it better
I add the next case to
test_tautologyintest_truth_table.py- whenfirst_inputis True andsecond_inputis False63 def test_tautology(self): 64 self.assertTrue(src.truth_table.tautology(True, True)) 65 self.assertTrue(src.truth_table.tautology(True, False))the terminal still shows green.
tautologyreturnsI add the next case - when the first input is False and the second input is True
63 def test_tautology(self): 64 self.assertTrue(src.truth_table.tautology(True, True)) 65 self.assertTrue(src.truth_table.tautology(True, False)) 66 self.assertTrue(src.truth_table.tautology(False, True))the test is still green.
tautologyreturns TrueI add the last case - when the two inputs are False
63 def test_tautology(self): 64 self.assertTrue(src.truth_table.tautology(True, True)) 65 self.assertTrue(src.truth_table.tautology(True, False)) 66 self.assertTrue(src.truth_table.tautology(False, True)) 67 self.assertTrue(src.truth_table.tautology(False, False)) 68 69 70# Exceptions seenstill green, there is only one result for this operation.
It always returns True, it is the opposite of Contradiction which always returns False
test_logical_disjunction
RED: make it fail
I add another test to test_truth_table.py with the first case, where the two inputs are True
67 self.assertTrue(src.truth_table.tautology(False, False))
68
69 def test_logical_disjunction(self):
70 self.assertTrue(src.truth_table.logical_disjunction(True, True))
71
72
73# Exceptions seen
the terminal shows AttributeError
AttributeError: module 'src.truth_table' has no attribute 'logical_disjunction'. Did you mean: 'logical_conjunction'?
there is no definition for 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 when the two inputs are True
REFACTOR: make it better
I add the next case - when
first_inputis True andsecond_inputis False, totest_logical_disjunctionintest_truth_table.py69 def test_logical_disjunction(self): 70 self.assertTrue(src.truth_table.logical_disjunction(True, True)) 71 self.assertTrue(src.truth_table.logical_disjunction(True, False))the terminal still shows green.
logical_disjunctionreturnsso far this is the same as Tautology
I add the next case - where the first input is False and the second input is True
69 def test_logical_disjunction(self): 70 self.assertTrue(src.truth_table.logical_disjunction(True, True)) 71 self.assertTrue(src.truth_table.logical_disjunction(True, False)) 72 self.assertTrue(src.truth_table.logical_disjunction(False, True))the test is still green.
logical_disjunctionstill looks like Tautology, it returnsI add the fourth case, where the two inputs are False
69 def test_logical_disjunction(self): 70 self.assertTrue(src.truth_table.logical_disjunction(True, True)) 71 self.assertTrue(src.truth_table.logical_disjunction(True, False)) 72 self.assertTrue(src.truth_table.logical_disjunction(False, True)) 73 self.assertFalse(src.truth_table.logical_disjunction(False, False)) 74 75 76# Exceptions seenthe terminal shows AssertionError
AssertionError: True is not falseI add if statements for the new case to
logical_disjunctionintruth_table.py45def logical_disjunction(first_input, second_input): 46 if first_input == False: 47 if second_input == False: 48 return False 49 return Truethe test passes.
logical_disjunctionreturnsI change the two if statements to one if statement with and
45def logical_disjunction(first_input, second_input): 46 if first_input == False and second_input == False: 47 # if first_input == False: 48 # if second_input == False: 49 return False 50 return Truethe test is still green
I remove the commented line and move the first return statement to the left
45def logical_disjunction(first_input, second_input): 46 if first_input == False and second_input == False: 47 return False 48 return Truestill green
I use not to write the statements in terms of True
45def logical_disjunction(first_input, second_input): 46 if (not first_input == True) and (not second_input == True): 47 # if first_input == False and second_input == False: 48 return False 49 return Truethe terminal still shows green
I use bool to make the if statement simpler
45def logical_disjunction(first_input, second_input): 46 if (not bool(first_input)) and (not bool(second_input)): 47 # if (not first_input == True) and (not second_input == True): 48 return False 49 return Truethe terminal shows green
I use a simpler if statement
45def logical_disjunction(first_input, second_input): 46 if (not first_input) and (not second_input): 47 # if (not bool(first_input)) and (not bool(second_input)): 48 return False 49 return Truehow many green bottles standing on a wall?
I add a second if statement for the cases where
logical_disjunctionreturns True like I did with Logical NAND45def logical_disjunction(first_input, second_input): 46 if (not first_input) and (not second_input): 47 return False 48 if not ((not first_input) and (not second_input)): 49 return Truethe test is still green
I move the new if statement to the top
45def logical_disjunction(first_input, second_input): 46 if not ((not first_input) and (not second_input)): 47 return True 48 if (not first_input) and (not second_input): 49 return Falsegreen
I change the second if statement to an else clause
45def logical_disjunction(first_input, second_input): 46 if not ((not first_input) and (not second_input)): 47 return True 48 else: 49 # if (not first_input) and (not second_input): 50 return FalseI add a conditional expression
45def logical_disjunction(first_input, second_input): 46 return True if not ((not first_input) and (not second_input)) else False 47 if not ((not first_input) and (not second_input)): 48 return True 49 else: 50 return FalseI make the return statement simpler
45def logical_disjunction(first_input, second_input): 46 return not ((not first_input) and (not second_input)) 47 return True if not ((not first_input) and (not second_input)) else Falsethe terminal still shows green. A reminder that I can return the Logical Negation (not) of an if statement that returns False like I did with Logical NAND
“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
45def logical_disjunction(first_input, second_input): 46 return (not not first_input) (not and) (not not second_input) 47 return not ((not first_input) and (not second_input))the terminal shows SyntaxError
SyntaxError: invalid syntaxI add it to the list of Exceptions seen in
test_truth_table.py76# Exceptions seen 77# AssertionError 78# AttributeError 79# TypeError 80# SyntaxErrorI fix the failing line by changing “not and” to “or” in
truth_table.py45def logical_disjunction(first_input, second_input): 46 return (not not first_input) or (not not second_input) 47 return not ((not first_input) and (not second_input))the test passes
I remove “not not” from the return statement because it cancels out
45def logical_disjunction(first_input, second_input): 46 return first_input or second_input 47 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
45def logical_disjunction(first_input, second_input): 46 return first_input or second_inputgreen everywhere
Logical Disjunction aka or returns
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 when
first_inputandsecond_inputare both Falseis the opposite or Logical Negation of Logical NOR which only returns True when the two inputs are False
-
always returns True
is the opposite or Logical Negation of Contradiction which always returns False
-
returns
not (first_input and second_input)returns False when
first_inputandsecond_inputare both Trueis the opposite or Logical Negation (not) of Logical Conjunction (and) which only returns True when the two inputs are True
-
returns
not first_inputis the opposite or Logical Negation of Project First which only returns True when
first_inputis True
-
returns
not first_input and second_inputreturns True when
first_inputis False andsecond_inputis Trueis the opposite or Logical Negation of Converse Implication which only returns False when
first_inputis False andsecond_inputis True
-
returns
second_inputis the opposite or Logical Negation of Negate Second which only returns True when
second_inputis False
Logical Conjunction returns
returns
first_input and second_inputis the opposite or Logical Negation of Logical NAND which only returns False when the two inputs are True
and
Logical Disjunction is “or”
Logical Conjunction is “and”
Logical Negation is “not”
All the logic statements or conditions have been written with some or all of the above 3.
code from the chapter
Do you want to see all the CODE I typed for the Truth Table?