Набрел на занятную статью о частых ошибках на Python у начинающих программистов. Мне кажется, она полезна будет для тех, кто перешел с другого языка или только планирует переход. Далее идет перевод.
Поиск решения проблем с сообщениями об ошибках, выдаваемых при запуске программ в Python, может доставлять трудности, если вы изучаете этот язык программирования впервые. Далее будут описаны наиболее частые ошибки, встречающиеся при запуске программ и вызывающие сбой при выполнении.
1) Пропущено двоеточие в конце строки после управляющих конструкций типа if, elif, else, for, while, class, or def, что приведет к ошибке типа SyntaxError: invalid syntax
Пример кода:
1 2 | if spam == 42 print('Hello!') |
2) Использование = вместо == приводит к ошибке типа SyntaxError: invalid syntax
Символ = является оператором присваивания, а символ == — оператором сравнения.
Эта ошибка возникает в следующем коде:
1 2 | if spam = 42: print('Hello!') |
3) Использование неправильного количества отступов.
Возникнет ошибка типа IndentationError: unexpected indent, IndentationError: unindent does not match any outer indentation level и IndentationError: expected an indented block
Нужно помнить, что отступ необходимо делать только после :, а по завершению блока обязательно вернуться к прежнему количеству отступов.
Пример ошибки:
1 2 | print('Hello!') print('Howdy!') |
и тут
1 2 3 | if spam == 42: print('Hello!') print('Howdy!') |
и тут
1 2 | if spam == 42: print('Hello!') |
4) Неиспользование функции len() в объявлении цикла for для списков list
Возникнет ошибка типа TypeError: ‘list’ object cannot be interpreted as an integer
Часто возникает желание пройти в цикле по индексам элементов списка или строки, при этом требуется использовать функцию range(). Нужно помнить, что необходимо получить значение len(someList) вместо самого значения someList
Ошибка возникнет в следующем коде:
1 2 3 | spam = ['cat', 'dog', 'mouse'] for i in range(spam): print(spam[i]) |
Некоторые читатели (оригинальной статьи) заметили, что лучше использовать конструкцию типа for i in spam:, чем написанный код выше. Но, когда нужно получить номер итерации в цикле, использование вышенаписанного кода намного полезнее, чем получение значения списка.
От переводчика: Иногда можно ошибочно перепутать метод shape с len() для определения размера списка. При этом возникает ошибка типа ‘list’ object has no attribute ‘shape’
5) Попытка изменить часть строки. (Ошибка типа TypeError: ‘str’ object does not support item assignment)
Строки имеют неизменяемый тип. Эта ошибка произойдет в следующем коде:
1 2 3 | spam = 'I have a pet cat.' spam[13] = 'r' print(spam) |
А ожидается такое результат:
1 2 3 | spam = 'I have a pet cat.' spam = spam[:13] + 'r' + spam[14:] print(spam) |
От переводчика: Подробней про неизменяемость строк можно прочитать тут
6) Попытка соединить нестроковую переменную со строкой приведет к ошибке TypeError: Can’t convert ‘int’ object to str implicitly
Такая ошибка произойдет тут:
1 2 | numEggs = 12 print('I have ' + numEggs + ' eggs.') |
А нужно так:
1 2 | numEggs = 12 print('I have ' + str(numEggs) + ' eggs.') |
или так:
1 2 | numEggs = 12 print('I have %s eggs.' % (numEggs)) |
От переводчика: еще удобно так
1 2 | print('This {1} xorosho{0}'.format('!','is')) # This is xorosho! |
7) Пропущена одинарная кавычка в начале или конце строковой переменной (Ошибка SyntaxError: EOL while scanning string literal)
Такая ошибка произойдет в следующем коде:
1 | print(Hello!') |
или в этом:
1 | print('Hello!) |
или в этом:
1 2 | myName = 'Al' print('My name is ' + myName + . How are you?') |
8) Опечатка в названии переменной или функции (Ошибка типа NameError: name ‘fooba’ is not defined)
Такая ошибка может встретиться в таком коде:
1 2 | foobar = 'Al' print('My name is ' + fooba) |
или в этом:
1 | spam = ruond(4.2) |
или в этом:
1 | spam = Round(4.2) |
От переводчика: очень часто при написании возникают ошибки типа NameError: name ‘true’ is not defined и NameError: name ‘false’ is not defined, связанные с тем, что нужно писать булевные значения с большой буквы True и False
9) Ошибка при обращении к методу объекта. (Ошибка типа AttributeError: ‘str’ object has no attribute ‘lowerr’)
Такая ошибка произойдет в следующем коде:
1 2 | spam = 'THIS IS IN LOWERCASE.' spam = spam.lowerr() |
10) Попытка использовать индекс вне границ списка. (Ошибка типа IndexError: list index out of range)
Ошибка возникает в следующем коде:
1 2 | spam = ['cat', 'dog', 'mouse'] print(spam[6]) |
11) Использование несуществующих ключей для словаря. (Ошибка типа KeyError: ‘spam’)
Ошибка произойдет в следующем коде:
1 2 | spam = {'cat': 'Zophie', 'dog': 'Basil', 'mouse': 'Whiskers'} print('The name of my pet zebra is ' + spam['zebra']) |
12) Использование зарезервированных в питоне ключевых слов в качестве имени для переменной. (Ошибка типа SyntaxError: invalid syntax)
Ключевые слова (зарезервированные) в питоне невозможно использовать как переменные. Пример в следующем коде:
1 | class = 'algebra' |
Python 3 имеет следующие ключевые слова: and, as, assert, break, class, continue, def, del, elif, else, except, False, finally, for, from, global, if, import, in, is, lambda, None, nonlocal, not, or, pass, raise, return, True, try, while, with, yield
13) Использование операторов присваивания для новой неинициализированной переменной. (Ошибка типа NameError: name ‘foobar’ is not defined)
Не стоит надеяться, что переменные инициализируются при старте каким-нибудь значением типа 0 или пустой строкой.
Эта ошибка встречается в следующем коде:
1 2 3 | spam = 0 spam += 42 eggs += 42 |
Операторы присваивания типа spam += 1 эквивалентны spam = spam + 1. Это означает, что переменная spam уже должна иметь какое-то значение до.
14) Использование локальных переменных, совпадающих по названию с глобальными переменными, в функции до инициализации локальной переменной. (Ошибка типа UnboundLocalError: local variable ‘foobar’ referenced before assignment)
Использование локальной переменной в функции с именем, совпадающим с глобальной переменной, опасно. Правило: если переменная в функции использовалась с оператором присвоения, это всегда локальная переменная для этой функции. В противном случае, это глобальная переменная внутри функции.
Это означает, что нельзя использовать глобальную переменную (с одинаковым именем как у локальной переменной) в функции до ее определения.
Код с появлением этой ошибки такой:
1 2 3 4 5 | someVar = 42 def myFunction(): print(someVar) someVar = 100 myFunction() |
15) Попытка использовать range() для создания списка целых чисел. (Ошибка типа TypeError: ‘range’ object does not support item assignment)
Иногда хочется получить список целых чисел по порядку, поэтому range() кажется подходящей функцией для генерации такого списка. Тем не менее нужно помнить, что range() возвращает range object, а не список целых чисел.
Пример ошибки в следующем коде:
1 2 | spam = range(10) spam[4] = -1 |
Кстати, это работает в Python 2, так как range() возвращает список. Однако попытка выполнить код в Python 3 приведет к описанной ошибке.
Нужно сделать так:
1 2 | spam = list(range(10)) spam[4] = -1 |
16) Отсутствие операторов инкремента ++ или декремента —. (Ошибка типа SyntaxError: invalid syntax)
Если вы пришли из другого языка типа C++, Java или PHP, вы можете попробовать использовать операторы ++ или — для переменных. В Питоне таких операторов нет.
Ошибка возникает в следующем коде:
1 2 | spam = 0 spam++ |
Нужно написать так:
1 2 | spam = 0 spam += 1 |
17) Как заметил читатель Luciano в комментариях к статье (оригинальной), также часто забывают добавлять self как первый параметр для метода. (Ошибка типа TypeError: myMethod() takes no arguments (1 given)
Эта ошибка возникает в следующем коде:
1 2 3 4 5 | class Foo(): def myMethod(): print('Hello!') a = Foo() a.myMethod() |
Краткое объяснение различных сообщений об ошибках представлено в Appendix D of the «Invent with Python» book.
Полезные материалы
Наиболее частые проблемы Python и решения (перевод)