Base.__init__(self, single_value, single_value)




 

test_derived = Derived(12)

 

print(test_derived.calculate_sum())

 

 

— или можно вместо

Base.__init__(self, single_value, single_value)

писать

super().__init__(single_value, single_value)

— не называя специально родительский класс.

 

хак: многострочные комментарии пишутся с тремя кавычками в начале и в конце:

""" Multi-line comment

Second line

Third line

Blah-blah-blah """

 

 

Полиморфизм

— мы переопределяем поведение (отдельных) методов, унаследованных от родительского класса

 

например, переопределим метод «вычислить», заменив сложение на вычитание:

 

class Base:

def __init__(self, value_1, value_2):

self._value_1 = value_1

self._value_2 = value_2

 

def calculate(self):

return self._value_1 + self._value_2

 

class Derived(Base):

 

def calculate(self):

Return self._value_1 - self._value_2

 

test_derived = Derived(10, 2)

 

print(test_derived.calculate())

 

+ теперь мы можем сделать функцию, которая будет пользоваться одним и тем же интерфейсом, а реализация будет уже прописана внутри классов:

 

class Base:

def __init__(self, value_1, value_2):

self._value_1 = value_1

self._value_2 = value_2

 

def calculate(self):

return self._value_1 + self._value_2

 

class Derived(Base):

 

def calculate(self):

return self._value_1 - self._value_2

 

def print_calculation(object_to_calculate):

Print(object_to_calculate.calculate())

 

test_base = Base(10, 2)

test_derived = Derived(10, 2)

 

Print_calculation(test_base)

Print_calculation(test_derived)

 

 

можно переопределять операторы, например, «==» (сравнение) — ему соответствует метод __eq__():

 

class Class:

 

...

 

def __eq__ (self, other):

if other.a > self.a:

return True

else:

return False

 

instance_1 = Class(1, 2)

instance_2 = Class(1, 5)

 

if instance_1 == instance_2:

print("Equal")

 

 

==============

Марта — хакатон

 

PIP — установка модулей (скачивает и устанавливает):

pip install X

 

можно для конкретного проекта сделать тестовое окружениевиртуальный «контейнер», в котором будут именно те библиотеки именно в тех версиях, которые нужны.

virtualenv — более старый пакет

venv — более новый

pipenv — ещё один

 

venv:

 

на Linux:

pyvenv FOLDER_NAME

 

на Windows:

python3 -m venv FOLDER_NAME

— потом надо запустить FOLDER_NAME/Scripts/activate.bat

(потом надо будет запустить deactivate.bat, чтобы отключить и снова начать использовать дефолтный Питон)

 

 

в VK чтобы что-то вытянуть даже из публичной группы, нужно сначала зарегистрировать приложение в самом VK, там выдадут секретный ключ и что-то ещё

документация VK: https://vk.com/dev/

 

бота в Телеграме тоже нужно регистрировать в самом Телеграме — это делается через системного бота BotFather, который через команду /newbot выдаёт секретный токен для нашего бота.

документация Телеграма: core.telegram.org/api

 

работа с PostgreSQL в Питоне: библиотека psycopg2

 

ещё небольшой хак: если надо разбить строку в коде на две строки для красоты — если есть скобки, ничего не надо дополнительного, если нет скобок — надо в конце первой строки поставить обратный слэш («\»)

 

==============

Марта

 

модули GUI:

 

PyQt — см. отдельную презентацию…

 

WXPython (привязка для фреймворка WXWidgets):

— тоже надо ставить через PIP (wx)

— тоже есть графический редактор интерфейса

— можно не задавать абсолютные размеры, а создавать “sizer” (в PyQt то же самое называется “layout”), тогда всё будет перерастягиваться при изменении размеров окна, etc.

 

tkinter (Tk interface)

— Tk — ещё один фреймворк (изначально для языка Tcl — Тикль, Ти-си-эль, Так-тикль, Тикль-ток)

не надо ставить через PIP, уже есть в Питоне в качестве базового пакета (в Python 3 называется tkinter)

— ещё есть редактор rapyd — тоже визуальный редактор интерфейса

 

 

общее по GUI:

 

у консольного приложения три потока (ввод, вывод, ошибка).

 

event loop (mainloop) — бесконечный цикл, который «слушает» входы и заканчивается, только когда вызывается закрытие окна приложения.

 

 

==============

Марта

 

Исключения

 

(тут есть полуофициальный туториал по исключениям в Питоне)

 

два способа обработки ошибок

