====== Модули и пакеты. ООП ======
===== Модули и пакеты =====
**Любой файл с кодом**, является модулем. Импортированный модуль может содержать программу на С.\\
Запускаемый модуль всегда называется **__main__**, доступно через атрибут "__name__"\\
==== import ====
import <название модуля> [as <Псевдоним>]\\
Название без расширения и т.д., создается одноименный идентификатор, наравне с переменными, через который в дальнейшем и доступно содержимое модуля.\\
Проверить существование атрибута- **hasattr()**\\
Перед выполнением каждый модуль компилируется в байт-код, откомпилированные файлы (*.pyc) хранятся в **__pycache__**, их тоже можно импортировать и использовать\\
Импорт производится при первом вызове, затем кэшируется в **sys.modules**\\
**__import__('str')** - динамический импорт, название из строки (переменной)\\
==== from ====
Для импортирования только определенных идентификаторов\\
**from <модуль> import <идентификатор> or (id1, id2 ..)**\\
==== Пути поиска модулей ====
Хранятся в переменной **sys.path**. Можно изменять программно- append()\\
* папка со скриптом
* переменная окружения **PYTHONPATH**
* пути к стандартным модулям
* содержимое в файлах ** *.pth **
==== Повторная загрузка модулей ====
Импортируется один раз, для повторной загрузки ф-я **imp.reload()**\\
==== Пакеты ====
Папка с модулями, в которой расположен файл инициализации **__init__.py**- может быть пустым либо содержать код для первой инициализации при импортировании любого модуля из этого пакета\\
===== Объектно-ориентированное программирование =====
В отличии от функционального подхода, позволяет описать предметы мира в виде сущностей и организовать связи между ними.\\
==== Определение класса, создание экземпляра ====
class <Название класса> [(<родит. классы>,...<..>)]:
""" Строка документирования """
<Св-ва / Методы>
В момент описания, **создается полноценный объект**. Выполнение **происходит в месте определения** а не создания экземпляров\\
Всем методам, обязательно, первым параметром **передается ссылка на экземпляр** класса (**self**), либо вызывать ф-ю из объекта\\
Все атрибуты и методы являются **public**, можно закрывать костылями\\
* **getattr(, , =)** - значение атрибута, либо исключение, название можно формировать динамически
* **setattr()** - установить значение, если атрибут не существует, то будет создан
* **delattr() / hasattr()** - удалить / проверка существования
Атрибуты классу (не объекту а именно классу) **можно создавать в коде, динамически** (собсна функции выше)\\
class MyClass:
pass
MyClass.x= 50
c1, c2= MyClass(), MyClass()
c1.y= 10
c2.y= 20
print(c1.x, c1.y) # 50 10
print(c2.x, c2.y) # 50 20
==== __init__()/__del__() ====
Конструктор/Деструктор (в скриптовой специфике python, последний особо смысла не имеет)\\
==== Наследование ====
Вроде ничего необычного, public-наследование..\\
Конструктор базового класса можно переопределять в производном\\
==== Множественное наследование ====
В случае пересечения названий, порядок поиска соответствует порядку перечисления классов в описании\\
=== Примеси и их использование ===
Что то вроде понятия абстрактного класса\\
class myMixin: # Класс "примеси"
attr= 0 # Атрибут такого класса
def mix_met(self):
pass
class Class1 (MyMixin):
def meth1():
pass
class Class2 (Class1, MyMixin):
...
==== Специальные методы ====
В основном благодаря им можно переопределить (перегрузить) стандартные функции, типа преобразования, проверка длинны и т.д., такие как: __call__() (типа д-е по умолчанию, при вызове объекта без методов), __getattr__ (set/del), __bool__(), __int__(), __float__() и т.д.\\
==== Перегрузка операторов ====
Аналогично, целый ряд спец функций для этого: __add__(), __sub__(), __mul__() и т.д. оч много..\\
==== Статические методы и методы класса ====
Статические методы создаются с помощью декоратора "@staticmethod". При вызове такого, self указывать собсна не нужно\\
Методы класса, декоратор "@classmethod", первым параметром передается ссылка на класс\\
class MyClass:
@staticmethod # Декоратор
def func1(): # Статический метод
pass
def func2(): # Обычный метод
pass
==== Абстрактные методы ====
Абстрактные классы содержат только определения методов, без реализации\\
Для верности можно вызывать исключение в функции\\
Так же есть декоратор "@abstractmethod"
class Class1:
def func1(self, x): # Абстрактный метод
raise NotImplementedError("Необходимо переопределить метод")
==== Декораторы классов ====
Аналогично декораторам функций\\
def deco(C):
...
return C
@deco
class MyClass:
def __init__(self, value):
self.v= value
c= myClass(5)
print(c.v)