#!/usr/bin/env python
# coding: utf-8
# # Основы программирования в Python
#
# *Материал подготовил: Виталий Евтушенко, НИУ ВШЭ*
# # Code Style, Variable scopes and Namespace, Testing and Debugging basics, Exception handling and Error Rising
# ## [Coding style](https://en.wikipedia.org/wiki/Programming_style) (Стандарт оформления кода)
#
# Чтобы упростить процессы и жизнь, человечество начало придумывать некие стандарты: стандарты красоты, золотые стандарты, стандарты уровня жизни, стандарты ведения войны, [стандарты обработки чисел с плавающей точкой](https://en.wikipedia.org/wiki/IEEE_754). Можно предоложить, что **прикладное программирование не обошла стороной стандартизация и в нём тоже есть свои стандарты**. Это предположение будет верным.
#
# Один из стандартов: **стандарт оформления кода**. Также есть стандарты документации, стандарты используемых библиотек. Почти на всё есть свой стандарт, а иногда еще и внутренняя/локальная/корпоративная договоренность (конвенция).
#
# **Зачем нужен Coding style?**
# - В целом, это очень утилитарная идея.
# - **Ограничение на количество символов в строке** - максимальная возможная длина одного монитора, чтобы не использовать scroll bar (полосу прокрутки);
# - **Осмысленные имена переменных** (Meaningful variables) ‒ чтобы другой человек _(а также разработчик, который уже через несколько дней ‒ другой человек)_ понимал, что делает переменная. **Пример:** переменная `today_temp` вместо A или переменная `number_of_revolution_per_year_in_developing_countries_first_database` вместо переменной с названием B;
# - **Пробелы** ‒ максимизации для читаемости кода;
# - **Отступы vs Пробелы** - для отсутствия проблем с компиляцией.
# - С его помощью человек, впервые увидевший Ваш код, может потратить меньше времени на понимание кода, если он выполнен согласно стандарту ("согласно стандарту" - примерно равно согласно "здравому смыслу")
# - Возможно, *coding style documents* не всегда написаны кровью (по аналогии с техникой безопасности и правилами дорожного движения), но написаны ценой человеко-часов, которые не стоит отдавать вновь и стоит экономить.
#
# **Что почитать?**
# - [PEP 8 ‒ Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/) (**README**)
# - [Chech PEP8 online](http://pep8online.com/) (**Just paste your code here**)
# - [Тест: а у вас стильный Python? (tproger)](https://tproger.ru/quiz/python-style-quiz/)
# - [Why does Google not follow PEP8 for Python code?](https://www.quora.com/Why-does-Google-not-follow-PEP8-for-Python-code) и [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html) (**пример корпоративной конвенции о коде**).
# ## [Variable scopes and Namespace](https://docs.python.org/3/tutorial/classes.html)
# Каждый объект в Python'е существует в своём scope (область видимости). Есть несколько областей видимости
#
#
# **Как это выглядит на практике?**
#
# >**Scopes rules**
# - Each name exists in a certain scope.
# - When entering a function a new local scope is created.
# - After exiting a function its local scope (with all the names
# in it) is deleted.
# - When referencing a name the Python interpreter first
# searches the local scope, then the global scope and finally
# the built-in scope. The complete picture also includes an Enclosing scope - check Python
# resources.
#
# **Что почитать?**
# - [Documentation](https://docs.python.org/3/tutorial/classes.html) (**стоит почитать**)
# - [What Are Python Namespaces (And Why Are They Needed?)](https://code.tutsplus.com/tutorials/what-are-python-namespaces-and-why-are-they-needed--cms-28598) (**стоит почитать**)
# - [global_&_return, Intermediate Python](https://lancelote.gitbooks.io/intermediate-python/content/book/global_&_return.html)
# - [A Beginner's Guide to Python's Namespaces, Scope Resolution, and the LEGB Rule](http://sebastianraschka.com/Articles/2014_python_scope_and_namespaces.html) (**стоит почитать**)
# - [Short Description of the Scoping Rules?](https://stackoverflow.com/questions/291978/short-description-of-the-scoping-rules) (**стоит почитать**)
# **Пример #1.** На этом примере видно, как **интерпретатор Python'а сначала ищет переменную a в local scope, не находит и обращается к глобальной переменной a**, плюсуя к ней 5.
# In[1]:
def function1():
return a + 5
a = 5
print(f'function results is {function1()} and a is still {a}')
# **Пример #2.**
# А здесь мы **явно говорим, что следует использовать переменную a из global scope**
# In[2]:
def function1():
global a
a = a + 5
return a
a = 5
print(f'function results is {function1()} and a is {a}')
# **Пример #3.** В этом примере происходит то же самое, что и в первом примере, но исходное значение глобальной переменной изменяется, потому что **list** (*список*) ‒ **mutable type** (*изменяемый тип*).
# In[3]:
def function2():
a.append(5)
return a
a = [5]
print(f'function results is {function2()} and b is {a}')
# ## Testing and Debugging basics (Тестирование и отладка)
# При написании программы, которая будет выполнять хоть немного важное задание, требуется тестировать свой код. Одним из примеров тестирования может выступать конструкция [assert](http://pythonz.net/references/named/assert/). Она нужна для проверки истинности утверждения. Примером отладки могут выступать встроенные в IDE отладчики или [библиотеки, позволяющие проводить отладку дажев Jupyter'е](https://davidhamann.de/2017/04/22/debugging-jupyter-notebooks/).
# ### Testing
# In[1]:
assert 2 + 2 == 4
print('right statement')
# In[2]:
assert 2 + 2 == 5, "Уверены ли Вы, что сумма двух и двух равняется пяти?"
print('right statement')
# In[3]:
assert isinstance(4, int)
print('right statement')
# In[4]:
assert isinstance(4, str), "Почему тут ошибка? Потому что сильная типизация."
print('right statement')
# **По примеру #2 стоит прочитать**:
# - [Strong, Weak, Dynamic, and Static Typed Programming Languages Explained](http://www.josephspurrier.com/strong-weak-dynamic-and-static-typed-programming-languages/)
# - [Is python strong typed?](https://stackoverflow.com/questions/11328920/is-python-strongly-typed)
# - [Static/Dynamic vs Strong/Weak](https://stackoverflow.com/questions/2351190/static-dynamic-vs-strong-weak)
# - [static vs dynamic vs strong vs weak vs duck typing](https://www.koffeinfrei.org/2012/03/19/static-vs-dynamic-vs-strong-vs-weak-vs-duck-typing/)
# ### [Debugging](https://ru.wikipedia.org/wiki/%D0%9E%D1%82%D0%BB%D0%B0%D0%B4%D0%BA%D0%B0_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D1%8B) [(en)](https://en.wikipedia.org/wiki/Debugging)
# **В очень общих словах**, это процесс очень подробного исполнения программы (контролируемое исполнение каждого действия, каждой операции и итерации) с мониторингом значения всех переменных или всех желаемых переменных и особо тщательном внимании (остановке) в местах, которые того требуют (где выставлен *breakpoint* ‒ точка остановки). **Нужно, чтобы не выставлять print(variable) в каждом месте программы, когда что-то идёт не так, а использовать уже готовый интерфейс для этого**.
#
# **Что посмотреть и почитать?**
# - [Отладка, Intermediate Python](https://lancelote.gitbooks.io/intermediate-python/content/book/debugging.html)
# - [Разработка через тестирование](https://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%82%D0%B5%D1%81%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)
# - [История термина дебаггинг/отладка на wiki en](https://en.wikipedia.org/wiki/Debugging#Origin_of_the_term)
# - [Getting Started with PyCharm 6/8: Debugging](https://www.youtube.com/watch?v=QJtWxm12Eo0) **(стоит посмотреть)**
# - [debugging-jupyter-notebooks](https://davidhamann.de/2017/04/22/debugging-jupyter-notebooks/) **(стоит не только посмотреть, почитать код но и установить себе библиотеку для отладки и начать ей пользовать)**.
#
# **ПАСХАЛЬНОЕ ЯЙЦО**: Первые три человека, кто прочитает эту статью и отправит мне на почту скрин с установленной работающей библиотекой и пример отладки, или окно отладки из IDE (например PyCharm) в процессе отладки с объяснением происходящего получит $+0.5$ балла к накопленной или экзамену, на выбор.
# ### Также, мы можем совмещать assert с более сложной концепцией ловли ошибок (см. ниже).
# In[ ]:
try:
assert 2 + 2 == 5
except AssertionError:
print('Wow, there were unclear statment!')
# ## Exception handling and Error rising (Ловля ошибок и вызов ошибок)
#
#
# **Иногда, человек пишет код, который наиболее вероятно может сломаться наиболее вероятным образом**. В целом, когда пишешь код, нужно заранее понимать, какие ошибки могут возникнуть и как их обойти, не прибегая к экстренным мерам вроде полной перезагрузки работающей программы (hello, windows blue screan). **Одним из способов контролировать ошибки может служить концепция ловли ошибок.**
#
# В общем виде, ловля ошибок - управляющая конструкция со следующей схемой [1](https://hadoopguru.blogspot.com/2013/09/java-interview-question-part03.html):
#
#
# **Что почитать?**
# - [Встроенные в язык исключения](https://docs.python.org/3.6/library/exceptions.html)
# - [sklearn eceptions](http://scikit-learn.org/stable/modules/classes.html#module-sklearn.exceptions), [numpy seterr](https://docs.scipy.org/doc/numpy-1.14.0/reference/ufuncs.html#error-handling)
# - [What is the use of exception handling? Quora](https://www.quora.com/What-is-the-use-of-exception-handling)
# - [wiki ru](https://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B9), [Хабр](https://habr.com/post/311214/)
# In[8]:
for i in range(2):
try:
int(input('''Введите числое число. Или хотя бы с плавающей точкой. Но вы же можете ввести буквы,
я знаю и готов к этому \n'''))
print('Wow, nice job. That is a NUMBER!')
except ValueError:
print('Ha-ha, i was ready!!1!')
# Можно ловить совершенно любую ошибку возникшую. Но так делать не стоит, потому что программа перестает быть очевидной и **Errors should never pass silently (The Zen of Python 0:10).** Лучше (хотя бы) перед этим рассмотреть наиболее вероятные. Пример, при работе с интернетом: ошибка соединения, ошибка возвращаемого кода. **Часто в задачах требуются шаблоные исключения, которые достаточно выучить или держать рядом чтобы сделать copy-paste**
# In[9]:
lst = list(range(5))
lst.append('5')
print(f'lst is {lst}')
try:
print('Сейчас я попробую суммировать элементы в листе')
print('Итак, сумма равна...\n')
print(sum(lst))
except:
print('''Ой, что-то пошло не так. Не знаю, что могло пойти не так.\n\
И Вы не узнаете. Потому что я выставил исключение на любую ошибку.\n\
Как правило, нет достаточно весомых оснований так делать''')
# Ошибка, которая возникает в описанном выше примере:
# ```python
# TypeError: unsupported operand type(s) for +: 'int' and 'str
# ```
# Попробуем решить её:
# In[11]:
lst = list(range(5))
lst.append('5')
print(f'lst is {lst}')
try:
print('Сейчас я попробую суммировать элементы в листе')
print('Итак, сумма равна...\n')
print(sum(lst))
except TypeError:
print('TypeError was catched. Good work!')
except:
print('''Ой, что-то пошло не так. Не знаю, что могло пойти не так.\n\
И Вы не узнаете. Потому что я выставил исключение на любую ошибку.\n\
Как правило, нет достаточно весомых оснований так делать''')
# Очевидно, что **таким образом можно ловить любую ошибку, встроенную в языке, так и придуманную другими людьми в своих пакетах, фреймворках, библиотеках, проектах**. Люди любят придумывать ошибки, а другие люди любят их ловить, иногда это одни и те же люди.
#
# **Более того, иногда люди любят вызывать ошибки** [How to catch NotImplementedError Exception in Python?](https://www.tutorialspoint.com/How-to-catch-NotImplementedError-Exception-in-Python). Например, если есть готовый интерфейс, но его методы (функции) еще не до конца реализованы.
# In[12]:
def function_that_finds_life_meaning():
'''
Эта функция находит смысл жизни.
Другая постановка задачи: ответ на главный вопрос жизни,
вселенной и всего такого.
:input something_meaningfull: dict
:output: life_meaning
'''
# YOUR CODE HERE
raise NotImplementedError() # - here the error rise
return life_meaning
try:
function_that_finds_life_meaning()
except NotImplementedError:
print('Sorry, The New Ultimate Question of Life, the Universe and Everything is not found yet. Time to be.')