0

this code was provided in an answer that I found, but there was no explanation. I'm wondering why the 'not message' need to be included in order for this to work?

def first_and_last(message):
    if not message or message[0] == message[-1]:
        return True
    else:
        return False
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
  • 2
    presumably, because `message` could be empty, in whichc ase, `message[0]` and `message[-1]` would throw index errors. Note, this is bad style, this should just be written as `return not message or message[0] == message[-1]`, the if-else branch is uncessary – juanpa.arrivillaga Oct 19 '20 at 21:32
  • 1
    The reason why `not message` is on the left-hand side is because of the concept of [short circuiting](https://stackoverflow.com/questions/9344305/what-is-short-circuiting-and-how-is-it-used-when-programming-in-java). – Random Davis Oct 19 '20 at 21:34
  • @juanpa.arrivillaga because of the way Python evaluates `a or b` your shortcut isn't a rule you can follow blindly. In this case it works because both sides of the expression are boolean, but if that wasn't the case you wouldn't necessarily return `True` or `False`. – Mark Ransom Oct 19 '20 at 21:38
  • @MarkRansom yes, this is true, but almost *never* have I *ever* had to explicitly do `if condition: return True; else: return False`. Worst case, just do `return bool(condition)`, although that I've never had to do. – juanpa.arrivillaga Oct 19 '20 at 21:40

3 Answers3

2

If message happens to be an empty list [] then you will throw an IndexError because message[0] and message[-1] do not exist in the list.

Generally, if not checks to see if something is Truthy or Falsey. (A great example of what is falsey is here)

In this example, if you pass [] which happens to be falsey, it will trigger the boolean comparison and since comparisons like or are lazy loaded, it will not even check message[0] == message[-1] which would throw an error.

If you know that message always be a list and will never be Falsey (i.e. None, [], '', etc.) then you do not need it.

JoeShiro
  • 31
  • 4
0

It depends what "message" is. I'll assume it's a list.

Firstly, if list means "is len(var)!=0". So if not list means "is len(var)==0"

Then message [0] is the first element in the list. And message [-1] is the last.

If these are == (equal to each other) then return true. Otherwise return false.

So essentially this code says "if the length is empty OR the first and last element are equal, return true"

Liam
  • 116
  • 1
  • 1
  • 8
0
def first_and_last(message):
    if not message or message[0] == message[-1]:
        return True
    else:
        return False

The function you wrote returns True, if message is 'empty' or first ([0]) and last ([-1]) character (or item, it could be list/tuple as well) of the message are the same; otherwise returns False.

Specifically if not message piece you are asking about checks whether parameter message is not 0, "", None and so on. That keeps you safe from IndexError: string index out of range too, so that you wouldn't call an item when there is no list/tuple at all.

Analyze the following:

def test(message):
    if not message:
        print("Foo")
    else:
        print("Bar")

if __name__ == "__main__":
    message = ""
    test(message)

When you run this code, "Foo" will be printed. Type in some characters between the quotation marks in message and "Bar" will appear.

mrkhrova
  • 86
  • 5