Метаклассы могут изменять тип словаря в котором хранятся атрибуты класса через метод
__prepare__В отличие от декораторов метаклассы наследуются потомками, т.е. не нужно каждый раз декорировать потомков для реализации задуманного поведения
Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why).— Тим Питерс
В стандартной библиотеке есть модуль
abc, который с помощью metaclass-ов позволяет писать абстрактные классы в pythonimport abcclass Iterable(metaclass=abc.ABCMeta): @abc.abstractmethod def __iter__(self): passclass Something(Iterable): pass>>> Something()TypeError: Can't instantiate abstract class Something with abstract methods __iter__Модуль
collections.abc содержит абстрактные базовые классы для различных коллекцийНапример, чтобы реализовать словарь запоминающий только последние несколько элементов и чтобы методы
setdefault и аналогичные работали, необходимо его унаследовать от MutableMapping и реализовать методы: __getitem__, __setitem__, __delitem__, __iter__, __len__ABC позволяет удобно проверять реализует ли коллекция необходимый функционал:
from collections import abcissubclass(list, abc.Sequence) # == Trueissubclass({}, abc.Hashable) # == Falsedef factorial(n): """Return the factorial of n, an exact integer >= 0. >>> [factorial(n) for n in range(6)] [1, 1, 2, 6, 24, 120] >>> factorial(30) 265252859812191058636308480000000 """ import math result = 1 factor = 2 while factor <= n: result *= factor factor += 1 return resultif __name__ == "__main__": import doctest doctest.testmod()import unittestclass TestHomework(unittest.TestCase): def test_2plus2(self): self.assertEqual(2 + 2, 5)if __name__ == "__main__": unittest.main()self.assertEqual(a, b)self.assertTrue(b)self.assertFalse(b)with self.assertRaises(TypeError): s.split(10)