truth table: Binary Operations 1
preview
These are the tests I have at the end of the chapter
1import src.truth_table
2import unittest
3
4
5class TestBinaryOperations(unittest.TestCase):
6
7 def test_contradiction(self):
8 contradiction = src.truth_table.contradiction
9 self.assertFalse(contradiction(True, True))
10 self.assertFalse(contradiction(True, False))
11 self.assertFalse(contradiction(False, True))
12 self.assertFalse(contradiction(False, False))
13
14 def test_logical_conjunction(self):
15 logical_conjunction = (
16 src.truth_table.logical_conjunction
17 )
18 self.assertTrue(
19 logical_conjunction(True, True)
20 )
21 self.assertFalse(
22 logical_conjunction(True, False)
23 )
24 self.assertFalse(
25 logical_conjunction(False, True)
26 )
27 self.assertFalse(
28 logical_conjunction(False, False)
29 )
30
31 def test_project_second(self):
32 project_second = src.truth_table.project_second
33 self.assertTrue(project_second(True, True))
34 self.assertFalse(project_second(True, False))
35 self.assertTrue(project_second(False, True))
36 self.assertFalse(project_second(False, False))
37
38 def test_converse_non_implication(self):
39 converse_non_implication = (
40 src.truth_table.converse_non_implication
41 )
42 self.assertFalse(
43 converse_non_implication(True, True)
44 )
45 self.assertFalse(
46 converse_non_implication(True, False)
47 )
48 self.assertTrue(
49 converse_non_implication(False, True)
50 )
51 self.assertFalse(
52 converse_non_implication(False, False)
53 )
54
55
56# Exceptions seen
57# AttributeError
58# TypeError
59# AssertionError
questions about Binary Operations 1
Questions to think about as I go through the chapter
requirements
continue the project
Make sure you are in the
pumping_pythonfolder with pwd in the terminalpwdif the terminal does not show
.../pumping_pythonchange directory to the
pumping_pythonfolderOnce in
pumping_python, change directory to the projectcd truth_tablethe terminal shows
.../pumping_python/truth_tableI make a new Python file for the tests in the
testsdirectorytouch tests/test_binary.pyNew-Item tests/test_binary.pythe terminal goes back to the command line.
I open
test_binary.pyI add
test_binary.pyto git for trackinggit add .I run the tests with pytest-watcher
uv run pytest-watcher . --nowthe terminal is my friend, and shows
rootdir: .../pumping_python/truth_table configfile: pyproject.toml collected 4 items tests/test_nullary_unary.py .... [100%] ================== 4 passed in G.HIs ===================
test_contradiction
The truth table for contradiction is
first input |
second input |
return |
|---|---|---|
True |
True |
False |
True |
False |
False |
False |
True |
False |
False |
False |
False |
RED: make it fail
I add a test for contradiction with an assertion for when the first input is True and the second input is True, in
test_binary.pyfirst input
second input
return
True
True
False
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 12 13# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.truth_table' has no attribute 'contradiction'because I have not defined contradiction in
truth_table.pyI add AttributeError to the list of Exceptions seen
13# Exceptions seen 14# AttributeError
GREEN: make it pass
I open
truth_table.pyI add the function to
truth_table.py13def logical_negation(the_input): 14 return not the_input 15 16 17def contradiction(): 18 return Nonethe terminal is my friend, and shows TypeError
TypeError: contradiction() takes 0 positional arguments but 2 were givenbecause the test called the contradiction function with two arguments (True and True) and the definition does not allow any arguments (the parentheses are empty).
I add TypeError to the list of Exceptions seen
13# Exceptions seen 14# AttributeError 15# TypeErrorI add
first_inputas the name of the first argument in the function signature for contradiction, intruth_table.py17# def contradiction(): 18def contradiction(first_input): 19 return Nonethe terminal is my friend, and shows TypeError
TypeError: contradiction() takes 1 positional argument but 2 were givenbecause the test called the contradiction function with two arguments (True and True) and I just changed the definition to only allow calls with one argument.
I add
second_inputas the name of the second input in parentheses17# def contradiction(): 18# def contradiction(first_input): 19def contradiction(first_input, second_input): 20 return Nonethe test passes because None is grouped as False (the result of
bool(None)is False) and the assertion expects False
REFACTOR: make it better
I change the return statement to make it clearer
17# def contradiction(): 18# def contradiction(first_input): 19def contradiction(first_input, second_input): 20 # return None 21 return Falsethe test is still green. contradiction returns False, if the first input is True and the second input is True
I remove the commented lines
13def logical_negation(the_input): 14 return not the_input 15 16 17def contradiction(first_input, second_input): 18 return FalseI add an assertion for the second case, which is when the first input is True and the second input is False, to
test_binary.pyfirst input
second input
return
True
False
False
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 15 16# Exceptions seenthe test is still green. contradiction returns False
if the first input is True and the second input is False
if the first input is True and the second input is True
if the first input is True
I add an assertion for the third case, which is when the first input is False and the second input is True
first input
second input
return
False
True
False
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 18 19# Exceptions seenthe test is still green. contradiction returns False
if the first input is False and the second input is True
if the first input is True
I add an assertion for the fourth case, which is when the first input is False and the second input is False
first input
second input
return
False
False
False
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 22# Exceptions seenthe test is still green. contradiction returns False
if the first input is False
if the first input is True
I add a variable for
src.truth_table.contradiction7 def test_contradiction(self): 8 contradiction = src.truth_table.contradiction 9 self.assertFalse( 10 src.truth_table.contradiction(True, True) 11 ) 12 self.assertFalse( 13 src.truth_table.contradiction(True, False) 14 ) 15 self.assertFalse( 16 src.truth_table.contradiction(False, True) 17 ) 18 self.assertFalse( 19 src.truth_table.contradiction(False, False) 20 ) 21 22 23# Exceptions seenI use the variable to remove repetition of
src.truth_table.contradiction7 def test_contradiction(self): 8 contradiction = src.truth_table.contradiction 9 self.assertFalse( 10 # src.truth_table.contradiction(True, True) 11 contradiction(True, True) 12 ) 13 self.assertFalse( 14 # src.truth_table.contradiction(True, False) 15 contradiction(True, False) 16 ) 17 self.assertFalse( 18 # src.truth_table.contradiction(False, True) 19 contradiction(False, True) 20 ) 21 self.assertFalse( 22 # src.truth_table.contradiction(False, False) 23 contradiction(False, False) 24 ) 25 26 27# Exceptions seenthe test is still green.
I remove the commented lines
7 def test_contradiction(self): 8 contradiction = src.truth_table.contradiction 9 self.assertFalse(contradiction(True, True)) 10 self.assertFalse(contradiction(True, False)) 11 self.assertFalse(contradiction(False, True)) 12 self.assertFalse(contradiction(False, False)) 13 14 15# Exceptions seenI add a git commit message in the other terminal
git commit -am 'add contradiction'
contradiction always returns False, it does not care about the inputs
examples of Contradiction
A broken light switch, if the inputs are
is the switch on?
is there electricity?
If the switch is broken, the inputs do not matter
switch
electricity
bulb
on
on
off
on
off
off
off
on
off
off
off
off
A rule that does not allow watching TV, if the inputs are
is homework done?
is the room clean?
homework done
clean room
can watch TV
yes
yes
no
yes
no
no
no
yes
no
no
no
no
A rule about loaning money to friends, if the inputs are
person can be trusted?
is a small amount?
trusted person
small amount
loan money to friend
yes
yes
no
yes
no
no
no
yes
no
no
no
no
Do not disturb, if the inputs are
is the person in favorites list?
is it during allowed hours?
favorites
allowed hours
allow to ring
yes
yes
no
yes
no
no
no
yes
no
no
no
no
Broken Multi Factor Authentication to log in, if the inputs are
did the user provide the right password?
did the user provide the right MFA code?
right password
right MFA code
log in
yes
yes
no
yes
no
no
no
yes
no
no
no
no
test_logical_conjunction
The truth table for logical_conjunction is
first input |
second input |
return |
|---|---|---|
True |
True |
True |
True |
False |
False |
False |
True |
False |
False |
False |
False |
RED: make it fail
I go back to the terminal where the tests are running
I add a test for logical_conjunction with an assertion for the first case, which is when the first input is True and the second input is True, in
test_binary.pyfirst input
second input
return
True
True
True
7 def test_contradiction(self): 8 contradiction = src.truth_table.contradiction 9 self.assertFalse(contradiction(True, True)) 10 self.assertFalse(contradiction(True, False)) 11 self.assertFalse(contradiction(False, True)) 12 self.assertFalse(contradiction(False, False)) 13 14 def test_logical_conjunction(self): 15 self.assertTrue( 16 src.truth_table.logical_conjunction( 17 True, True 18 ) 19 ) 20 21 22# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.truth_table' has no attribute 'logical_conjunction'. Did you mean: 'logical_negation'?because there is nothing named logical_conjunction in
truth_table.py
GREEN: make it pass
I add the function to truth_table.py
17def contradiction(first_input, second_input):
18 return False
19
20
21def logical_conjunction(first_input, second_input):
22 return True
the test passes. logical_conjunction returns True, if the first input is True and the second input is True.
REFACTOR: make it better
I add an assertion for the next case, which is when the first input is True and the second input is False, to test_logical_conjunction in
test_binary.pyfirst input
second input
return
True
False
False
14 def test_logical_conjunction(self): 15 self.assertTrue( 16 src.truth_table.logical_conjunction( 17 True, True 18 ) 19 ) 20 self.assertFalse( 21 src.truth_table.logical_conjunction( 22 True, False 23 ) 24 ) 25 26 27# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: True is not falsebecause the function returns True and the assertion expects False.
I add AssertionError to the list of Exceptions
27# Exceptions seen 28# AttributeError 29# TypeError 30# AssertionErrorI make the logical_conjunction function in
truth_table.pyreturn False21def logical_conjunction(first_input, second_input): 22 # return True 23 return Falsethe terminal is my friend, and shows AssertionError
AssertionError: False is not truebecause the function now returns False and the assertion before this one, expects True.
logical_conjunction has to make a choice. It should return
False, 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
the second input in these 2 cases
I change the return statement of the logical_conjunction function in
truth_table.py21def logical_conjunction(first_input, second_input): 22 # return False 23 # return True 24 return second_inputthe test passes. logical_conjunction returns
False, if the second input is False
True, if the second input is True
I add an assertion for the third case, which is when the first input is False and the second input is True, to test_logical_conjunction in
test_binary.pyfirst input
second input
return
False
True
False
14 def test_logical_conjunction(self): 15 self.assertTrue( 16 src.truth_table.logical_conjunction( 17 True, True 18 ) 19 ) 20 self.assertFalse( 21 src.truth_table.logical_conjunction( 22 True, False 23 ) 24 ) 25 self.assertFalse( 26 src.truth_table.logical_conjunction( 27 False, True 28 ) 29 ) 30 31 32# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: True is not falsebecause my solution does not work for this case. The function returns True and the assertion expects False. The logical_conjunction function has to make a choice, it should return
False, if the first input is False and the second input is True
False, 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
I can use if statements to make it choose what to do based on the inputs.
if statements
An if statement is a way for a program to choose what to do based on something else. I can use if statements to make a function choose between two things. They are written this way in Python
if something:
then do this
I add an if statement for when the first input is False to the logical_conjunction function in
truth_table.py21def logical_conjunction(first_input, second_input): 22 # return False 23 # return True 24 if first_input == False: 25 return False 26 return second_inputthe test passes. logical_conjunction returns
False, if the first input is False
the second input if the above condition is NOT met
because this happens when
if first_input == False:runs, Python checks iffirst_inputis equal to Falseif
first_inputis NOT equal to False, it leaves the if statement and continues to run the rest of the function -return second_input, which returns the value ofsecond_inputas the output, then leaves the function since the return statement is the last thing to run in a functionif
first_inputis equal to False, it goes to the next line -return Falseand leaves the function since the return statement is the last thing to run in a function
I add an assertion for the last case, which is when the first input is False and the second input is False, to test_logical_conjunction in
test_binary.pyfirst input
second input
return
False
False
False
14 def test_logical_conjunction(self): 15 self.assertTrue( 16 src.truth_table.logical_conjunction( 17 True, True 18 ) 19 ) 20 self.assertFalse( 21 src.truth_table.logical_conjunction( 22 True, False 23 ) 24 ) 25 self.assertFalse( 26 src.truth_table.logical_conjunction( 27 False, True 28 ) 29 ) 30 self.assertFalse( 31 src.truth_table.logical_conjunction( 32 False, False 33 ) 34 ) 35 36 37# Exceptions seenthe test is still green.
There is only one case where logical_conjunction returns True, I add an if statement for it in
truth_table.py21def logical_conjunction(first_input, second_input): 22 # return False 23 # return True 24 # if first_input == False: 25 # return False 26 # return second_input 27 if first_input == True: 28 if second_input == True: 29 return Truethe test is still green, because the function returns
True when the conditions are met
None when the conditions are NOT met, because all functions return None by default, as if they have an invisible line that says return None
I add a return statement to make it clearer
21def logical_conjunction(first_input, second_input): 22 # return False 23 # return True 24 # if first_input == False: 25 # return False 26 # return second_input 27 if first_input == True: 28 if second_input == True: 29 return True 30 return Nonestill green, because None is grouped as False.
I change None to False in the return statement, to make it clearer
21def logical_conjunction(first_input, second_input): 22 # return False 23 # return True 24 # if first_input == False: 25 # return False 26 # return second_input 27 if first_input == True: 28 if second_input == True: 29 return True 30 # return None 31 return Falsegreen.
I add bool to the if statements
21def logical_conjunction(first_input, second_input): 22 # return False 23 # return True 24 # if first_input == False: 25 # return False 26 # return second_input 27 # if first_input == True: 28 if bool(first_input) == True: 29 # if second_input == True: 30 if bool(second_input) == True: 31 return True 32 # return None 33 return Falsestill green because
bool(something)returns True if the object in parentheses is grouped as True.Since
bool(True)is the same as True,bool(first_input) == Trueis the same thing asTrue == Truewhenfirst_inputis True, which is a repetition. I remove== Truefrom the if statements21def logical_conjunction(first_input, second_input): 22 # return False 23 # return True 24 # if first_input == False: 25 # return False 26 # return second_input 27 # if first_input == True: 28 # if bool(first_input) == True: 29 if bool(first_input): 30 # if second_input == True: 31 # if bool(second_input) == True: 32 if bool(second_input): 33 return True 34 # return None 35 return Falsethe test is still green because
if bool(something)checks ifbool(something)returns Trueif bool(something) == Trueis the same asif bool(something)if the result of
bool(something)is True thenif bool(something)is the same thing asif True
I can remove bool
21def logical_conjunction(first_input, second_input): 22 # return False 23 # return True 24 # if first_input == False: 25 # return False 26 # return second_input 27 # if first_input == True: 28 # if bool(first_input) == True: 29 # if bool(first_input): 30 if first_input: 31 # if second_input == True: 32 # if bool(second_input) == True: 33 # if bool(second_input): 34 if second_input: 35 return True 36 # return None 37 return Falsestill green because I can assume the following substitutions for
if something == True:if the value of
somethingis Falseif something == True if bool(something ) == True if bool(False ) == True if False == True if not True == True # change to terms of True if not True # remove '==True' if False if somethingif the value of
somethingis Trueif something == True if bool(something ) == True if bool(True ) == True if True == True # remove '==True' if True if something
this means that
if bool(something) == Trueis the same asif bool(something)is the same asif something.I can use AND to put two if statements together when one is indented under the other
if something: if something_else:can also be written as
if something and something_else:I use AND to put the two if statements together
21def logical_conjunction(first_input, second_input): 22 # return False 23 # return True 24 # if first_input == False: 25 # return False 26 # return second_input 27 # if first_input == True: 28 # if bool(first_input) == True: 29 # if bool(first_input): 30 # if first_input: 31 # if second_input == True: 32 # if bool(second_input) == True: 33 # if bool(second_input): 34 # if second_input: 35 if first_input and second_input: 36 return True 37 # return None 38 return Falsegreen.
I add an else clause to make it clearer
21def logical_conjunction(first_input, second_input): 22 # return False 23 # return True 24 # if first_input == False: 25 # return False 26 # return second_input 27 # if first_input == True: 28 # if bool(first_input) == True: 29 # if bool(first_input): 30 # if first_input: 31 # if second_input == True: 32 # if bool(second_input) == True: 33 # if bool(second_input): 34 # if second_input: 35 if first_input and second_input: 36 return True 37 # return None 38 else: 39 return Falsestill green because this happens when the logical_conjunction function is called. When
if first_input and second_input:runs, Python checks iffirst_inputis grouped as Trueif
first_inputis grouped as False, it leaves the if statement to run the rest of the function -else: return False, which returns False as the output then leaves the function since the return statement is the last thing to run in a functionif
first_inputis grouped as True, it checks ifsecond_inputis grouped as Trueif
second_inputis grouped as False, it leaves the if statement to run the rest of the function -else: return False, which returns False as the output then leaves the function since the return statement is the last thing to run in a functionif
second_inputis grouped as True, it runsreturn True, which returns True as the output then leaves the function since the return statement is the last thing to run in a function
conditional expressions
There is a way to write the if statement and else clause on one line instead of four lines. It is called a ternary operator or conditional expression. I add one to the function
21def logical_conjunction(first_input, second_input): 22 # return False 23 # return True 24 # if first_input == False: 25 # return False 26 # return second_input 27 # if first_input == True: 28 # if bool(first_input) == True: 29 # if bool(first_input): 30 # if first_input: 31 # if second_input == True: 32 # if bool(second_input) == True: 33 # if bool(second_input): 34 # if second_input: 35 # if first_input and second_input: 36 # return True 37 # return None 38 # else: 39 # return False 40 return ( 41 True if 42 first_input and second_input 43 else False 44 )the test is still green, because this is the same statement in a different order
return Truecomes first instead of afterif first_input and second_inputfirst_input and second_inputcome next, without theifelsecomes afterfirst_input and second_inputthen False without the return comes after
else
this means that
return True if something else Falseis a simpler way to write
if something: return True else: return FalseI can make the conditional expression even simpler, if I remove
True ifandelse False21def logical_conjunction(first_input, second_input): 22 # return False 23 # return True 24 # if first_input == False: 25 # return False 26 # return second_input 27 # if first_input == True: 28 # if bool(first_input) == True: 29 # if bool(first_input): 30 # if first_input: 31 # if second_input == True: 32 # if bool(second_input) == True: 33 # if bool(second_input): 34 # if second_input: 35 # if first_input and second_input: 36 # return True 37 # return None 38 # else: 39 # return False 40 return ( 41 # True if 42 first_input and second_input 43 # else False 44 )still green! This means that
return somethingis a simpler way to write
return True if something else Falsewhich is a simpler way to write
if something: return True else: return FalseI remove the commented lines
17def contradiction(first_input, second_input): 18 return False 19 20 21def logical_conjunction(first_input, second_input): 22 return first_input and second_inputI add a variable for
src.truth_table.logical_conjunctionin test_logical_conjunction intest_truth_table.py14 def test_logical_conjunction(self): 15 logical_conjunction = ( 16 src.truth_table.logical_conjunction 17 ) 18 self.assertTrue( 19 src.truth_table.logical_conjunction( 20 True, True 21 ) 22 ) 23 self.assertFalse( 24 src.truth_table.logical_conjunction( 25 True, False 26 ) 27 ) 28 self.assertFalse( 29 src.truth_table.logical_conjunction( 30 False, True 31 ) 32 ) 33 self.assertFalse( 34 src.truth_table.logical_conjunction( 35 False, False 36 ) 37 ) 38 39 40# Exceptions seenI use the variable to remove repetition of
src.truth_table.logical_conjunctionfrom the test14 def test_logical_conjunction(self): 15 logical_conjunction = ( 16 src.truth_table.logical_conjunction 17 ) 18 self.assertTrue( 19 # src.truth_table.logical_conjunction( 20 logical_conjunction( 21 True, True 22 ) 23 ) 24 self.assertFalse( 25 # src.truth_table.logical_conjunction( 26 logical_conjunction( 27 True, False 28 ) 29 ) 30 self.assertFalse( 31 # src.truth_table.logical_conjunction( 32 logical_conjunction( 33 False, True 34 ) 35 ) 36 self.assertFalse( 37 # src.truth_table.logical_conjunction( 38 logical_conjunction( 39 False, False 40 ) 41 ) 42 43 44# Exceptions seenthe test is still green.
I remove the commented lines
14 def test_logical_conjunction(self): 15 logical_conjunction = ( 16 src.truth_table.logical_conjunction 17 ) 18 self.assertTrue( 19 logical_conjunction(True, True) 20 ) 21 self.assertFalse( 22 logical_conjunction(True, False) 23 ) 24 self.assertFalse( 25 logical_conjunction(False, True) 26 ) 27 self.assertFalse( 28 logical_conjunction(False, False) 29 ) 30 31 32# Exceptions seenI add a git commit message in the other terminal
git commit -am 'add logical_conjunction'
logical_conjunction also known as and, always returns
first_input and second_inputTrue, if the first input is True and the second input is True
examples of Logical Conjunction
A person can vote, if the inputs are
is the person a citizen?
is the person old enough?
is a citizen
is old enough
can vote
yes
yes
yes
yes
no
no
no
yes
no
no
no
no
Music player goes to the next song or pauses, if the inputs are
are headphones connected?
has the current song finished playing?
headphones connected
current song finished
play next
yes
yes
yes
yes
no
no
no
yes
no
no
no
no
Baking a cake, if the inputs are
flour?
eggs?
flour
eggs
can bake
yes
yes
yes
yes
no
no
no
yes
no
no
no
no
I am a programmer, if the inputs are
can read code?
can write code?
read
write
is a programmer
yes
yes
yes
yes
no
no
no
yes
no
no
no
no
Multi Factor Authentication to log in, if the inputs are
did the user provide the right password?
did the user provide the MFA code?
right password
right MFA code
log in
yes
yes
yes
yes
no
no
no
yes
no
no
no
no
how did I get the right MFA code without the right password?
selling a product, if the inputs are
is there supply?
is there demand?
supply
demand
can sell
yes
yes
yes
yes
no
no
no
yes
no
no
no
no
All of the statements below have the same result as return something because Python groups objects as False or True
return True if
somethingis equal to Trueif something == True: return True else: return Falsereturn True if the result of
bool(something)is equal to Trueif bool(something) == True: return True else: return Falsereturn True if the result of
bool(something)is Trueif bool(something): return True else: return Falsereturn True if the result of
bool(something)is Trueif something: return True else: return Falsereturn True if the result of
bool(something)is Truereturn True if something else False
test_project_second
The truth table for project_second is
first input |
second input |
return |
|---|---|---|
True |
True |
True |
True |
False |
False |
False |
True |
True |
False |
False |
False |
RED: make it fail
I go back to the terminal where the tests are running
I add a test for project_second with an assertion for the case when the first input is True and the second input is True, to
test_binary.pyfirst input
second input
return
True
True
True
14 def test_logical_conjunction(self): 15 logical_conjunction = ( 16 src.truth_table.logical_conjunction 17 ) 18 self.assertTrue( 19 logical_conjunction(True, True) 20 ) 21 self.assertFalse( 22 logical_conjunction(True, False) 23 ) 24 self.assertFalse( 25 logical_conjunction(False, True) 26 ) 27 self.assertFalse( 28 logical_conjunction(False, False) 29 ) 30 31 def test_project_second(self): 32 self.assertTrue( 33 src.truth_table.project_second(True, True) 34 ) 35 36 37# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.truth_table' has no attribute 'project_second'because I do not have a definition for the project_second function in
truth_table.py
GREEN: make it pass
I add the function to truth_table.py
31def logical_conjunction(first_input, second_input):
32 return first_input and second_input
33
34
35def project_second(first_input, second_input):
36 return True
the test passes. project_second returns True, if the first input is True and the second input is True, just like logical_conjunction
REFACTOR: make it better
I add an assertion for the second case, which is when the first input is True and the second input is False, to test_project_second in
test_binary.pyfirst input
second input
return
True
False
False
31 def test_project_second(self): 32 self.assertTrue( 33 src.truth_table.project_second(True, True) 34 ) 35 self.assertFalse( 36 src.truth_table.project_second(True, False) 37 ) 38 39 40# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: True is not falsebecause the function returns True and the assertion expects
False, 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
the second input in both cases
I make project_second return
second_inputintruth_table.py25def project_second(first_input, second_input): 26 # return True 27 return second_inputthe test passes. project_second function returns the second input.
I remove the commented line
25def project_second(first_input, second_input): 26 return second_inputI add an assertion to test_project_second for the next case, which is when the first input is False and the second input is True, in
test_binary.py31 def test_project_second(self): 32 self.assertTrue( 33 src.truth_table.project_second(True, True) 34 ) 35 self.assertFalse( 36 src.truth_table.project_second(True, False) 37 ) 38 self.assertTrue( 39 src.truth_table.project_second(False, True) 40 ) 41 42 43# Exceptions seenthe test is still green.
I add an assertion for the last case, which is when the first input is False and the second input is False
first input
second input
return
False
False
False
31 def test_project_second(self): 32 self.assertTrue( 33 src.truth_table.project_second(True, True) 34 ) 35 self.assertFalse( 36 src.truth_table.project_second(True, False) 37 ) 38 self.assertTrue( 39 src.truth_table.project_second(False, True) 40 ) 41 self.assertFalse( 42 src.truth_table.project_second(False, False) 43 ) 44 45 46# Exceptions seenstill green.
I add a variable for
src.truth_table.project_second31 def test_project_second(self): 32 project_second = src.truth_table.project_second 33 self.assertTrue( 34 src.truth_table.project_second(True, True) 35 ) 36 self.assertFalse( 37 src.truth_table.project_second(True, False) 38 ) 39 self.assertTrue( 40 src.truth_table.project_second(False, True) 41 ) 42 self.assertFalse( 43 src.truth_table.project_second(False, False) 44 ) 45 46 47# Exceptions seenI use the variable to remove repetition of
src.truth_table.project_secondfrom the test31 def test_project_second(self): 32 project_second = src.truth_table.project_second 33 self.assertTrue( 34 # src.truth_table.project_second(True, True) 35 project_second(True, True) 36 ) 37 self.assertFalse( 38 # src.truth_table.project_second(True, False) 39 project_second(True, False) 40 ) 41 self.assertTrue( 42 # src.truth_table.project_second(False, True) 43 project_second(False, True) 44 ) 45 self.assertFalse( 46 # src.truth_table.project_second(False, False) 47 project_second(False, False) 48 ) 49 50 51# Exceptions seenthe test is still green.
I remove the commented lines
31 def test_project_second(self): 32 project_second = src.truth_table.project_second 33 self.assertTrue(project_second(True, True)) 34 self.assertFalse(project_second(True, False)) 35 self.assertTrue(project_second(False, True)) 36 self.assertFalse(project_second(False, False)) 37 38 39# Exceptions seenI add a git commit message in the other terminal
git commit -am 'add project_second'
project_second always returns the second input, it does not care about the first input
examples of Project Second
Binge watching TV, if the inputs are
should I sleep?
do I want to watch one more episode?
sleep?
do I want it?
watch TV
yes
yes
yes
yes
no
no
no
yes
yes
no
no
no
dictatorship, if the inputs are
is voters’ choice?
is dictator’s choice?
voters
dictator
outcome
yes
yes
yes
yes
no
no
no
yes
yes
no
no
no
being sick, if the inputs are
sick before?
sick now?
before
now
sick
healthy
healthy
healthy
healthy
sick
sick
sick
healthy
healthy
sick
sick
sick
my expectation versus reality, if the inputs are
my expectation
reality
expectation
reality
result
True
True
True
True
False
False
False
True
True
False
False
False
test_converse_non_implication
The truth table for converse_non_implication is
first input |
second input |
return |
|---|---|---|
True |
True |
False |
True |
False |
False |
False |
True |
True |
False |
False |
False |
RED: make it fail
I go back to the terminal where the tests are running
I add a test for converse_non_implication with an assertion for when the first input is True and the second input is True, to
test_binary.pyfirst input
second input
return
True
True
False
31 def test_project_second(self): 32 project_second = src.truth_table.project_second 33 self.assertTrue(project_second(True, True)) 34 self.assertFalse(project_second(True, False)) 35 self.assertTrue(project_second(False, True)) 36 self.assertFalse(project_second(False, False)) 37 38 def test_converse_non_implication(self): 39 self.assertFalse( 40 src.truth_table.converse_non_implication( 41 True, True 42 ) 43 ) 44 45 46# Exceptions seenthe terminal is my friend, and shows AttributeError
AttributeError: module 'src.truth_table' has no attribute 'converse_non_implication'because there is no definition for converse_non_implication in
truth_table.pyin thesrcfolder.
GREEN: make it pass
I add the function to truth_table.py
25 def project_second(first_input, second_input):
26 return second_input
27
28
29 def converse_non_implication(first_input, second_input):
30 return False
the test passes. converse_non_implication returns False, if the first input is True and the second input is True.
REFACTOR: make it better
I add an assertion for the next case, which is when the first input is True and the second input is False, to test_converse_non_implication in
test_binary.pyfirst input
second input
return
True
False
False
38 def test_converse_non_implication(self): 39 self.assertFalse( 40 src.truth_table.converse_non_implication( 41 True, True 42 ) 43 ) 44 self.assertFalse( 45 src.truth_table.converse_non_implication( 46 True, False 47 ) 48 ) 49 50 51# Exceptions seenthe test is still green. converse_non_implication returns False
if the first input is True and the second input is False
if the first input is True and the second input is True
I add an assertion for the third case, which is when the first input is False and the second input is True
first input
second input
return
False
True
True
38 def test_converse_non_implication(self): 39 self.assertFalse( 40 src.truth_table.converse_non_implication( 41 True, True 42 ) 43 ) 44 self.assertFalse( 45 src.truth_table.converse_non_implication( 46 True, False 47 ) 48 ) 49 self.assertTrue( 50 src.truth_table.converse_non_implication( 51 False, True 52 ) 53 ) 54 55 56# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: False is not truebecause the converse_non_implication function returns False and the assertion expects True.
I add an if statement for this case to the converse_non_implication function in
truth_table.py29def converse_non_implication(first_input, second_input): 30 if first_input == False: 31 return True 32 return Falsethe test passes. converse_non_implication returns
True if the first input is False
False if the above condition is NOT met
because this happens when the converse_non_implication function is called. When
if first_input == False:runs, Python checks iffirst_inputis equal to as Falseif
first_inputis NOT equal to False, it leaves the if statement to run the rest of the function -return False, which returns False as the output then leaves the function since the return statement is the last thing to run in a functionif
first_inputis equal to False, it runsreturn True, which returns True as the output then leaves the function since the return statement is the last thing to run in a function
I add an assertion for the next case, which is when the first input is False and the second input is False, to test_converse_non_implication in
test_binary.pyfirst input
second input
return
False
False
False
38 def test_converse_non_implication(self): 39 self.assertFalse( 40 src.truth_table.converse_non_implication( 41 True, True 42 ) 43 ) 44 self.assertFalse( 45 src.truth_table.converse_non_implication( 46 True, False 47 ) 48 ) 49 self.assertTrue( 50 src.truth_table.converse_non_implication( 51 False, True 52 ) 53 ) 54 self.assertFalse( 55 src.truth_table.converse_non_implication( 56 False, False 57 ) 58 ) 59 60 61# Exceptions seenthe terminal is my friend, and shows AssertionError
AssertionError: True is not falsebecause the function returned True and the assertion expects False.
I add an if statement for the one case that returns True, to the one in the converse_non_implication function in
truth_table.py29def converse_non_implication(first_input, second_input): 30 if first_input == False: 31 if second_input == True: 32 return True 33 return Falsethe test passes.
I add bool
29def converse_non_implication(first_input, second_input): 30 # if first_input == False: 31 if bool(first_input) == False: 32 # if second_input == True: 33 if bool(second_input) == True: 34 return True 35 return Falsethe test is still green.
I use Logical Negation (NOT) to write the first if statement in terms of True
29def converse_non_implication(first_input, second_input): 30 # if first_input == False: 31 # if bool(first_input) == False: 32 if bool(not first_input) == True: 33 # if second_input == True: 34 if bool(second_input) == True: 35 return True 36 return Falsestill green.
I remove
== Trueto remove repetition29def converse_non_implication(first_input, second_input): 30 # if first_input == False: 31 # if bool(first_input) == False: 32 # if bool(not first_input) == True: 33 if bool(not first_input): 34 # if second_input == True: 35 # if bool(second_input) == True: 36 if bool(second_input): 37 return True 38 return Falsegreen.
I remove bool
29def converse_non_implication(first_input, second_input): 30 # if first_input == False: 31 # if bool(first_input) == False: 32 # if bool(not first_input) == True: 33 # if bool(not first_input): 34 if not first_input: 35 # if second_input == True: 36 # if bool(second_input) == True: 37 # if bool(second_input): 38 if second_input: 39 return True 40 return Falsestill green, because
when
if first_input == False:runs, Python checks iffirst_inputis equal to False. I can assume the following substitutionsif the value of
somethingis Falseif something == False if bool(something ) == False if bool(False ) == False if False == False if True == True # use equality if True # remove '== True' if not False # change to terms of False if not somethingif the value of
somethingis Trueif something == False if bool(something ) == False if bool(True ) == False if True == False if False == True # use equality if False # remove '== True' if not True # change to terms of True if not something
when
if second_input == True:runs, Python checks if(second_input)is equal to True. I can assume the following substitutionsif the value of
somethingis Falseif something == True if bool(something ) == True if bool(False ) == True if False == True if not True == True # change to terms of True if not True # remove '==True' if False if somethingif the value of
somethingis Trueif something == True if bool(something ) == True if bool(True ) == True if True == True # remove '==True' if True if something
this means that
if bool(something) == Falseis the same asif bool(not something) == Trueis the same asif bool(not something)is the same asif not something.if bool(something) == Trueis the same asif bool(something)is the same asif something.
I use Logical Conjunction (AND) to put the two if statements together
29def converse_non_implication(first_input, second_input): 30 # if first_input == False: 31 # if bool(first_input) == False: 32 # if bool(not first_input) == True: 33 # if bool(not first_input): 34 # if not first_input: 35 # if second_input == True: 36 # if bool(second_input) == True: 37 # if bool(second_input): 38 # if second_input: 39 if not first_input and second_input: 40 return True 41 return Falsethe test is still green, because I can put two if statements together when one is indented under the other
if something: if something_else:can also be written as
if something and something_else:I add an else clause to be clearer
29def converse_non_implication(first_input, second_input): 30 # if first_input == False: 31 # if bool(first_input) == False: 32 # if bool(not first_input) == True: 33 # if bool(not first_input): 34 # if not first_input: 35 # if second_input == True: 36 # if bool(second_input) == True: 37 # if bool(second_input): 38 # if second_input: 39 if not first_input and second_input: 40 return True 41 else: 42 return Falsestill green.
I use a conditional expression
29def converse_non_implication(first_input, second_input): 30 # if first_input == False: 31 # if bool(first_input) == False: 32 # if bool(not first_input) == True: 33 # if bool(not first_input): 34 # if not first_input: 35 # if second_input == True: 36 # if bool(second_input) == True: 37 # if bool(second_input): 38 # if second_input: 39 # if not first_input and second_input: 40 # return True 41 # else: 42 # return False 43 return ( 44 True if 45 not first_input and second_input 46 else False 47 )green.
I remove
True ifandelse Falseto make the simpler return statement29def converse_non_implication(first_input, second_input): 30 # if first_input == False: 31 # if bool(first_input) == False: 32 # if bool(not first_input) == True: 33 # if bool(not first_input): 34 # if not first_input: 35 # if second_input == True: 36 # if bool(second_input) == True: 37 # if bool(second_input): 38 # if second_input: 39 # if not first_input and second_input: 40 # return True 41 # else: 42 # return False 43 return ( 44 # True if 45 not first_input and second_input 46 # else False 47 )still green.
converse_non_implication returns
not first_input and second_inputwhen
not first_inputruns, Python replaces it with the logical negation (NOT) offirst_input
if
first_inputis Falsenot first_input not False Trueif
first_inputis Truenot first_input not True False
this means that in the four cases
if the first input is True and the second input is True, converse_non_implication returns
(not first) and second (not True ) and True False and True False # logical_conjunction(False, True)if the first input is True and the second input is False, converse_non_implication returns
(not first) and second (not True ) and False False and False False # logical_conjunction(False, False)if the first input is False and the second input is True, converse_non_implication returns
(not first) and second (not False) and True True and True True # logical_conjunction(True, True)if the first input is False and the second input is False, converse_non_implication returns
(not first) and second (not False) and False True and False False # logical_conjunction(True, False)
first
not first
second
(not first) and second
True
False
True
False
True
False
False
False
False
True
True
True
False
True
False
False
I add a return statement to show this
29def converse_non_implication(first_input, second_input): 30 # if first_input == False: 31 # if bool(first_input) == False: 32 # if bool(not first_input) == True: 33 # if bool(not first_input): 34 # if not first_input: 35 # if second_input == True: 36 # if bool(second_input) == True: 37 # if bool(second_input): 38 # if second_input: 39 # if not first_input and second_input: 40 # return True 41 # else: 42 # return False 43 return logical_conjunction( 44 logical_negation(first_input), 45 second_input 46 ) 47 return ( 48 # True if 49 not first_input and second_input 50 # else False 51 )the test is still green.
I remove the commented lines
29def converse_non_implication(first_input, second_input): 30 return logical_conjunction( 31 logical_negation(first_input), 32 second_input 33 ) 34 return not first_input and second_inputI can use either of these two `return statements`_, the first return statement is the only one that runs in this case, because the return statement is the last thing to run in a function.
I add a variable for
src.truth_table.converse_non_implication38 def test_converse_non_implication(self): 39 converse_non_implication = ( 40 src.truth_table.converse_non_implication 41 ) 42 self.assertFalse( 43 src.truth_table.converse_non_implication( 44 True, True 45 ) 46 ) 47 self.assertFalse( 48 src.truth_table.converse_non_implication( 49 True, False 50 ) 51 ) 52 self.assertTrue( 53 src.truth_table.converse_non_implication( 54 False, True 55 ) 56 ) 57 self.assertFalse( 58 src.truth_table.converse_non_implication( 59 False, False 60 ) 61 ) 62 63 64# Exceptions seenI use the variable to remove repetition of
src.truth_table.converse_non_implication38 def test_converse_non_implication(self): 39 converse_non_implication = ( 40 src.truth_table.converse_non_implication 41 ) 42 self.assertFalse( 43 # src.truth_table.converse_non_implication( 44 converse_non_implication( 45 True, True 46 ) 47 ) 48 self.assertFalse( 49 # src.truth_table.converse_non_implication( 50 converse_non_implication( 51 True, False 52 ) 53 ) 54 self.assertTrue( 55 # src.truth_table.converse_non_implication( 56 converse_non_implication( 57 False, True 58 ) 59 ) 60 self.assertFalse( 61 # src.truth_table.converse_non_implication( 62 converse_non_implication( 63 False, False 64 ) 65 ) 66 67 68# Exceptions seenthe test is still green.
I remove the commented lines
38 def test_converse_non_implication(self): 39 converse_non_implication = ( 40 src.truth_table.converse_non_implication 41 ) 42 self.assertFalse( 43 converse_non_implication(True, True) 44 ) 45 self.assertFalse( 46 converse_non_implication(True, False) 47 ) 48 self.assertTrue( 49 converse_non_implication(False, True) 50 ) 51 self.assertFalse( 52 converse_non_implication(False, False) 53 ) 54 55 56# Exceptions seenI add a git commit message in the other terminal
git commit -am 'add converse_non_implication'
Converse Non-Implication always returns
not first_input and second_inputthe Logical Conjunction of the Logical Negation of the first input, and the second input
True, if the first input is False and the second input is True
examples of Converse Non-Implication
crossing the street, if the inputs are
light is green for cars?
light is green for walking?
green for cars?
green for walking?
can I cross the street?
yes
yes
no
yes
no
no
no
yes
yes
no
no
no
do a computer update, if the inputs are
is the computer in use?
is there an update available?
computer in use
update available
do update
yes
yes
no
yes
no
no
no
yes
yes
no
no
no
should I reply to a message?, if the inputs are
is it a group message?
is it one on one from a close friend?
group chat
close friend
reply
yes
yes
no
yes
no
no
no
yes
yes
no
no
no
only give a discount to a new customer with a coupon code, if the inputs are
is already a customer?
does customer have the coupon code?
already customer
has coupon
give discount
yes
yes
no
yes
no
no
no
yes
yes
no
no
no
run the gas generator, if the inputs are
is the house receiving electricity from the grid?
is there fuel in the generator?
grid
fuel
run generator
yes
yes
no
yes
no
no
no
yes
yes
no
no
no
close the project
I close
test_binary.pyandtruth_table.pyI click in the terminal where the tests are running
I use q on the keyboard to leave the tests. The terminal goes back to the command line.
I change directory to the parent of
truth_tablecd ..the terminal shows
.../pumping_pythonI am back in the
pumping_pythondirectory
review
Binary Operations take two inputs, each input can be True or False. If I name the first input first_input and the second input second_input, the tests show that
-
first input
second input
return
True
True
False
True
False
False
False
True
True
False
False
False
returns
not first_input and second_inputreturns True only if
first_inputis False andsecond_inputis Trueis the Logical Negation (NOT) of Converse Implication which returns False if
first_inputis False andsecond_inputis True
-
first input
second input
return
True
True
True
True
False
False
False
True
True
False
False
False
always returns
second_inputreturns True only if
second_inputis Trueis the Logical Negation (NOT) of Negate Second which returns True only if
second_inputis False
Logical Conjunction returns
first input
second input
return
True
True
True
True
False
False
False
True
False
False
False
False
returns
first_input and second_inputreturns True only if
first_inputis True andsecond_inputis Trueis the Logical Negation (NOT) of Logical NAND which returns False only if
first_inputis True andsecond_inputis True
-
first input
second input
return
True
True
False
True
False
False
False
True
False
False
False
False
always returns False
never returns True
is the Logical Negation (NOT) of Tautology which always returns True
and
One logic statement has been written with and, another was written both and and not.
return |
True, True |
True, False |
False, True |
False, False |
name of operation |
|---|---|---|---|---|---|
False |
False |
False |
False |
False |
|
first and second |
True |
False |
False |
False |
|
second |
True |
False |
True |
False |
|
(not first) and second |
False |
False |
True |
False |
code from the chapter
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.