liveBook · Manning

__setitem__

As explained in The Quick Python Book, Fourth Edition

__setitem__ is a Python special method that defines how an object responds when an item or slice is assigned with subscription syntax.

`__setitem__` defines what happens when an object is assigned through subscription syntax: `obj[index] = value`. Python calls the method automatically. Define it when a custom object needs to accept, validate, or redirect item assignments. section 17.7.2 section 17.8

Assigning to a typed list

A `TypedList` can check an incoming element before storing it in an underlying list: `x[2] = "Hello"` calls `__setitem__`, which checks the type and then assigns to `self.elements[2]`. Reading `x[2]` is a separate job for `__getitem__`. section 17.8

class TypedList:
   def __init__(self, example_element, initial_list=[]):
       self.type = type(example_element)
       if not isinstance(initial_list, list):
           raise TypeError("Second argument of TypedList must " 
                           "be a list.")
       for element in initial_list: 
           self.__check(element)
       self.elements = initial_list[:]
   def __check(self, element):
       if type(element) != self.type:
           raise TypeError("Attempted to add an element of " 
                           "incorrect type to a typed list.")
   def __setitem__(self, i, element):
       self.__check(element)
       self.elements[i] = element
   def __getitem__(self, i):
       return self.elements[i]

The implementation places the type check immediately before assignment to the stored list. section 17.8

Subclassing a built-in collection avoids reimplementing its other operations. An overriding `__setitem__` can check a value, then call `super().__setitem__(index, value)`. Assignment alone is not the whole collection interface: a custom list also needs other methods, and slice assignment needs explicit handling. section 17.9.1 section 17.8

Restricting dictionary entries

A `dict` subclass can reject a key or value that is not a string, raise `TypeError`, and delegate valid assignments to the parent method. Do not rely on `__setitem__` alone to validate construction from another dictionary or key-value tuples: those paths can bypass it. Check existing entries in an overridden `__init__` as well. section 17.11 section 17.11.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 dictionary example checks assignments in `__setitem__` and entries supplied at construction in `__init__`. section 17.11.2

How The Quick Python Book, Fourth Edition covers it

How deep it goes
Works through validation and parent-method delegation, then identifies construction bypasses and deferred slice handling.
Examples
Uses typed-list assignments and a string-only dictionary with constructor checks.
What it assumes
Assumes familiarity with classes and indexing while explaining when Python calls the special method.
What you can do after
Build it from scratch in a typed-list wrapper, or apply it through subclassing to validate assignments.
How it connects
Links subscription assignment to __getitem__, built-in type subclassing, type checking, and __init__.

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.