truth table: Binary Operations 1


preview

These are the tests I have at the end of the chapter

truth_table/tests/test_binary.py
 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(logical_conjunction(True, True))
19        self.assertFalse(logical_conjunction(True, False))
20        self.assertFalse(logical_conjunction(False, True))
21        self.assertFalse(logical_conjunction(False, False))
truth_table/tests/test_binary.py
23    def test_project_second(self):
24        project_second = src.truth_table.project_second
25        self.assertTrue(project_second(True, True))
26        self.assertFalse(project_second(True, False))
27        self.assertTrue(project_second(False, True))
28        self.assertFalse(project_second(False, False))
29
30    def test_converse_non_implication(self):
31        converse_non_implication = (
32            src.truth_table.converse_non_implication
33        )
34        self.assertFalse(converse_non_implication(True, True))
35        self.assertFalse(converse_non_implication(True, False))
36        self.assertTrue(converse_non_implication(False, True))
37        self.assertFalse(converse_non_implication(False, False))
38
39
40# Exceptions seen
41# AttributeError
42# TypeError
43# AssertionError

questions about Binary Operations 1

Questions to think about as I go through the chapter


requirements

truth table: Nullary and Unary Operations

open the project

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

    pwd
    

    if the terminal does not show

    .../pumping_python
    

    change directory to the pumping_python folder

  • Once in pumping_python, change directory to the project

    cd truth_table
    
  • I use touch to make a new Python file named test_binary.py in the tests directory

    touch tests/test_binary.py
    
    New-Item tests/test_binary.py
    
  • I add test_binary.py to git for tracking

    git add tests/test_binary.py
    
  • I open test_binary.py from the tests folder

  • I run the tests with pytest-watcher

    uv run pytest-watcher . --now
    
  • the 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 if the first input is True and the second input is True, in test_binary.py

    first 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 seen
    

    the 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.py

  • I add AttributeError to the list of Exceptions seen

    13# Exceptions seen
    14# AttributeError
    

