5 распространенных ошибок начинающих программистов на Python
В первые дни работы программистом на Python все мы сталкиваемся с тем или иным типом странной ошибки в нашем коде, которая после нескольких болезненных часов в StackOverflow оказывается не ошибкой, а функцией Python. Вот как все работает в Python. Ниже приведены 5 самых распространенных ошибок, которые делают большинство начинающих программистов на Python. Давайте немного о них узнаем, чтобы сэкономить несколько часов, задавая вопросы на страницах и в группах в Facebook.
Создание копии словаря или списков.
Всякий раз, когда вам нужно сделать копию словаря или списка, не просто используйте оператор присваивания.
Неправильно:
>>> dict_a = {"name": "John", "address":"221B Baker street"} >>> dict_b = dict_a
Теперь, если вы редактируете / обновляете dict_b
, dict_a
также будет обновляться, потому что с помощью оператора присваивания вы пытаетесь сказать, что он dict_b
будет указывать на тот же объект, на который dict_a
указывает.
>>> dict_b["age"] = 26 >>> dict_b {'address': '221B Baker street', 'name': 'John', 'age': 26} >>> dict_a {'address': '221B Baker street', 'name': 'John', 'age': 26}
Правильный:
Используйте метод copy()
или deepcopy()
.
>>> dict_c = dict_b.copy() >>> dict_c["location"] = "somewhere" >>> dict_c {'address': '221B Baker street', 'name': 'John', 'age': 26, 'location': 'somewhere'} >>> dict_b {'address': '221B Baker street', 'name': 'John', 'age': 26} >>> dict_a {'address': '221B Baker street', 'name': 'John', 'age': 26}
Словарь ключей
Допустим, мы поместили следующие значения в словарь.
>>> dict_a = dict() >>> dict_a {} >>> dict_a[1] = "apple" >>> dict_a[True] = "mango" >>> dict_a[2] = "melon"
Если мы попытаемся напечатать словарь, какой будет вывод. Посмотрим.
>>> dict_a {1: 'mango', 2: 'melon'}
Что сейчас произошло? где ключ True
?
Помните, что логический класс является подклассом Integer. Целочисленный эквивалент True
равен 1, а False
равен 0. Следовательно, значение ключа 1 перезаписывается.
>>> isinstance(True, int) True >>> isinstance(False, int) True >>> True == 1 True >>> False == 0 True
Обновление списков или словарей.
Допустим, вы хотите добавить элемент в список.
>>> list_a = [1,2,3,4,5] >>> list_a = list_a.append(6) >>> list_a >>> # prints nothing
Попробуйте обновить словарь.
>>> dict_a = {"a" : "b"} >>> dict_a = dict_a.update({"c" : "d"}) >>> dict_a >>> # prints nothing
Хорошо, давайте попробуем отсортировать список.
>>> list_b = [2,5,3,1,7] >>> list_b = list_b.sort() >>> list_b >>> # prints nothing
Почему ничего не печатается? Что мы делаем не так?
Большинство методов объекта последовательности, таких как сортировка, обновление, добавление и т.д., для повышения производительности работают избегая ненужного создания отдельной копии.
Не пытайтесь присвоить выходные данные таких методов переменной.
Правильно:
>>> list_a = [1,2,3,4,5] >>> list_a.append(6) >>> dict_a = {"a" : "b"} >>> dict_a.update({"c" : "d"}) >>> dict_a {'c': 'd', 'a': 'b'} >>> list_a.sort() >>> list_a [1, 2, 3, 4, 5, 6]
Интернирование строк
В некоторых случаях python пытается повторно использовать существующие неизменяемые объекты. Строковое интернирование является одним из таких случаев.
>>> a = "gmail" >>> b = "gmail" >>> a is b True
Здесь мы попытались создать два разных строковых объекта. Но когда проверено, являются ли оба объекта одинаковыми, возвращается True. Это потому, что python не создал другой объект, b
но указал на первое значение "gmail".
Все строки одной длины интернированы. Строка, содержащая что-либо, кроме символов ASCII, цифр и подчеркивания в них, не интернируется.
Посмотрим.
>>> a = "@gmail" >>> b = "@gmail" >>> a is b False
Кроме того, помните ==
, отличается от оператора is
. ==
проверяет, равны ли значения или нет, а is
проверяет, указывают ли обе переменные на один и тот же объект.
>>> a = "@gmail" >>> b = "@gmail" >>> a is b False >>> a == b True
Так что имейте в виду вышеизложенное при использовании неизменяемых строк ==
или оператора is
.
Аргументы по умолчанию инициализируется только один раз.
Рассмотрим приведенный ниже пример.
def func(a, lst=[]): lst.append(a) return lst print(func(1)) print(func(2))
Как вы думаете, что будет выходом из двух вышеприведенных операторов печати?
Давайте попробуем запустить его.
>>> def func(a, lst=[]): ... lst.append(a) ... return lst ... >>> print(func(1)) [1] >>> print(func(2)) [1, 2] >>>
Почему вывод [1,2]
во втором случае. Разве это не должно быть просто [2]
?
Итак, подвох в том, что аргументы функции по умолчанию инициализируется только один раз. При первом вызове, т.е. func(1)
список lst
инициализируется и считается пустым, поэтому к нему добавляется 1. Но при втором вызове список уже содержит один элемент, поэтому вывод равен [1,2]