truth table: Binary Operations 1


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
64# Exceptions seen
65# AttributeError
66# TypeError
67# AssertionError

requirements

truth table: Nullary and Unary Operations

continue the project

  • Make sure you are in the pumping_python folder with pwd in the terminal

    pwd
    

    if the terminal shows anything other than

    .../pumping_python
    

    change directory to the pumping_python folder

  • Once in pumping_python, change directory to the project

    cd truth_table
    

    the terminal shows

    .../pumping_python/truth_table
    
  • I run the tests with pytest-watcher

    uv run pytest-watcher . --now
    
  • the terminal 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


RED: make it fail


  • I make a new file in the tests folder named test_binary.py

  • I add a new test to test_binary.py

     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 seen
    

    the terminal shows AttributeError

    AttributeError: module 'src.truth_table' has no attribute 'contradiction'
    
  • I add AttributeError to the list of Exceptions seen

    13# Exceptions seen
    14# AttributeError
    

GREEN: make it pass


  • I open truth_table.py in the editor

  • I add a function to truth_table.py

    13def logical_negation(the_input):
    14    return not the_input
    15
    16
    17def contradiction():
    18    return None
    

    the terminal shows TypeError

    TypeError: contradiction() takes 0 positional arguments but 2 were given
    

    the function takes no input but the test sent two

  • I add TypeError to the list of Exceptions seen

    13# Exceptions seen
    14# AttributeError
    15# TypeError
    
  • I add first_input in parentheses

    17def contradiction(first_input):
    18    return None
    

    the terminal shows TypeError

    TypeError: contradiction() takes 1 positional argument but 2 were given
    
  • I add second_input as the second name in parentheses

    17def contradiction(the_input, second_input):
    18    return None
    

    the test passes because None is False. contradiction returns False, if the first input is True and if the second input is True


REFACTOR: make it better


  • I change the return statement to be clearer

    17def contradiction(first_input, second_input):
    18    return False
    

    the test is still green

  • I add the second case, which is when the first input is True and the second input is False to test_binary.py

     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        )
    

    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

  • I add the third case, which is when the first input is False and the second input is True

     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        )
    

    the 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 and the second input is False

    • if the first input is True and the second input is True

  • I add the fourth case for when the first input is False and the second input is 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 seen
    

    the test is still green!

contradiction always returns False, it does not care about what it gets


test_logical_conjunction


RED: make it fail


I add a test for the first case where the two inputs are True for logical_conjunction to test_binary.py

 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
26
27# Exceptions seen

the terminal shows AttributeError

AttributeError: module 'src.truth_table' has no attribute 'logical_conjunction'. Did you mean: 'logical_negation'?

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 the next case - when the first input is True and the second input is False, to test_logical_conjunction in test_binary.py

    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        )
    

    the terminal shows AssertionError

    AssertionError: True is not false
    
  • I add AssertionError to the list of Exceptions

    30# Exceptions seen
    31# AttributeError
    32# TypeError
    33# AssertionError
    
  • I make the logical_conjunction function in truth_table.py return False

    21def logical_conjunction(first_input, second_input):
    22    return False
    

    the terminal shows AssertionError

    AssertionError: False is not true
    

    the line that was passing before is now failing. 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.py

    21def logical_conjunction(first_input, second_input):
    22    return second_input
    

    the test passes

  • I add the 3rd case where the first input is False and the second input is True to test_logical_conjunction in test_binary.py

    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        )
    

    the terminal shows AssertionError

    AssertionError: True is not false
    

    my solution does not work for this case. logical_conjunction has to make a choice, it should return

    I can make it do that with if statements


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 2 things. They are written this in Python