GREEN: make it pass


  • I open truth_table/__init__.py from the src folder

  • I add contradiction to truth_table.py

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

    the terminal is my friend, and shows TypeError

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

    because 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 , in test_binary.py

    13# Exceptions seen
    14# AttributeError
    15# TypeError
    
  • I add first_input as the name of the first argument in the function signature for contradiction, in truth_table.py

    17# def contradiction():
    18def contradiction(first_input):
    19    return None
    

    the terminal is my friend, and shows TypeError

    TypeError: contradiction() takes
               1 positional argument but 2 were given
    

    because 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_input as the name of the second input in parentheses

    17# def contradiction():
    18# def contradiction(first_input):
    19def contradiction(first_input, second_input):
    20    return None
    

    the test passes because None is grouped as False (the result of bool(None) is False) and the assertion expects False.

    contradiction(True, True) -> None
    

    Using substitution since I can treat a call to a function as the object it returns

    assertFalse(src.truth_table.contradiction(True, True))
    assertFalse(None                                     )
    assertFalse(bool(None)                               )
    assertFalse(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 False
    

    the test is still green. contradiction returns False, if the first input is True and the second input is True.

  • I remove the commented lines from contradiction

    13def logical_negation(the_input):
    14    return not the_input
    15
    16
    17def contradiction(first_input, second_input):
    18    return False
    
  • I add an assertion for the second case, which is if the first input is True and the second input is False, to test_binary.py

    first 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 seen
    

    the 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

    contradiction(True, False) -> False
    contradiction(True, True ) -> False
    
  • I add an assertion for the third case, which is if 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 seen
    

    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

    contradiction(False, True ) -> False
    contradiction(True , False) -> False
    contradiction(True , True ) -> False
    
  • I add an assertion for the fourth case, which is if 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 seen
    

    the test is still green. contradiction returns False

    • if the first input is False

    • if the first input is True

    contradiction(False, False) -> False
    contradiction(False, True ) -> False
    contradiction(True , False) -> False
    contradiction(True , True ) -> False
    
  • I add a variable for src.truth_table.contradiction

     7    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 seen
    
  • I use the variable to remove repetition of src.truth_table.contradiction

     7    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 seen
    

    the test is still green.

  • I remove the commented lines from test_contradiction

     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 seen
    
  • I 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?

    the rule does not take the inputs into consideration

    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 if the first input is True and the second input is True, in test_binary.py

    first input

    second input

    return

    True

    True

    True

    12        self.assertFalse(contradiction(False, False))
    13
    14    def test_logical_conjunction(self):
    15        self.assertTrue(
    16            src.truth_table.logical_conjunction(True, True)
    17        )
    18
    19
    20# Exceptions seen
    

    the 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, yet.


GREEN: make it pass


I add logical_conjunction 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.

logical_conjunction(True , True ) -> True

REFACTOR: make it better


  • I add an assertion for the next case, which is if the first input is True and the second input is False, to test_logical_conjunction in test_binary.py

    first 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 seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: True is not false
    

    because the function returns True and the assertion expects False. Using substitution since I can treat a call to a function as the object it returns

    assertFalse(src.truth_table.logical_conjunction(True, False))
    assertFalse(True                                            )
    
  • I add AssertionError to the list of Exceptions seen, in test_binary.py

    27# Exceptions seen
    28# AttributeError
    29# TypeError
    30# AssertionError
    
  • I make the logical_conjunction function in truth_table.py return False

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

    the terminal is my friend, and shows AssertionError

    AssertionError: False is not true
    

    because 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.py

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

    the test passes.

    logical_conjunction(True, False) -> False
    logical_conjunction(True, True ) -> True
    
  • I add an assertion for the third case, which is if the first input is False and the second input is True, to test_logical_conjunction in test_binary.py

    first 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 seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: True is not false
    

    because 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.py

    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
    

    the test passes. logical_conjunction returns

    • False, if the first input is False

    • the second input if the above condition is NOT met

    because Python checks if first_input is equal to False when if first_input == False: runs,

    • if first_input is 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 of second_input as the output, then leaves the function since the return statement is the last thing to run in a function

      logical_conjunction(True , True ) -> True
      └── def logical_conjunction(first_input, second_input):
          ├── first_input  == True
          ├── second_input == True
          ├── if first_input == False:
                return False
          └── return second_input
      
      logical_conjunction(True , False) -> False
      └── def logical_conjunction(first_input, second_input):
          ├── first_input  == True
          ├── second_input == False
          ├── if first_input == False:
                return False
          └── return second_input
      
    • if first_input is equal to False, it goes to the next line - return False then leaves the function since the return statement is the last thing to run in a function

      logical_conjunction(False, True ) -> False
      └── def logical_conjunction(first_input, second_input):
          ├── first_input  == False
          ├── second_input == False
          └── if first_input == False:
              └── return False
              return second_input
      
  • I add an assertion for the last case, which is if the first input is False and the second input is False, to test_logical_conjunction in test_binary.py

    first 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 seen
    

    the test is still green.

  • There is only one case where logical_conjunction returns True, I add an if statement for it in truth_table.py

    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
    

    the test is still green, because the function returns

  • 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 None
    

    still 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 False
    

    green. It now only checks second_input if first_input is True.

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

    still 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) == True is the same thing as True == True when first_input is True, which is a repetition.

    first_input = True
    
    if bool(first_input) == True:
    if bool(True       ) == True:
    if True              == True:
    

    I remove == True from 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 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 False
    

    the test is still green because

    • if bool(something) checks if bool(something) returns True

    • if the result of bool(something) is True then if bool(something) is the same thing as if True

    • if bool(something) is the same as if bool(something) == True

    if bool(something)
    if bool(something) == True
    if True            == True
    if True
    
  • Which means 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 False
    

    still green because I can assume the following substitutions for if something == True:

    • if the value of something is False

      something = False
      
      if something       == True
      if bool(something) == True
      if bool(False    ) == True # use the value
      if False           == True # bool(False) returns False
      if not True        == True  # write in terms of True
      if not True                 # remove '== True'
      if False                    # not True == False
      if something                # use the name for the value
      
    • if the value of something is True

      something = True
      
      if something       == True
      if bool(something) == True
      if bool(True     ) == True # use the value
      if True            == True # bool(True) returns True
      if True                    # remove '== True'
      if something               # use the name for the value
      

    this means that if bool(something) == True is the same as if bool(something) is the same as if 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 False
    

    green.

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

    still green because Python checks if first_input is grouped as True when the logical_conjunction function is called. When if first_input and second_input: runs,

    • if first_input is 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 function

      logical_conjunction(False, False) -> False
      └── def logical_conjunction(first_input, second_input):
          ├── first_input  == False
          ├── second_input == False
          ├── if first_input and second_input:
                 return True
          └── else:
              └── return False
      
      logical_conjunction(False, True ) -> False
      └── def logical_conjunction(first_input, second_input):
          ├── first_input  == False
          ├── second_input == True
          ├── if first_input and second_input:
                 return True
          └── else:
              └── return False
      
    • if first_input is grouped as True, it checks if second_input is grouped as True

      • if second_input is 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 function

        logical_conjunction(True , False) -> False
        └── def logical_conjunction(first_input, second_input):
            ├── first_input  == True
            ├── second_input == False
            ├── if first_input and second_input:
                   return True
            └── else:
                └── return False
        
      • if second_input is grouped as True, it runs return True, which returns True as the output then leaves the function since the return statement is the last thing to run in a function

        logical_conjunction(True , True ) -> True
        └── def logical_conjunction(first_input, second_input):
            ├── first_input  == True
            ├── second_input == True
            └── if first_input and second_input:
                └── return True
                else:
                    return False
        
    • it only checks second_input if first_input is True.


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 True comes first instead of after if first_input and second_input

    • first_input and second_input come next, without the if

    • else comes after first_input and second_input

    • then False without the return comes after else

    if first_input and second_input: vs return True
        return True                  vs if first_input and second_input
    else:                            vs else
        return False                 vs False
    
    return True if something else False
    

    is a simpler way to write

    if something:
        return True
    else:
        return False
    
  • I can make the conditional expression even simpler, if I remove True if and else False

    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    )
    

    still green!

    return something
    

    is a simpler way to write

    return True if something else False
    

    which is a simpler way to write

    if something:
        return True
    else:
        return False
    
  • I remove the commented lines from logical_conjunction

    17def contradiction(first_input, second_input):
    18    return False
    19
    20
    21def logical_conjunction(first_input, second_input):
    22    return first_input and second_input
    
  • I add a variable for src.truth_table.logical_conjunction in test_logical_conjunction of test_binary.py

    14    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 seen
    
  • I use the variable to remove repetition of src.truth_table.logical_conjunction from the test

    14    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 seen
    

    the 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(logical_conjunction(True, True))
    19        self.assertFalse(logical_conjunction(True, False))
    20        self.assertFalse(logical_conjunction(False, True))
    21        self.assertFalse(logical_conjunction(False, False))
    22
    23
    24# Exceptions seen
    
  • I 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_input

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

  • A person can get a license, if the inputs are

    • did the person pass the test?

    • is the person old enough?

    passed test

    is old enough

    can get license

    yes

    yes

    yes

    yes

    no

    no

    no

    yes

    no

    no

    no

    no

  • I can bake 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

    how did I learn to write without reading?

  • 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?

  • I can sell 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 something is equal to True

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

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

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

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

    return 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.py

    first input

    second input

    return

    True

    True

    True

    21        self.assertFalse(logical_conjunction(False, False))
    22
    23    def test_project_second(self):
    24        self.assertTrue(
    25            src.truth_table.project_second(True, True)
    26        )
    27
    28
    29# Exceptions seen
    

    the 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 project_second 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

     project_second(True , True ) -> True