— возврат кода ошибки (если ошибка вложена глубоко, нужно руками поднимать её наверх в основной код, где она будет отлавливаться)

— а есть try-catch (try-except на Питоне), который делает это сам — поднимает ошибку наверх, пока её не поймают

 

 

стандартные (встроенные) исключения, которые можно переопределять:

ValueError, IOError (→ OSError), Exception, … (полный список)

 

raise — поднимает нужное исключение «вручную».

 

 

def divide(left_value, right_value):

if right_value == 0:

raise IOError("Divide by zero")

 

return left_value / right_value

 

print(divide(4,0))

 

try:

print(divide(4,0))

 

except ValueError as exception:

print("Please do not divide by zero")

 

else:

print("Everything is fine")

 

 

— можно переопределить стандартное общее исключение Питона:

 

except Exception as exception:

print(exception)

 

или вообще просто

except:

print("Oops")

 

 

— есть ещё волшебное слово finally — этот (под)блок вызывается всегда, независимо от того, произошло исключение или нет (а также завершился ли участок кода естественным образом или вообще был прерван).

 

try:

 

except … as exception:

 

else:

 

finally:

print("Exiting")

 

 

— выполняется в любом случае, даже если что-то сломается по ходу обработки исключения — в отличие от просто того же кода, написанного после блока try!

 

Как обеспечить симметричность некоторых операций (e.g. открыли файл — потом надо закрыть)?

 

пример — работа с файлами:

 

file = open ("test.txt", 'w') # 'w' — открытие для записи; если файл есть, очищает его(!), если файла нет, создаёт его

file.write("Hello, World!")

file. close ()

 

— по идее, можно не закрывать, но:

close() увеличивает шансы, что произойдёт запись на жёсткий диск; мы удалим дескриптор из памяти ОС (иначе они могут кончиться); в следующий раз мы откроем файл уже точно в том же состоянии.

 

Существует концепция RAII (resource acquisition is initialization) — получение некоторого ресурса неразрывно совмещается с инициализацией объекта, а освобождение — с уничтожением объекта.

Ср. конструкторы и деструкторы в C++.

В Питоне деструкторов (в чистом виде) нет. Все экземпляры объектов лежат в памяти, пока сборщик мусора их не вычистит.

Но безопасная работа с симметричными операциями в Питоне есть, “context management”.

 

Блок with:

 

with open("test.txt", 'w'), as opened_file:

opened_file.write("Test line")

 

— делает обращение с файлом симметричным — т.е. обязательно вызывает close() после завершения всех операций (даже если исключение вылетит во время работы или даже мы аварийно завершим программу по Ctrl+C!)

 

 

with open("test.txt", ' a '), as opened_file:

opened_file.write(" \n Test line")

 

— дописывает строку к уже имеющемуся в файле тексту

 

 

with open("test.txt", 'w') as opened_file, open("test2.txt", 'w') as opened_file2:

opened_file.write("Test line")

opened_file2.write("Test line")

 

 

Для своего класса

Как сделать то же самое для своего класса — нужно переопределить __exit__():

 

clas ContextedClass:

def __enter__ (self):

print("Enter switched context")

return(self)

def __exit__ (self, exc_type, exc_value, traceback):

print("Left switched context")

 

with ContextedClass() as my_class:

raise IOError("Oops")

print("Hello")

 

print("Some other operations")

 

 

пояснения:

__ enter __() — то, что происходит, когда мы создаём экземпляр класса (при этом ещё __init__() выполняется) и работаем с ним через with (и только в этом случае); если мы просто создаём объект, будет выполнен только __init__()

__ exit __() — по сути, почти- деструктор

 

 

контекст — набор условий, состояний, окружений.

 

 

то же самое — ещё и с конструктором:

 

clas ContextedClass:

def __init__ (self, stored_value):

self._value = stored_value

def __enter__(self):

print("Enter switched context")

return(self) # если хотим, чтобы ещё работал конструктор, нужно ещё здесь вернуть обязательно экземпляр класса!

def __exit__ (self, exc_type, exc_value, traceback):

print("Left switched context")

 

with ContextedClass(42) as my_class:

raise IOError("Oops")

print("Hello")

print(my_class._value)

 

print("Some other operations")

 

 

— итого, если мы создаём экземпляр класса просто так, выполняется только __init__(). Если же мы создаём экземпляр класса через with, то выполняется и __init__(), и __enter__(), а после завершения работы ещё и обязательно __ exit __().

 

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2019-06-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: