Материал подготовил: Виталий Евтушенко, НИУ ВШЭ
Чтобы упростить процессы и жизнь, человечество начало придумывать некие стандарты: стандарты красоты, золотые стандарты, стандарты уровня жизни, стандарты ведения войны, стандарты обработки чисел с плавающей точкой. Можно предоложить, что прикладное программирование не обошла стороной стандартизация и в нём тоже есть свои стандарты. Это предположение будет верным.
Один из стандартов: стандарт оформления кода. Также есть стандарты документации, стандарты используемых библиотек. Почти на всё есть свой стандарт, а иногда еще и внутренняя/локальная/корпоративная договоренность (конвенция).
Зачем нужен Coding style?
today_temp
вместо A или переменная number_of_revolution_per_year_in_developing_countries_first_database
вместо переменной с названием B;Что почитать?
Каждый объект в Python'е существует в своём scope (область видимости). Есть несколько областей видимости
Scopes rules
in it) is deleted.
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.
Что почитать?
Пример #1. На этом примере видно, как интерпретатор Python'а сначала ищет переменную a в local scope, не находит и обращается к глобальной переменной a, плюсуя к ней 5.
def function1():
return a + 5
a = 5
print(f'function results is {function1()} and a is still {a}')
function results is 10 and a is still 5
Пример #2. А здесь мы явно говорим, что следует использовать переменную a из global scope
def function1():
global a
a = a + 5
return a
a = 5
print(f'function results is {function1()} and a is {a}')
function results is 10 and a is 10
Пример #3. В этом примере происходит то же самое, что и в первом примере, но исходное значение глобальной переменной изменяется, потому что list (список) ‒ mutable type (изменяемый тип).
def function2():
a.append(5)
return a
a = [5]
print(f'function results is {function2()} and b is {a}')
function results is [5, 5] and b is [5, 5]
При написании программы, которая будет выполнять хоть немного важное задание, требуется тестировать свой код. Одним из примеров тестирования может выступать конструкция assert. Она нужна для проверки истинности утверждения. Примером отладки могут выступать встроенные в IDE отладчики или библиотеки, позволяющие проводить отладку дажев Jupyter'е.
assert 2 + 2 == 4
print('right statement')
right statement
assert 2 + 2 == 5, "Уверены ли Вы, что сумма двух и двух равняется пяти?"
print('right statement')
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) <ipython-input-2-686801ed7846> in <module>() ----> 1 assert 2 + 2 == 5, "Уверены ли Вы, что сумма двух и двух равняется пяти?" 2 print('right statement') AssertionError: Уверены ли Вы, что сумма двух и двух равняется пяти?
assert isinstance(4, int)
print('right statement')
right statement
assert isinstance(4, str), "Почему тут ошибка? Потому что сильная типизация."
print('right statement')
--------------------------------------------------------------------------- AssertionError Traceback (most recent call last) <ipython-input-4-4f990796fd98> in <module>() ----> 1 assert isinstance(4, str), "Почему тут ошибка? Потому что сильная типизация." 2 print('right statement') AssertionError: Почему тут ошибка? Потому что сильная типизация.
В очень общих словах, это процесс очень подробного исполнения программы (контролируемое исполнение каждого действия, каждой операции и итерации) с мониторингом значения всех переменных или всех желаемых переменных и особо тщательном внимании (остановке) в местах, которые того требуют (где выставлен breakpoint ‒ точка остановки). Нужно, чтобы не выставлять print(variable) в каждом месте программы, когда что-то идёт не так, а использовать уже готовый интерфейс для этого.
Что посмотреть и почитать?
ПАСХАЛЬНОЕ ЯЙЦО: Первые три человека, кто прочитает эту статью и отправит мне на почту скрин с установленной работающей библиотекой и пример отладки, или окно отладки из IDE (например PyCharm) в процессе отладки с объяснением происходящего получит $+0.5$ балла к накопленной или экзамену, на выбор.
try:
assert 2 + 2 == 5
except AssertionError:
print('Wow, there were unclear statment!')
Иногда, человек пишет код, который наиболее вероятно может сломаться наиболее вероятным образом. В целом, когда пишешь код, нужно заранее понимать, какие ошибки могут возникнуть и как их обойти, не прибегая к экстренным мерам вроде полной перезагрузки работающей программы (hello, windows blue screan). Одним из способов контролировать ошибки может служить концепция ловли ошибок.
В общем виде, ловля ошибок - управляющая конструкция со следующей схемой 1:
Что почитать?
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!')
Введите числое число. Или хотя бы с плавающей точкой. Но вы же можете ввести буквы, я знаю и готов к этому FiftyFive Ha-ha, i was ready!!1! Введите числое число. Или хотя бы с плавающей точкой. Но вы же можете ввести буквы, я знаю и готов к этому 55 Wow, nice job. That is a NUMBER!
Можно ловить совершенно любую ошибку возникшую. Но так делать не стоит, потому что программа перестает быть очевидной и Errors should never pass silently (The Zen of Python 0:10). Лучше (хотя бы) перед этим рассмотреть наиболее вероятные. Пример, при работе с интернетом: ошибка соединения, ошибка возвращаемого кода. Часто в задачах требуются шаблоные исключения, которые достаточно выучить или держать рядом чтобы сделать copy-paste
lst = list(range(5))
lst.append('5')
print(f'lst is {lst}')
try:
print('Сейчас я попробую суммировать элементы в листе')
print('Итак, сумма равна...\n')
print(sum(lst))
except:
print('''Ой, что-то пошло не так. Не знаю, что могло пойти не так.\n\
И Вы не узнаете. Потому что я выставил исключение на любую ошибку.\n\
Как правило, нет достаточно весомых оснований так делать''')
lst is [0, 1, 2, 3, 4, '5'] Сейчас я попробую суммировать элементы в листе Итак, сумма равна... Ой, что-то пошло не так. Не знаю, что могло пойти не так. И Вы не узнаете. Потому что я выставил исключение на любую ошибку. Как правило, нет достаточно весомых оснований так делать
Ошибка, которая возникает в описанном выше примере:
TypeError: unsupported operand type(s) for +: 'int' and 'str
Попробуем решить её:
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\
Как правило, нет достаточно весомых оснований так делать''')
lst is [0, 1, 2, 3, 4, '5'] Сейчас я попробую суммировать элементы в листе Итак, сумма равна... TypeError was catched. Good work!
Очевидно, что таким образом можно ловить любую ошибку, встроенную в языке, так и придуманную другими людьми в своих пакетах, фреймворках, библиотеках, проектах. Люди любят придумывать ошибки, а другие люди любят их ловить, иногда это одни и те же люди.
Более того, иногда люди любят вызывать ошибки How to catch NotImplementedError Exception in Python?. Например, если есть готовый интерфейс, но его методы (функции) еще не до конца реализованы.
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.')
Sorry, The New Ultimate Question of Life, the Universe and Everything is not found yet. Time to be.