<h4>Разное</h4>
- Python - строго типизированный язык. 
- Оператор "is" проверяет значение и тип.
- Декоратор - это функция, которая принимает одну функцию в качестве аргумента и возвращает другую.
<h4>Объекты</h4>
- Имя - это ссылка на объект, но не сам объект.
- В случае, когда оба имени указывают на изменяемый объект, его можно изменить с помощью любого имени.
**Объект содержит:**
- тип
- id
- значение
- счетчик ссылок
<h4>Типы данных</h4>
**Неизменяемые типы данных:**
- int
- bool
- float
- string
- complex
- tuple
- bytes
- frozenset
**Изменяемые типы данных:**
- list
- dict
- set
- bytearray

<h6>Классы</h6>
* Результат вызова класса - экземпляр класса.
* Методы работы с атрибутами - `getattr, setattr, hasattr`

```python
__mro__ # возвращает картеж родетельских классов
```
<h6>Миксины</h6>
`Mixin` — это класс, предоставляющий реализации методов для повторного использования дочерними классами. Он представляет ограниченную форму множественного наследования и родительский класс, который просто даёт функциональные возможности подклассам, не содержит состояния и не предназначен для создания экземпляров.

Когда использовать миксины? Они подходят, когда хочется:
* предоставить множество дополнительных функций для класса
* использовать определённую функцию во множестве разных классов
<h6>@property</h6>
```python
class C:
    def __init__(self):
        self._x = None

    @property
    def x(self): # В декораторах 'setter' и 'deleter' нужно указывать имя метода-свойства
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x
```
<h6>@classmethod</h6>
**@classmethod** – это метод, который получает класс в качестве неявного первого аргумента, точно так же, как обычный метод экземпляра получает экземпляр. Это означает, что вы можете использовать класс и его свойства внутри этого метода, а не конкретного экземпляра.
**@classmethod** используется, когда вам нужно получить методы, не относящиеся к какому-либо конкретному экземпляру, но тем не менее, каким-то образом привязанные к классу. Самое интересное в них то, что их можно переопределить дочерними классами.

```python
class A():
    count = 0
    
    def __init__(self):
        A.count += 1

	def exclaim(self):
        print('I`m an A!')

    @classmethod
    def kids(cls):
        print("A has", cls.count, "little objects.")

def test_classmethod():
    easy_a = A()
    breezy_a = A()
    wheezy_a = A()
    A.kids()
```
<h6>@staticmethod</h6>
@staticmethod – используется для создания метода, который ничего не знает о классе или экземпляре, через который он был вызван. Он просто получает переданные аргументы, без неявного первого аргумента, и его определение неизменяемо через наследование.

```python
class CoyoteWeapon():
    @staticmethod
    def commercial():
        print('This CoyoWeapon has been brought to you by Acme')

CoyoteWeapon.commercial()
```
<h4>Полезные фичи</h4>
* Фуyкция divmod возвращает частное и остаток
```python
>>> divmod(9, 5)
(1, 4)
```
<h4>Строки</h4>
**Модуль string содержит строковые константы:**
```python
import string 

>>> string.whitespace
' \t\n\r\x0b\x0c'
>>> string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
```
<h4>Бинарные данные</h4>
* bytes  - картеж байтов (неизменяемый тип)
* bytearray - список байтов (изменяемый тип)