Thanks for your comment, I think you are right. If you pass a string to foo() you also get some unexpected behavior. You already posted a remedy to the situation: checking the type of the data argument. That made me think, if there are other ways, that do not rely on type checking. (I know, type checking is not an expensive operation, but still...)
Two more ways, you could alleviate the situation: Working with conventions, if the caller does not respect the contract, they get unexpected behavior:
"""This function expects a list."""
Using type hinting: Since Python 3.5 you can specify the type of arguments, and static type checkers can use this information, to determine if you pass the correct types.
def foo(data: list) -> None:
We're a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.