logical_conjunction(True , True ) -> True

REFACTOR: make it better


  • I add an assertion for the second case, which is if the first input is True and the second input is False, to test_project_second in test_binary.py

    first input

    second input

    return

    True

    False

    False

    23    def test_project_second(self):
    24        self.assertTrue(
    25            src.truth_table.project_second(True, True)
    26        )
    27        self.assertFalse(
    28            src.truth_table.project_second(True, False)
    29        )
    30
    31
    32# Exceptions seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: True is not false
    

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

    25def project_second(first_input, second_input):
    26    # return True
    27    return second_input
    

    the test passes. The project_second function returns the second input.

    project_second(True , False) -> False
    project_second(True , True ) -> True
    
  • I remove the commented line

    25def project_second(first_input, second_input):
    26    return second_input
    
  • I add an assertion to test_project_second for the next case, which is if the first input is False and the second input is True, in test_binary.py

    23    def test_project_second(self):
    24        self.assertTrue(
    25            src.truth_table.project_second(True, True)
    26        )
    27        self.assertFalse(
    28            src.truth_table.project_second(True, False)
    29        )
    30        self.assertTrue(
    31            src.truth_table.project_second(False, True)
    32        )
    33
    34
    35# Exceptions seen
    

    the test is still green.

    project_second(False, True ) -> True
    project_second(True , False) -> False
    project_second(True , True ) -> True
    
  • I add an assertion for the last case, which is if the first input is False and the second input is False

    first input

    second input

    return

    False

    False

    False

    23    def test_project_second(self):
    24        self.assertTrue(
    25            src.truth_table.project_second(True, True)
    26        )
    27        self.assertFalse(
    28            src.truth_table.project_second(True, False)
    29        )
    30        self.assertTrue(
    31            src.truth_table.project_second(False, True)
    32        )
    33        self.assertFalse(
    34            src.truth_table.project_second(False, False)
    35        )
    36
    37
    38# Exceptions seen
    

    still green.

    project_second(False, False) -> False
    project_second(False, True ) -> True
    project_second(True , False) -> False
    project_second(True , True ) -> True
    
  • I add a variable for src.truth_table.project_second

    23    def test_project_second(self):
    24        project_second = src.truth_table.project_second
    25        self.assertTrue(
    26            src.truth_table.project_second(True, True)
    27        )
    28        self.assertFalse(
    29            src.truth_table.project_second(True, False)
    30        )
    31        self.assertTrue(
    32            src.truth_table.project_second(False, True)
    33        )
    34        self.assertFalse(
    35            src.truth_table.project_second(False, False)
    36        )
    37
    38
    39# Exceptions seen
    
  • I use the variable to remove repetition of src.truth_table.project_second from the test

    23    def test_project_second(self):
    24        project_second = src.truth_table.project_second
    25        self.assertTrue(
    26            # src.truth_table.project_second(True, True)
    27            project_second(True, True)
    28        )
    29        self.assertFalse(
    30            # src.truth_table.project_second(True, False)
    31            project_second(True, False)
    32        )
    33        self.assertTrue(
    34            # src.truth_table.project_second(False, True)
    35            project_second(False, True)
    36        )
    37        self.assertFalse(
    38            # src.truth_table.project_second(False, False)
    39            project_second(False, False)
    40        )
    41
    42
    43# Exceptions seen
    

    the test is still green.

  • I remove the commented lines

    23    def test_project_second(self):
    24        project_second = src.truth_table.project_second
    25        self.assertTrue(project_second(True, True))
    26        self.assertFalse(project_second(True, False))
    27        self.assertTrue(project_second(False, True))
    28        self.assertFalse(project_second(False, False))
    29
    30
    31# Exceptions seen
    
  • I 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, it projects the second 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 if the first input is True and the second input is True, to test_binary.py

    first input

    second input

    return

    True

    True

    False

    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 seen
    

    the 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.py in the src folder.