if something:
    then do this
  • I add if statements for when False is the first_input and the second input is True to the logical_conjunction function in truth_table.py

    21def logical_conjunction(first_input, second_input):
    22    if first_input == False:
    23        if second_input == True:
    24            return False
    25    return second_input
    

    the test passes. logical_conjunction returns

    Note

  • I add the last case, which is when the two inputs are False, to test_logical_conjunction in test_binary.py

    21def 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
    36# Exceptions seen
    

    the test is still green. logical_conjunction returns

    • False, if the first input is False and the second input is False

    • 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 - this is the only case where it returns True

  • I add an if statement for the case where logical_conjunction returns True in truth_table.py

    21def logical_conjunction(first_input, second_input):
    22    if first_input == True:
    23        if second_input == True:
    24            return True
    25    if first_input == False:
    26        if second_input == True:
    27            return False
    28    return second_input
    

    still green

    • if first_input == True: checks if first_input is equal to True

      • if first_input is equal to True, it goes to the next line if second_input == True:

      • if first_input is NOT equal to True, it leaves this if statement and continues to if first_input == False:, it will never go to if second_input == True:

    • if second_input == True: checks if second_input is equal to True

    Since there is only one case where the function returns True, I do not need any other statements

  • I remove the other if statements

    21def logical_conjunction(first_input, second_input):
    22    if first_input == True:
    23        if second_input == True:
    24            return True
    

    the test is still green 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    if first_input == True:
    23        if second_input == True:
    24            return True
    25    return None
    

    still green because None is False

  • I change the return statement to use False

    21def logical_conjunction(first_input, second_input):
    22    if first_input == True:
    23        if second_input == True:
    24            return True
    25    return False
    

    green

  • I put the two if statements for the one case where the result is True together and use an else clause for the other cases where the first and second inputs are NOT both True

    Tip

    I can put two if statements together when one is indented under the other. For example

    if something:
        if something_else:
    

    can also be written as

    if something and something_else:
    
    21def logical_conjunction(first_input, second_input):
    22    # if first_input == True:
    23        # if second_input == True:
    24    if first_input == True and second_input == True:
    25            return True
    26    return False
    

    still green

  • I remove the commented lines then use bool in the if statement

    Tip

    bool(anything) returns True or False for the thing in parentheses like the tests in the booleans chapter with the assertFalse and assertTrue methods

    21def logical_conjunction(first_input, second_input):
    22    # if first_input == True and second_input == True:
    23    if bool(first_input) == True and bool(second_input) == True:
    24            return True
    25    return False
    

    the test is still green

  • I remove the commented line

  • Since bool(True) is the same as True, bool(first_input) == True is the same thing as True == True, which is a repetition. I remove == True from the if statement

    21def logical_conjunction(first_input, second_input):
    22    # if bool(first_input) == True and bool(second_input) == True:
    23    if bool(first_input) and bool(second_input):
    24            return True
    25    return False
    

    still green

    Note

    if bool(anything) checks if bool(anything) returns True

  • I remove the commented line then change the first line to make it simpler

    21def logical_conjunction(first_input, second_input):
    22    # if bool(first_input) and bool(second_input):
    23    if first_input and second_input:
    24            return True
    25    return False
    

    the test is still green

  • I add an else clause to be clearer

    22def logical_conjunction(first_input, second_input):
    23    if first_input and second_input:
    24            return True
    25    else:
    26        return False
    

    still green

Note

these if statements have the same result

  • if something == True: - checks if something is equal to True?

these check if the result of bool(something) is True, the same way the assertTrue method does

  • if bool(something) == True:

  • if bool(something):

  • if something:


conditional expressions

  • I can write the if statement and else clause on one line with a ternary operator or conditional expression

    21def logical_conjunction(first_input, second_input):
    22    return True if first_input and second_input else False
    23    if first_input and second_input:
    24            return True
    25    else:
    26        return False
    

    the test is still green

  • I remove the other statements and write the return statement in a simpler way

    21def logical_conjunction(first_input, second_input):
    22    return first_input and second_input
    23    return True if first_input and second_input else False
    

    still green!

  • I remove the second return statement because the return statement is the last thing to run in a function

    21def logical_conjunction(first_input, second_input):
    22    return first_input and second_input
    

Logical Conjunction also known as and, always returns

  • first_input and second_input

  • True, if the first input is True and the second input is True

Note

All of the statements below have the same result

  • this checks if something is equal True

    if something == True:
        return True
    else:
        return False
    
  • this uses bool to get the boolean of something then checks if the result is equal to True

    if bool(something) == True:
        return True
    else:
        return False
    
  • this checks if the result of bool(something) is True

    if bool(something):
        return True
    else:
        return False
    
  • this also checks if the result of bool(something) is True

    if something:
        return True
    else:
        return False
    
  • this returns True if the result of bool(something) is True

    return True if something else False
    
  • this also returns True if the result of bool(something) is True

    return something
    

    all of this means that if something: return True is the same as return something


test_project_second


RED: make it fail


I add a test for another Binary Operation to test_binary.py

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
40
41# Exceptions seen

the terminal shows AttributeError

AttributeError: module 'src.truth_table' has no attribute 'project_second'

GREEN: make it pass


I add the function to truth_table.py

21def logical_conjunction(first_input, second_input):
22    return first_input and second_input
23
24
25def project_second(first_input, second_input):
26    return True

the test passes. project_second returns True, if the first input is True and the second input is True. So far this is the same as logical_conjunction


REFACTOR: make it better


  • I add the second case - when the first input is True and the second input is False, to test_project_second in test_binary.py

    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        )
    

    the terminal shows AssertionError

    AssertionError: True is not false
    

    the test 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_input in truth_table.py

    25def project_second(first_input, second_input):
    26    return second_input
    

    the test passes. project_second returns True

    • if the first input is True and the second input is False

    • if the first input is True and the second input is True

    • the second input in both cases

  • I add the next case, which is when the first input is False and the second input is True for test_project_second in test_binary.py

    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        )
    

    the test is still green. project_second returns

    • True, 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

    • the second input in all 3 cases

  • I add the last case - when the first input is False and the second input is False

    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
    50# Exceptions seen
    

    still green. project_second returns

    • False, 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

    • 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 all cases, it does not care about the first input


