Why does Python start at index -1 (as opposed to 0) when indexing a list from the end?

    list = ["a", "b", "c", "d"]
    print(list[3]) # Number 3 is "d"

    print(list[-4]) # Number -4 is "a"

To explain it in another way, because -0 is equal to 0, if backward starts from 0, it is ambiguous to the interpreter.

If you are confused about -, and looking for another way to index backwards more understandably, you can try ~, it is a mirror of forward:

    arr = ["a", "b", "c", "d"]
    print(arr[~0])   # d
    print(arr[~1])   # c

The typical usages for ~ are like "swap mirror node" or "find median in a sort list":

    """swap mirror node"""
    def reverse(arr: List[int]) -> None:
        for i in range(len(arr) // 2):
            arr[i], arr[~i] = arr[~i], arr[i]

    """find median in a sort list"""
    def median(arr: List[float]) -> float:
        mid = len(arr) // 2
        return (arr[mid] + arr[~mid]) / 2

    """deal with mirror pairs"""
    # verify the number is strobogrammatic, strobogrammatic number looks the same when rotated 180 degrees
    def is_strobogrammatic(num: str) -> bool:
        return all(num[i] + num[~i] in '696 00 11 88' for i in range(len(num) // 2 + 1))

~ actually is a math trick of inverse code and complement code, and it is more easy to understand in some situations.

Discussion about whether should use python tricks like ~:

In my opinion, if it is a code maintained by yourself, you can use any trick to avoid potential bug or achieve goal easier, because of maybe a high readability and usability. But in team work, avoid using 'too clever' code , may bring troubles to your co-workers.

For example, here is one concise code from Stefan Pochmann to solve this problem. I learned a lot from his code. But some are just for fun, too hackish to use.

    # a strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down)
    # find all strobogrammatic numbers that are of length = n
    def findStrobogrammatic(self, n):
        nums = n % 2 * list('018') or ['']
        while n > 1:
            n -= 2
            # n < 2 is so genius here
            nums = [a + num + b for a, b in '00 11 88 69 96'.split()[n < 2:] for num in nums]
        return nums

I have summarized python tricks like this, in case you are interested.

From: stackoverflow.com/q/55684960

Back to homepage or read more recommendations: