{"id":"logic-not","slug":"not","title":"Turning a condition around: not","text":"The operator `not` turns a condition around: `not` of something true is false, and `not` of something false is true.\n\n```pycon\n>>> not True\nFalse\n>>> not False\nTrue\n>>> not 3 > 5\nTrue\n```\n\nPython works out the comparison before `not`, so `not 3 > 5` means `not (3 > 5)`. Often `not` is handy in front of a combined condition in parentheses. In the step about `or`, `day == \"Saturday\" or day == \"Sunday\"` checked for the weekend. With `not` in front, the same condition checks for a weekday:\n\n```python\nday = \"Tuesday\"\nif not (day == \"Saturday\" or day == \"Sunday\"):\n    print(\"The library opens at 8 today.\")\n```\n\n```output\nThe library opens at 8 today.\n```\n\nThe parentheses matter here: without them, the `not` would turn around only the first comparison, and the condition would be true on Sundays too.\n\n### Truth values in variables\n\nYou saw in part 1 that the value of a comparison, `True` or `False`, can be stored in a variable like any other value. With `not`, such a variable reads almost like English:\n\n```python\nanswer = input(\"Is the door locked? (yes/no) \")\nlocked = answer == \"yes\"\nif not locked:\n    print(\"Remember to lock the door!\")\nprint(\"Good night.\")\n```\n\n```input\nno\n```\n\n```output\nIs the door locked? (yes/no) no\nRemember to lock the door!\nGood night.\n```\n\nThe line `locked = answer == \"yes\"` first evaluates the comparison, then stores its value in `locked`. Here that value is `False`, so `not locked` is `True`.\n\n### Which goes first\n\nWhen a condition mixes the operators, Python groups it as if there were parentheses around each comparison first, then around each `not`, then around each `and`, with `or` last. So `a or b and c` means `a or (b and c)`, which can surprise you. (The grouping only decides which parts belong together. Python still reads the condition from left to right.) Children under 12 and seniors 65 or older should get a discount, but not on Sundays:\n\n```python\nage = 8\nday = \"Sunday\"\nif age < 12 or age >= 65 and day != \"Sunday\":\n    print(\"Discount price\")\nelse:\n    print(\"Full price\")\n```\n\n```output\nDiscount price\n```\n\nBecause `and` is grouped before `or`, Python reads the condition as `age < 12 or (age >= 65 and day != \"Sunday\")`, and a child gets the discount every day. Parentheses say what is meant: `(age < 12 or age >= 65) and day != \"Sunday\"`. When a condition mixes `and` and `or`, add parentheses even where they aren't needed. They make the condition easier to read.\n","task":"Drum practice is allowed from 8 to 21 o'clock. Fill in the blank so the program asks for quiet at every other hour:\n\n```\nHour: 23\nQuiet hours, no drums please.\n```\n","kind":"fill","seed":"hour = int(input(\"Hour: \"))\nif [[not]] (hour >= 8 and hour <= 21):\n    print(\"Quiet hours, no drums please.\")\nelse:\n    print(\"Go ahead and practice!\")\n","solution":"hour = int(input(\"Hour: \"))\nif not (hour >= 8 and hour <= 21):\n    print(\"Quiet hours, no drums please.\")\nelse:\n    print(\"Go ahead and practice!\")\n","hints":["The condition in parentheses is true during practice hours, but the first message is for the other hours.","Turn the whole condition around with `not`."],"tests":[{"name":"Test 1","stdin":"23\n","expect":"Hour: 23\nQuiet hours, no drums please.","hidden":false},{"name":"Test 2","stdin":"8\n","expect":"Hour: 8\nGo ahead and practice!","hidden":true},{"name":"Test 3","stdin":"21\n","expect":"Hour: 21\nGo ahead and practice!","hidden":true},{"name":"Test 4","stdin":"7\n","expect":"Hour: 7\nQuiet hours, no drums please.","hidden":true},{"name":"Test 5","stdin":"15\n","expect":"Hour: 15\nGo ahead and practice!","hidden":true}],"require":[],"forbid":[],"more":[{"task":"What does this program print? Type each line it prints.\n","kind":"predict","seed":"a = True\nb = False\nprint(not a)\nprint(a and not b)\nprint(not a or b)\nprint(not (a or b))\n","solution":"a = True\nb = False\nprint(not a)\nprint(a and not b)\nprint(not a or b)\nprint(not (a or b))\n","hints":["`not` goes before `and` and `or`, so in `a and not b` the `not` belongs to `b` only.","`not a or b` means `(not a) or b`: both sides are `False`.","In the last line the parentheses come first: `a or b` is `True`, and `not` turns it around."],"tests":[{"name":"Output","stdin":"","expect":"False\nTrue\nFalse\nFalse","hidden":false}],"require":[],"forbid":[],"lines":["False","True","False","False"]},{"task":"Children under 12 and seniors 65 or older get a discount, but never on Sundays. The program below gives a child the discount on Sundays too. Fix the condition.\n\n```\nAge: 8\nDay: Sunday\nFull price: 10 euros\n```\n","kind":"code","seed":"age = int(input(\"Age: \"))\nday = input(\"Day: \")\nif age < 12 or age >= 65 and day != \"Sunday\":\n    print(\"Discount price: 5 euros\")\nelse:\n    print(\"Full price: 10 euros\")\n","solution":"age = int(input(\"Age: \"))\nday = input(\"Day: \")\nif (age < 12 or age >= 65) and day != \"Sunday\":\n    print(\"Discount price: 5 euros\")\nelse:\n    print(\"Full price: 10 euros\")\n","hints":["`and` goes before `or`, so Python groups the condition as `age < 12 or (age >= 65 and day != \"Sunday\")`.","The two age checks belong together. Put parentheses around them, so the day check applies to both."],"tests":[{"name":"Test 1","stdin":"8\nSunday\n","expect":"Age: 8\nDay: Sunday\nFull price: 10 euros","hidden":false},{"name":"Test 2","stdin":"8\nMonday\n","expect":"Age: 8\nDay: Monday\nDiscount price: 5 euros","hidden":true},{"name":"Test 3","stdin":"70\nSunday\n","expect":"Age: 70\nDay: Sunday\nFull price: 10 euros","hidden":true},{"name":"Test 4","stdin":"65\nFriday\n","expect":"Age: 65\nDay: Friday\nDiscount price: 5 euros","hidden":true},{"name":"Test 5","stdin":"30\nTuesday\n","expect":"Age: 30\nDay: Tuesday\nFull price: 10 euros","hidden":true}],"require":[],"forbid":[]}]}