Фишки Python
29 subscribers
2 photos
3 files
29 links
Всё что ты хотел узнать, но ленился спросить.

Декораторы, итераторы и контракты.
Download Telegram
Метаклассы могут изменять тип словаря в котором хранятся атрибуты класса через метод __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-ов позволяет писать абстрактные классы в python
import abc

class Iterable(metaclass=abc.ABCMeta):
@abc.abstractmethod
def __iter__(self):
pass

class 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 abc
issubclass(list, abc.Sequence) # == True
issubclass({}, abc.Hashable) # == False
Тестирование
doctest
def 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 result


if __name__ == "__main__":
import doctest
doctest.testmod()
assert
def test_2plus2():
assert 2 + 2 == 5, 'Error not equals'
unittest
import unittest

class 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)
python -m unittest test_module.py
Запуск всех тестов в текущей папке:

python -m unittest .