<jupyter_start><jupyter_text>Goose typing Python doesn’t have an interface keyword. We use Abstract BaseClasses (ABCs) to define interfaces for explicit type checking at runtime—but also supported by static type checkers.The Python Glossary entry for abstract base class has a good explanation ofthe value they bring to duck-typed languages Goose typing is a runtime type checking approach that leverages ABCs.<jupyter_code>class Struggle:

    def __len__(self): return 23
from collections import abc

isinstance(Struggle(), abc.Sized)<jupyter_output><empty_output><jupyter_text>Subclassing an ABC Example 13-6. frenchdeck2.py: FrenchDeck2, a subclass ofcollections.MutableSequence<jupyter_code>from collections import namedtuple, abc

Card = namedtuple('Card', ['rank', 'suit'])

class FrenchDeck2(abc.MutableSequence):
    ranks = [str(n) for n in range(2, 11)] + list('JQKA')
    suits = 'spades diamonds clubs hearts'.split()

    def __init__(self):
        self._cards = [Card(rank, suit) for suit in self.suits
                                      for rank in self.ranks]
    def __len__(self):
        return len(self._cards)

    def __getitem__(self, position):
        return self._cards[position]

    def __setitem__(self, position, value):
        self._cards[position] = value

    def __delitem__(self, position):
        del self._cards[position]

    def insert(self, position, value):
        self._cards.insert(position, value)<jupyter_output><empty_output><jupyter_text>ABCs in the Standard LibrarySince Python 2.6, the standard library provides several ABCs. Most aredefined in the collections.abc module, but there are others. Defining and Using an ABC Example 13-7 shows the definition of the Tombola ABC.Example 13-7. tombola.py: Tombola is an ABC with two abstract methodsand two concrete methods<jupyter_code>import abc

class Tombola(abc.ABC):

    @abc.abstractmethod
    def load(self, iterable):
        """Add items from an iterable."""

    @abc.abstractmethod
    def pick(self):
        """Remove item at random, returning it.
        This method should raise `LookupError` when the instance is
        empty.
        """
    def loaded(self):
        """Return `True` if there's at least 1 item, `False`
        otherwise."""
        return bool(self.inspect())
    def inspect(self):
        """Return a sorted tuple with the items currently
        inside."""
        items = []
        while True:
            try:
                items.append(self.pick())
            except LookupError:
                break
            self.load(items)
            return tuple(items)
class Fake(Tombola):

    def pick(self):
        return 13

Fake
f = Tombola()<jupyter_output><empty_output><jupyter_text>Example 13-9. bingo.py: BingoCage is a concrete subclass of Tombola<jupyter_code>import random

class BingoCage(Tombola):

    def __init__(self, items) -> None:
        self._randomizer = random.SystemRandom()
        self._items = []
        self.load(items)

    def load(self, items) -> None:
        self._items.extend(items)
        self._randomizer.shuffle(self._items)

    def pick(self):
        try:
            return self._items.pop()
        except IndexError:
            raise LookupError('pick from empty BingoCage')
        
    def __call__(self) -> None:
        self.pick()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09196428571428572, 'fraction_numerical': 0.00744047619047619, 'mean_word_length': 2.9728132387706854, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '377019', 'license': 'MIT', 'n_tokens_mistral': 994, 'n_tokens_neox': 952, 'n_words': 306, 'path': 'chapter 13-Interfaces, Protocols, and ABCs/example 13-6-Goose typing.ipynb', 'repo_name': 'Jalilnkh/KartalOl-Fluent-Python-2022', 'size': '3360'}