test_converse_non_implication


RED: make it fail


I add a test for converse_non_implication to test_binary.py

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
54
55# Exceptions seen

the terminal shows AttributeError

AttributeError: module 'src.truth_table' has no attribute 'converse_non_implication'

GREEN: make it pass


I add the function to truth_table.py

25def project_second(first_input, second_input):
26    return second_input
27
28
29def 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 the next case - when the first input is True and the second input is False to test_converse_non_implication 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        )
    

    the 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 the third case - when the first input is False and the second input is True

    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        )
    

    the terminal shows AssertionError

    AssertionError: False is not true
    
  • I add an if statement for this case to converse_non_implication in truth_table.py

    29def converse_non_implication(first_input, second_input):
    30    if first_input == False:
    31        if second_input == True:
    32            return True
    33    return False
    

    the test passes. converse_non_implication returns False

    • if the first input is False and the second input is True

    • 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 the next case - when the first input is False and the second input is False, to test_converse_non_implication 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
    64# Exceptions seen
    

    the test is still green. converse_non_implication returns

    • False, 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 - this is the only case where it returns True

    • False, if the first input is True and the second input is False

    • False, if the first input is True and the second input is True

  • I use logical conjunction (and) to put the two if statements together in converse_non_implication in truth_table.py

    29def converse_non_implication(first_input, second_input):
    30    # if first_input == False:
    31    #     if second_input == True:
    32    if first_input == False and second_input == True:
    33            return True
    34    return False
    

    still green

  • I remove the comments and use not to write the if statement with True

    29def converse_non_implication(first_input, second_input):
    30    # if first_input == False and second_input == True:
    31    if not first_input == True and second_input == True:
    32            return True
    33    return False
    

    green

  • I remove the commented line and use bool

    29def converse_non_implication(first_input, second_input):
    30    # if not first_input == True and second_input == True:
    31    if not bool(first_input) == True and bool(second_input) == True:
    32            return True
    33    return False
    

    still green

  • I remove the comment and the repeated == True

    29def converse_non_implication(first_input, second_input):
    30    # if not bool(first_input) == True and bool(second_input) == True:
    31    if not bool(first_input) and bool(second_input):
    32            return True
    33    return False
    

    the test is still green

  • I remove the comment and bool

    29def converse_non_implication(first_input, second_input):
    30    # if not bool(first_input) and bool(second_input):
    31    if not first_input and second_input:
    32        return True
    33    return False
    

    still green

  • I remove the comment then add an else clause

    29def converse_non_implication(first_input, second_input):
    30    if not bool(first_input) and bool(second_input):
    31            return True
    32    else:
    33        return False
    

    green

  • I use a conditional expression

    29def converse_non_implication(first_input, second_input):
    30    return True if not first_input and second_input else False
    31    if not bool(first_input) and bool(second_input):
    32            return True
    33    else:
    34        return False
    

    still green

  • I remove the other statements then use the simpler return statement

    29def converse_non_implication(first_input, second_input):
    30    return not first_input and second_input
    31    return True if not first_input and second_input else False
    

    the test is still green

  • I remove the second return statement

    29def converse_non_implication(first_input, second_input):
    30    return not first_input and second_input
    

    Note

    this means that in the 4 cases

    • if the first input is True and the second input is True, converse_non_implication returns

      not first_input and second_input
      not True        and True
      False           and True          # logical_conjunction(False, True)
      False                             # logical_conjunction(False, True)
      
    • if the first input is True and the second input is False, converse_non_implication returns

      not first_input and second_input
      not True        and False
      False           and False         # logical_conjunction(False, False)
      False                             # logical_conjunction(False, False)
      
    • if the first input is False and the second input is True, converse_non_implication returns

      not first_input and second_input
      not False       and True
      True            and True          # logical_conjunction(True, True)
      True                              # logical_conjunction(True, True)
      
    • if the first input is False and the second input is False, converse_non_implication returns

      not first_input and second_input
      not False       and False
      True            and False         # logical_conjunction(True, False)
      False                             # logical_conjunction(True, False)
      
  • I add a return statement

    29def converse_non_implication(first_input, second_input):
    30    return logical_conjunction(not first_input, second_input)
    31    return not first_input and second_input
    

    the test is still green

Converse NonImplication always returns


close the project

  • I close test_binary.py and truth_table.py in the editor

  • I 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_table

    cd ..
    

    the terminal shows

    .../pumping_python
    

    I am back in the pumping_python directory


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

and

All the logic statements or conditions have been written with and or not or both.


code from the chapter

Do you want to see all the CODE I typed for the Truth Table?


what is next?

Would you like to write more tests with bool?


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