1

I have 2 code segments to check data types of function arguments.

1st one uses typing

def write_str(str1: str, file1_str: str):

    return None

2nd one uses assert.

def write_str(str1, file1_str):
    assert (type(str1) == str and type(file1_str) == str)

    return None 

Does python typing make the use of assert checking unnecessary? Which code segment catches bug better?

I'm using python v3.7

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
user1315789
  • 3,069
  • 6
  • 18
  • 41
  • 2
    Using type annotations is good documentation; it also lets you lint your code and IDEs can help. It doesn't 'catch' bugs in any real sense. Asserts are nuclear and also don't generally provide useful info. Python isn't strongly typed and you'll never catch type-related bugs 100% of the time. – erip May 15 '20 at 14:51
  • 4
    They run at totally different times - the type annotations are used when the code is checked by e.g. mypy, the assertion is at runtime (unless [disabled](https://stackoverflow.com/q/1273211/3001761)). – jonrsharpe May 15 '20 at 14:53
  • @erip, do you think it's good practice in python to catch data type errors in function argument using assert? – user1315789 May 15 '20 at 14:53
  • @jonrsharpe, is it possible for mypy to catch the data type error before assert does? – user1315789 May 15 '20 at 14:54
  • It's useful to add type annotations (both parameters and return types) to your function signatures and to incorporate mypy or similar to check your code before it's executed. If you're principled about type annotations, this will save headaches. It's not a silver bullet, though - you can incorrectly document the types. – erip May 15 '20 at 14:54
  • 2
    That doesn't really make sense as a question. If mypy *can* catch it it will definitely be before assert does, assuming you're running the type checking before deploying the code. As for whether it's good practice, I'd recommend (indeed [have recommended](https://stackoverflow.com/a/25885433/3001761)) not type checking with `assert` but instead throwing a proper TypeError (or allowing one to be thrown by not checking at runtime at all). – jonrsharpe May 15 '20 at 14:56
  • @jonrsharpe, thanks. Good suggestion. Throwing exception is better idea. – user1315789 May 15 '20 at 14:59
  • 1
    Python code typically does not worry about runtime typechecking. Instead, duck typing is used: if `str1` provides a value consistent with how `str1` will be used, it does not matter what the actual type is. – chepner May 15 '20 at 15:15

2 Answers2

4

The annotation method (1st) does not throw an error when the wrong type is passed.

Thus the second method is better, however it can still be improved:

def write_str(str1, file1_str):
    assert (isinstance(str1, str) and isinstance(file1_str, str))

    return None 

Which will also work if you pass an object that inherited from str. Although not really relevant here, isinstance is generally recommended over type.

Edit:

The correct way to deal with an invalid type would be to throw a type error:

def write_str(str1: str, file1_str: str):
    if not isinstance(str1, str) and isinstance(file1_str, str):
        raise TypeError(
            f"The function 'write_str' expects two strings. Instead got: {type(str1)=}, {type(file1_str)=}."
        )
    # normal continuation
1

From PEP 3107, Fundamentals of Function Annotations, p. 2:

By itself, Python does not attach any particular meaning or significance to annotations. Left to its own, Python simply makes these expressions available as described in Accessing Function Annotations below.

Annotations do nothing with poor python, but they are used by other python's official project called mypy.

What is mypy:

Mypy is an optional static type checker for Python. You can add type hints (PEP 484) to your Python programs, and use mypy to type check them statically. Find bugs in your programs without even running them!

In short, it is a CLI that parses your code without running it and returns a list of errors when types do not match. Main goal of this tool is to improve quality of code, it is commonly used with other quality control tools like linters and formatters.

validname
  • 1,376
  • 15
  • 22