liveBook · Manning

Type error

As explained in The Quick Python Book, Fourth Edition

TypeError is a Python built-in exception class raised when an operation or function receives a value of an inappropriate type.

TypeError is Python’s built-in exception for an operation or function given an inappropriate type. It is useful when enforcing an input requirement: a function expecting an iterable can raise TypeError if its argument is not iterable, while a dictionary subclass can raise it when a key or value is not a string. section 14.4.2 section 17.11.2

Python associates types with objects, not variables. A variable can refer to a string and later to an integer, so assigning a value of an unintended type is not itself rejected. Type hints and testing can help find mismatches; a runtime check can raise TypeError when a particular operation requires a particular type. section 1.3.2 section 17.11.2

Reject a non-string dictionary entry

In a dict subclass, `__setitem__` can check `isinstance(key, str)` and `isinstance(value, str)`, raising `TypeError('key is not a string')` or `TypeError('value is not a string')` before calling `super().__setitem__(key, value)`. Check `__init__` too: entries supplied when the instance is created must satisfy the same rule. section 17.11.2

Choose the exception for the failed requirement, rather than adding checks indiscriminately. An input that is not iterable calls for TypeError; an invalid positive-integer argument is treated separately with ValueError. Catching TypeError also requires care: in a word-counting loop, merely catching an unhashable key and then using that key again does not skip it. section 14.4.2

""" Create a dictionary that allows only strings for keys and values"""
 
class StringDict(dict):
    def __setitem__(self, key, value):
        if not isinstance(key, str):
            raise TypeError('key is not a string')     #1
        if not isinstance(value, str):
            raise TypeError('value is not a string')
        super().__setitem__(key, value)
 
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        key_error = any(not isinstance(_, str) 
                         for _ in self.keys())         #2
        if key_error:
            raise TypeError('key is not a string')
        value_error = any(not isinstance(_, str) 
                         for _ in self.values())       #2
        if value_error:
            raise TypeError('value is not a string')

The complete subclass shows separate checks for item assignment and entries supplied during initialization. section 17.11.2

How The Quick Python Book, Fourth Edition covers it

How deep it goes
Works through explicit checks, raising, and catching TypeError; does not examine exception internals.
Examples
Demonstrates non-iterable input, unhashable dictionary keys, and non-string keys or values in a dictionary subclass.
What it assumes
Assumes familiarity with functions and dictionaries while explaining that Python variables are not bound to one object type.
What you can do after
Build it from scratch: validate a string-only dictionary on both assignment and initialization, raising TypeError for invalid entries.
How it connects
Connects TypeError to dynamic typing, type hints, exception handling, and dictionary subclassing.

Also explained in

Compare how 2 books explain type error →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Quick Python Book, Fourth Edition. The section links point to the parts of the book it draws on.