GREEN: make it pass


I add converse_non_implication 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.

converse_non_implication(True , True ) -> False

REFACTOR: make it better


  • I add an assertion for the next case, which is if the first input is True and the second input is False, to test_converse_non_implication of test_binary.py

    first input

    second input

    return

    True

    False

    False

    30    def test_converse_non_implication(self):
    31        self.assertFalse(
    32            src.truth_table.converse_non_implication(
    33                True, True
    34            )
    35        )
    36        self.assertFalse(
    37            src.truth_table.converse_non_implication(
    38                True, False
    39            )
    40        )
    41
    42
    43# Exceptions seen
    

    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

    converse_non_implication(True , False) -> False
    converse_non_implication(True , True ) -> False
    
  • I add an assertion for the third case, which is if the first input is False and the second input is True

    first input

    second input

    return

    False

    True

    True

    30    def test_converse_non_implication(self):
    31        self.assertFalse(
    32            src.truth_table.converse_non_implication(
    33                True, True
    34            )
    35        )
    36        self.assertFalse(
    37            src.truth_table.converse_non_implication(
    38                True, False
    39            )
    40        )
    41        self.assertTrue(
    42            src.truth_table.converse_non_implication(
    43                False, True
    44            )
    45        )
    46
    47
    48# Exceptions seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: False is not true
    

    because 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.py

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

    the test passes. converse_non_implication returns

    • True if the first input is False

    • False if the above condition is NOT met

    because Python checks if first_input is equal to False, when the converse_non_implication function is called. When if first_input == False: runs

    • if first_input is 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 function

      converse_non_implication(True , True ) -> False
      └── def converse_non_implication(first_input, second_input):
          ├── first_input  == True
          ├── second_input == True
          ├── if first_input == False:
                 return True
          └── return False
      
      converse_non_implication(True , False) -> False
      └── def converse_non_implication(first_input, second_input):
          ├── first_input  == True
          ├── second_input == False
          ├── if first_input == False:
                 return True
          └── return False
      
    • if first_input is equal to False, it runs return True, which returns True as the output then leaves the function since the return statement is the last thing to run in a function

      converse_non_implication(False, True ) -> True
      └── def converse_non_implication(first_input, second_input):
          ├── first_input  == False
          ├── second_input == True
          └── if first_input == False:
              └── return True
              return False
      
  • I add an assertion for the next case, which is if the first input is False and the second input is False, to test_converse_non_implication in test_binary.py

    first input

    second input

    return

    False

    False

    False

    30    def test_converse_non_implication(self):
    31        self.assertFalse(
    32            src.truth_table.converse_non_implication(
    33                True, True
    34            )
    35        )
    36        self.assertFalse(
    37            src.truth_table.converse_non_implication(
    38                True, False
    39            )
    40        )
    41        self.assertTrue(
    42            src.truth_table.converse_non_implication(
    43                False, True
    44            )
    45        )
    46        self.assertFalse(
    47            src.truth_table.converse_non_implication(
    48                False, False
    49            )
    50        )
    51
    52
    53# Exceptions seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: True is not false
    

    because 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.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. The converse_non_implication function only checks the second input if the first input is False.

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

    the 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 not bool(first_input) == True:
    33        # if second_input == True:
    34        if bool(second_input) == True:
    35            return True
    36    return False
    

    still green.

  • I remove == True to remove repetition

    29def converse_non_implication(first_input, second_input):
    30    # if first_input == False:
    31    # if bool(first_input) == False:
    32    # if not bool(first_input) == True:
    33    if not bool(first_input):
    34        # if second_input == True:
    35        # if bool(second_input) == True:
    36        if bool(second_input):
    37            return True
    38    return False
    

    green.

  • I remove bool

    29def converse_non_implication(first_input, second_input):
    30    # if first_input == False:
    31    # if bool(first_input) == False:
    32    # if not bool(first_input) == True:
    33    # if not bool(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 False
    

    still green, because

    • Python checks if first_input is equal to False when if first_input == False: runs. I can assume the following substitutions

      • if the value of something is False

        something = False
        
        if something       == False
        if bool(something) == False
        if bool(False    ) == False # use the value
        if False           == False # bool(False) returns False
        if True            == True  # write in terms of True
        if True                     # remove '== True'
        if not False                # not False == True
        if not something            # use the name for the value
        
      • if the value of something is True

        something = True
        
        if something       == False
        if bool(something) == False
        if bool(True     ) == False # use the value
        if True            == False # bool(True) returns True
        if False           == True  # write in terms of True
        if not True        == True  # write in terms of True
        if not True                 # remove '== True'
        if not something            # use the name for the value
        
    • Python checks if (second_input) is equal to True when if second_input == True: runs. I can assume the following substitutions

      • if the value of something is False

        something = False
        
        if something       == True
        if bool(something) == True
        if bool(False    ) == True # use the value
        if False           == True # bool(False) returns False
        if not True        == True  # write in terms of True
        if not True                 # remove '== True'
        if False                    # not True == False
        if something                # use the name for the value
        
      • if the value of something is True

        something = True
        
        if something       == True
        if bool(something) == True
        if bool(True     ) == True # use the value
        if True            == True # bool(True) returns True
        if True                    # remove '== True'
        if something               # use the name for the value
        

    this means that

    • if bool(something) == False is the same as if not bool(something) == True is the same as if not bool(something) is the same as if not something.

    • if bool(something) == True is the same as if bool(something) is the same as if 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 not bool(first_input) == True:
    33    # if not bool(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 False
    

    the 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 not bool(first_input) == True:
    33    # if not bool(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
    

    still green because Python checks if first_input is grouped as False when the converse_non_implication function is called. When if not first_input and second_input: runs,

    • if first_input is grouped as True, 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 function

      converse_non_implication(True , True ) -> False
      └── def converse_non_implication(first_input, second_input):
          ├── first_input  == True
          ├── second_input == True
          ├── if not first_input and second_input:
                 return True
          └── else:
              └── return False
      
      converse_non_implication(True , False) -> False
      └── def converse_non_implication(first_input, second_input):
          ├── first_input  == True
          ├── second_input == False
          ├── if not first_input and second_input:
                 return True
          └── else:
              └── return False
      
    • if first_input is grouped as False, it checks if second_input is grouped as True

      • if second_input is 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 function

        converse_non_implication(False, False) -> False
        └── def converse_non_implication(first_input, second_input):
            ├── first_input  == False
            ├── second_input == False
            ├── if not first_input and second_input:
                   return True
            └── else:
                └── return False
        
      • if second_input is grouped as True, it runs return True, which returns True as the output then leaves the function since the return statement is the last thing to run in a function

        converse_non_implication(False, True ) -> True
        └── def converse_non_implication(first_input, second_input):
            ├── first_input  == False
            ├── second_input == True
            └── if not first_input and second_input:
                └── return True
                else:
                    return False
        
    • it only checks second_input if first_input is False.

  • 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 not bool(first_input) == True:
    33    # if not bool(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.

    if (                  vs return True
        not first_input
        and second_input
    ):
        return True       vs if not first_input and second_input
    else:                 vs else
        return False      vs False
    
  • I remove True if and else False to make the simpler return statement

    29def converse_non_implication(first_input, second_input):
    30    # if first_input == False:
    31    # if bool(first_input) == False:
    32    # if not bool(first_input) == True:
    33    # if not bool(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_input

    • if first_input is False

      not first_input
      not False
      True
      
    • if first_input is True

      not 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  # logical_conjunction(False, True)
       False
      
    • 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 # logical_conjunction(False, 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  # logical_conjunction(True, 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 # logical_conjunction(True, False) -> False
       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 not bool(first_input) == True:
    33    # if not bool(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.

    converse_non_implication(False, False) -> False
     └── logical_conjunction(True , False) -> False
    
    converse_non_implication(False, True ) -> True
     └── logical_conjunction(True , True ) -> True
    
    converse_non_implication(True , False) -> False
     └── logical_conjunction(False, False) -> False
    
    converse_non_implication(True , True ) -> False
     └── logical_conjunction(False, True ) -> False
    
  • 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_input
    

    I can use either of these two return statements. Only the first one will run 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_implication in test_binary.py

    30    def test_converse_non_implication(self):
    31        converse_non_implication = (
    32            src.truth_table.converse_non_implication
    33        )
    34        self.assertFalse(
    35            src.truth_table.converse_non_implication(
    36                True, True
    37            )
    38        )
    39        self.assertFalse(
    40            src.truth_table.converse_non_implication(
    41                True, False
    42            )
    43        )
    44        self.assertTrue(
    45            src.truth_table.converse_non_implication(
    46                False, True
    47            )
    48        )
    49        self.assertFalse(
    50            src.truth_table.converse_non_implication(
    51                False, False
    52            )
    53        )
    54
    55
    56# Exceptions seen
    
  • I use the variable to remove repetition of src.truth_table.converse_non_implication

    30    def test_converse_non_implication(self):
    31        converse_non_implication = (
    32            src.truth_table.converse_non_implication
    33        )
    34        self.assertFalse(
    35            # src.truth_table.converse_non_implication(
    36            converse_non_implication(
    37                True, True
    38            )
    39        )
    40        self.assertFalse(
    41            # src.truth_table.converse_non_implication(
    42            converse_non_implication(
    43                True, False
    44            )
    45        )
    46        self.assertTrue(
    47            # src.truth_table.converse_non_implication(
    48            converse_non_implication(
    49                False, True
    50            )
    51        )
    52        self.assertFalse(
    53            # src.truth_table.converse_non_implication(
    54            converse_non_implication(
    55                False, False
    56            )
    57        )
    58
    59
    60# Exceptions seen
    

    the test is still green.

  • I remove the commented lines

    30    def test_converse_non_implication(self):
    31        converse_non_implication = (
    32            src.truth_table.converse_non_implication
    33        )
    34        self.assertFalse(converse_non_implication(True, True))
    35        self.assertFalse(converse_non_implication(True, False))
    36        self.assertTrue(converse_non_implication(False, True))
    37        self.assertFalse(converse_non_implication(False, False))
    38
    39
    40# Exceptions seen
    41# AttributeError
    42# TypeError
    43# AssertionError
    
  • I 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_input

  • the 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.py and truth_table.py

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

    cd ..
    

    the terminal shows

    .../pumping_python
    

    I am back in the pumping_python directory.


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

  • Converse Non-Implication

    first input

    second input

    return

    True

    True

    False

    True

    False

    False

    False

    True

    True

    False

    False

    False

    • returns not first_input and second_input

    • returns True only if first_input is False and second_input is True

    • is the Logical Negation (NOT) of Converse Implication which returns False if first_input is False and second_input is True

  • Project Second

    first input

    second input

    return

    True

    True

    True

    True

    False

    False

    False

    True

    True

    False

    False

    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_input

    • returns True only if first_input is True and second_input is True

    • is the Logical Negation (NOT) of Logical NAND which returns False only if first_input is True and second_input is True

  • Contradiction

    first input

    second input

    return

    True

    True

    False

    True

    False

    False

    False

    True

    False

    False

    False

    False

and

One logic statement has been written with and, another was written with both and and not.

return

True, True

True, False

False, True

False, False

name of operation

False

False

False

False

False

contradiction

first and second

True

False

False

False

logical_conjunction

second

True

False

True

False

project_second

(not first) and second

False

False

True

False

converse_non_implication


code from the chapter

Do you want to see all the CODE I typed in this chapter?


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.