Python Kickstart: целочисленное деление и списки
С чего начать изучение Python? Если с английским все в порядке, то рекомендую The Python Tutorial. На русском можно почитать «Язык программирования Python».
Из печатных книг ничего посоветовать не могу. Просмотрел в книжном магазине: «Python. Подробный справочник» Дэвида Бизли и «Программирование на Python 3. Подробное руководство» Марка Саммерфилда. На первый взгляд книги вполне адекватные, но цена кусается.
Пересказывать учебники не буду, предлагаю разобрать несколько примеров. Начнем!
Пример №1:
# coding: utf-8 if __name__ == '__main__': pass |
Строка «# coding: utf-8
» указывает, что файл сохранен в кодировке UTF-8. Рекомендую раз и навсегда отказаться от остальных кодировок везде, где это возможно.
Оператор pass
ничего не делает. Используется как временная затычка вместо блока кода. Перед pass
стоят 4 пробела - так в Python принято выделять блоки кода.
Пример №2:
# coding: utf-8 # <- так выделяются комментарии if __name__ == '__main__': # это тоже комментарий # Обратите внимание! Как правило ожидается результат = 2.5 print 'Целочисленное деление:' print '5 / 2 =', 5 / 2 print 'Деление, возвращающее действительное число:' print 5.0 / 2, '=', 5 / 2.0 print float(5) / 2, '=', 5 / float(2) print 'Целочисленное деление действительных чисел:' print 5.0 // 2.0 print float(5) // float(2) |
Оператор print
выводит параметры на экран и переводит строку. Параметры разделяются запятой. При выводе между параметрами добавляется пробел. Чтобы print
не переводил строку, нужно в конце строки поставить запятую:
print 'No <br>, please!', |
Если аргументы у оператора /
целые числа, то производится целочисленное деление. Достаточно часто возникает ошибка, когда вместо обычного деления выполняется целочисленное. Бывают сложные случаи:
# coding: utf-8 if __name__ == '__main__': a = 5 b = 2 # Здесь мы не знаем, что a и b - целые числа print 'a / b =', a / b |
Если в приведенном примере a и b чаще всего действительные числа, то такую ошибку достаточно трудно отловить. Решается она так:
# coding: utf-8 if __name__ == '__main__': a = 5 b = 2 # Здесь мы не знаем, что a и b - целые числа print 'a / b =', float(a) / b # Всегда преобразуем a к действительному числу |
В Python 3 такое поведение исправили, см. PEP 238. Этот пример хорошо демонстрирует, как разработчики Python работают над интуитивностью языка.
Пример №3
Важное достоинство Python - гибкие высокоуровневые структуры данных.
Начнем со списков:
# coding: utf-8 if __name__ == '__main__': # Создаем список с именем a a = [2, 3, 4] # Выводим список a print 'a =', a # Выводим нулевой элемент списка print a[0] # Выводим первый элемент списка print a[1] # Список может содержать любые типы данных, # в том числе списки b = ['a', 1, 'hello', [1, [2, [3]]]] print 'b =', b # Определяем длину списка a print 'Длина a =', len(a) # Добавляем новый элемент в конец списка a a.append(5) print 'a =', a # Добавляем новый элемент в начало списка a a.insert(0, 1) print a # Выводим элементы списка a, умноженные на 2 for i in a: print i*2, # запятая в конце - не переводить на новую строку print for i in xrange(0, 10): print i, |
Список — изменяемый тип данных, в который можно поместить переменную любого типа, в том числе и другой список. Пустой список задается так: []
. При добавлении элемента список автоматически изменяет размер.
К элементам списка можно обращаться по индексу: a[0]
, a[1]
, ..., a[N]
. Кроме того, применима операция среза: a[0:2]
, возвращающая список элементов между указанными индексами. Операция среза хорошо рассмотрена в книге «Язык программирования Python».
Оператор цикла for
перебирает элементы из списка по одному. В теле цикла (отступ - 4 пробела!) производятся операции с конкретным элементом из списка.
Оператор print
без параметров выполняет переход на новую строку.
Существует функция range
, которая возвращает список чисел из заданного интервала. Выше рассматривается функция xrange
, которая возвращает итератор. Итератор - это некая сущность, которую можно попросить "дай следующий элемент?". В результате можно получить следующий элемент, либо узнать, что больше элементов нет. Итератор не хранит в себе все элементы.
Допустим, нам нужно посчитать сумму чисел от a до b-1:
# coding: utf-8 if __name__ == '__main__': a = 1 b = 100000 sum = 0 for i in range(a, b): sum += i print 'Sum =', sum |
Это плохой код. Недостаток его в том, что результат функции range
- это список. А что, если b = 10000000000
? В памяти будет хранится огромный список, который для данной задачи совсем не нужен! На каждом шаге цикла нам нужен только текущий элемент: 1, 2, 3... Итератор не создает списка из всех элементов, он просто последовательно отдает элементы до тех пор, пока они не закончатся.
# coding: utf-8 if __name__ == '__main__': a = 1 b = 100000 sum = 0 for i in xrange(a, b): sum += i print 'Sum =', sum |
Так писать правильнее. В Python 3 функция range
возвращает итератор, а функцию xrange
убрали из языка.
Напоследок рассмотрим нюанс:
# coding: utf-8 if __name__ == '__main__': a = [1, 2, 3] b = ['!', a, '!'] print b a = ['A', 'A', 'A'] print b |
Тут важно понять, что список b
хранит в себе не содержимое списка a
, а некоторую информацию о том, где взять содержимое списка a
. Поэтому когда мы изменяем список a
, то мы неявно изменяем содержимое списка b
.
В этом случае, очевидно, никаких изменений в списке b
не произойдет:
# coding: utf-8 if __name__ == '__main__': a = [1, 2, 3] b = ['!', [1, 2, 3], '!'] print b a = ['A', 'A', 'A'] print b |
Потому что содержимое списка a
и содержимое списка b[1]
никак между собой не связаны.
С приведенными примерами нужно обязательно поиграться (например, в Eclipse), а также попробовать модифицировать их.
Нет обратных ссылок на эту запись.
Декабрь 21st, 2012 - 16:42
SPASIBO!
Январь 11th, 2013 - 19:36
Спасибо, но я что-то не так понял? «# coding: utf-8
if name == ‘main‘: a = 1 b = 100000 sum = 0 for i in xrange(a, b): sum += i print ‘Sum =’, sum Так писать правильнее. В Python 3 функция range возвращает итератор, а функцию xrange убрали из языка.» Если правильнее почему из 3 убрали?
Январь 13th, 2013 - 13:28
В Python 3 xrange переименовали в range, а range убрали.
Апрель 21st, 2017 - 15:33
Результат предпоследнего примера:
[‘!’, [1, 2, 3], ‘!’] [‘!’, [1, 2, 3], ‘!’]
содержимое b таки не изменилось, чяднт?
Апрель 21st, 2017 - 15:59
Очевидно, это всё-таки не ссылка на массив a, но присваивание массива a второму элементу массива b.
В примере ниже массив а присваивается повторно после изменения и только тогда выводится в составе b
if name == ‘main‘: a = [1, 2, 3] b = [‘!’, a, ‘!’] print b a = [‘A’, ‘A’, ‘A’] b = [‘!’, a, ‘!’] print b