Python 02
Python 02
if a % 10 == 0 or b % 10 == 0:
0 Mary
1 had
2 a
3 little
4 lamb
В большинстве таких случаев удобно
использовать функцию enumerate().
Функция enumerate возвращает генератор,
отдающий пары счётчик-элемент для
элементов указанной последовательности.
Прототип функции
enumerate(sequence[, start=0]).
Параметры:
sequence – iterable Любая последовательность,
итератор, или объект, поддерживающий
итерирование.
start=0 -- int начально значение счётчика.
Результат: generator выдаёт пары счётчик-элемент.
Функция применяется в случаях, когда
необходим счётчик количества
элементов в последовательности и
позволяет избавиться от необходимости
инициализировать и обновлять
отдельную переменную-счётчик:
вариант 2
for idx, item in enumerate(sequence):
print(idx)
a=['первый', 'второй', 'третий', \
'четвертый', 'пятый'] 0 первый
for i in range(len(a)): 1 второй
2 третий
print( i, a[i]) 3 четвертый
4 пятый
print(10*'-') ----------
i=0 0 первый
1 второй
for name in a: 2 третий
3 четвертый
print(i, name) 4 пятый
i+=1 ----------
0 первый
print(10*'-') 1 второй
2 третий
for i, name in enumerate(a): 3 четвертый
4 пятый
print(i, name) ----------
print(10*'-')
Странные вещи начинают происходить при
попытке вывода последовательности:
>>> print(range(10))
range(0, 10)
Во многих случаях объект, возвращаемый
функцией range(), ведёт себя как список, но
фактически им не является.
Этот объект возвращает по очереди
элементы желаемой последовательности,
когда вы проходите по нему в цикле, но на
самом деле не создаёт списка, сохраняя
таким образом пространство в памяти.
Такие объекты называются итерируемыми
(iterable),
это все объекты, которые предназначаются для
функций и конструкций, ожидающих от них
поочерёдного предоставления элементов до тех
пор, пока источник не иссякнет.
Оператор for является таким итератором iterator.
Функция list() тоже из их числа — она создаёт
списки из итерируемых объектов:
>>> list(range(5))
[0, 1, 2, 3, 4]
В библиотеке питона есть и другие функции, которые
возвращают и принимают итерируемые объекты
в качестве параметров.
Действительные числа
Рассмотрим действительные числа, имеющие тип float.
Обратите внимание, что если вы хотите считать с клавиатуры
действительное число, то результат, возращаемый
функцией input() необходимо преобразовывать к типу float:
x = float( input() )
Срезы (slices)
Срез (slice) — извлечение из данной строки
одного символа или некоторого фрагмента
подстроки или подпоследовательности.
Есть три формы срезов.
1 Самая простая форма среза: взятие одного символа
строки, а именно, S[i] — это срез, состоящий из одного
символа, который имеет номер i, при этом считая, что
нумерация начинается с числа 0.
То есть если S='Hello', то
S[0]=='H', S[1]=='e', S[2]=='l', S[3]=='l', S[4]=='o'.
Номера символов в строке (а также в других структурах
данных: списках, кортежах) называются индексом.
Если указать отрицательное значение индекса, то
номер будет отсчитываться с конца, начиная с
номера -1.
То есть S[-1]=='o', S[-2]=='l', S[-3]=='l', S[-4]=='e', S[-5]=='H'.
Или в виде таблицы:
Если же номер символа в срезе строки S больше либо равен len(S), или
меньше, чем -len(S), то при обращении к этому символу строки
произойдет ошибка IndexError: string index out of range.
2. Срез с двумя параметрами: S[a:b]
возвращает подстроку из b-a символов, начиная с
символа c индексом a, до символа с индексом b, не
включая его.
Например, S[1:4]=='ell', то же самое получится если
написать S[-4:-1].
Можно использовать как положительные, так и
отрицательные индексы в одном срезе,
например, S[1:-1] — это строка без первого и последнего
символа (срез начинается с символа с индексом 1 и
заканчивается индексом -1, не включая его).
При использовании такой формы среза ошибки IndexError
никогда не возникает.
Например, срез S[1:5] вернет строку 'ello', таким же будет
результат, если сделать второй индекс очень большим,
например, S[1:100] (если в строке не более 100 символов).
Если опустить второй параметр (но
поставить двоеточие), то срез берется от k-
го символа до конца строки S[k:]
Чтобы удалить из строки первый символ (его
индекс равен 0) можно взять срез, начиная
с символа с индексом 1 S[1:]
Если опустить первый параметр, то срез
берется от начала строки до k-го символа
S[: k].
Удалить из строки последний символ можно
при помощи среза S[:-1].
Срез S[:] совпадает с самой строкой S.
3. Если задать срез с тремя параметрами
S[a:b:d], то третий параметр задает шаг, как в
случае с функцией range
S[a:b:d] - будут взяты символы с индексами a, a+d,
a+2*d и т.д.
При задании значения третьего параметра,
равному 2, в срез попадет каждый второй
символ, а если взять значение среза, равное -1,
то символы будут идти в обратном порядке.
s='0123456789‘
s[5:0:-1] -- '54321'
s[5::-1] -- '543210'
Методы
Метод - это функция, применяемая к объекту, в данном
случае - к строке.
Метод вызывается в виде
Имя_объекта.Имя_метода(параметры)
Например, S.find("e") — это применение к строке S метода
find с одним параметром "e".
Метод find и rfind
Объект.find(подстрока)
Метод find находит в данной строке (к которой применяется
метод) подстроку, которая передается в качестве
параметра («поиск с начала строки»).
Функция возвращает индекс первого вхождения
искомой подстроки.
Если же подстрока не найдена, то метод возвращает
значение -1
>>> S = 'Hello'
>>> print(S.find('e'))
1
>>> print(S.find('ll'))
2
>>> print(S.find('L'))
-1
Аналогично, метод rfind возвращает индекс последнего
вхождения данной строки (“поиск справа”):
>>> S = 'Hello'
>>> print(S.find('l'))
2
>>> print(S.rfind('l'))
3
Если вызвать метод find с тремя
параметрами S.find(T, a, b), то поиск
будет осуществляться в срезе S[a:b].
Если указать только два параметра
S.find(T, a), то поиск будет
осуществляться в срезе S[a:] - начиная
с символа с индексом a и до конца
строки.
Метод S.find(T, a, b) возвращает
индекс в строке S, а не индекс
относительно среза.
Метод replace
Метод replace заменяет все вхождения одной
строки на другую.
Формат:
S.replace(old, new)
заменить в строке S все вхождения подстроки
old на подстроку new.
Пример:
>>> 'Hello'.replace('l', 'L')
'HeLLo'
Если методу replace задать еще один
параметр: S.replace(old, new, count),
то заменены будут не все вхождения, а только
не больше, чем первые count из них.
>>> 'Abrakadabra'.replace('a', 'A', 2)
'AbrAkAdabra'
Метод count
Подсчитывает количество вхождений одной строки в
другую строку. Простейшая форма вызова
S.count(T)
возвращает число вхождений строки T внутри строки S.
При этом подсчитываются только непересекающиеся
вхождения, например:
>>> 'Abracadabra'.count('a')
4
>>> ('a' * 100000).count('aa')
50000
При указании трех параметров
S.count(T, a, b),
будет выполнен подсчет числа вхождений строки T в срез
S[a:b].
Цикл while
Цикл while (“пока”) позволяет выполнить одну
и ту же последовательность действий, пока
проверяемое условие истинно.
Условие проверяется до выполнения тела
цикла.
Как правило, цикл while используется, когда
невозможно определить точное значение
количества итераций тела цикла.
Синтаксис цикла while в простейшем случае
выглядит так:
while условие:
блок инструкций
При выполнении цикла while сначала
проверяется условие.
Если оно ложно, то выполнение цикла
прекращается и управление передается на
следующую инструкцию после тела цикла
while.
Если условие истинно, то выполняются
инструкции тела цикла, после чего условие
проверяется снова
Так продолжается до тех пор, пока условие
будет истинно.
Как только условие станет ложно, работа цикла
завершится и управление передастся
следующей инструкции после цикла.
фрагмент программы выведет квадраты всех
целых чисел от 1 до 10 ( цикл while может
заменять цикл for ... in range(...)):
i=1
Тело цикла
while i <= 10: «отступ» ЧЕТЫРЕ пробела
print(i*i)
i += 1
В этом примере переменная i изменяется от 1
до 10. Эта переменная, значение которой
меняется с каждым новым проходом цикла
(итерацией), выполняет роль счетчика.
Заметим, что после выполнения этого
фрагмента значение переменной i будет
равно 11, т.к. при i==11 условие i<=10
впервые перестанет выполняться.
пример использования цикла while для определения
количества цифр натурального числа n:
n = int(input())
length = 0
while n > 0:
n //= 10
length += 1
>>> try:
... import audioop...
except ImportError:
... pass
...
Другой вариант: pass может применяться в качестве заглушки для
тела функции или условия при создании нового кода, позволяя вам
сохранить абстрактный взгляд на вещи.
С другой стороны, оператор pass игнорируется без каких-либо
сигналов и лучшим выбором было бы породить исключение
NotImplementedError:
>>> def initlog(*args):
... raise NotImplementedError # Открыть файл для
# логгинга,
# если он ещё
# не открыт
... if not logfp:
... raise NotImplementedError # Настроить
# заглушку для
# логгинга
... raise NotImplementedError(
'Обработчик инициализации лога вызовов')
... Если бы здесь использовались операторы pass, а позже вы бы
запускали тесты, они могли бы «упасть» без указания причины.
Использование NotImplementedError принуждает этот код породить
исключение, сообщая вам конкретное место, где присутствует
незавершённый код.
Функции
Рассмотрим задачу вычисления числа
сочетаний из n элементов по k, для чего
необходимо вычисление факториалов трех
величин: n, k и n-k.
Для этого можно сделать три цикла, что
приводит к увеличению размера программы
за счет трехкратного повторения похожего
кода.
Вместо этого лучше сделать одну функцию,
вычисляющую факториал любого данного
числа n и трижды использовать эту функцию
в своей программе.
def factorial(n):
f = 1
for i in range(2, n + 1):
f *= i
return f
Этот текст должен идти в начале программы, вернее, до того
места, где мы захотим воспользоваться функцией factorial.
Первая строчка этого примера является описанием
нашей функции. Зарезервированное слово def
предваряет определение функции. За ним должны
следовать «имя функции» -
factorial — идентификатор, то есть имя нашей функции.
После идентификатора в круглых скобках идет список
параметров, которые получает наша функция.
Список состоит из перечисленных через запятую
идентификаторов параметров.
В нашем случае список состоит из одной величины n. В
конце строки ставится двоеточие.
Далее идет тело функции, оформленное в виде
блока, то есть с отступом.
Первым выражением в теле функции может быть
строковой литерал — этот литерал является
строкой документации функции, или док-строкой
(docstring). (не обязательный элемент).
Существуют инструменты, которые используют док-
строки для того, чтобы сгенерировать печатную
или онлайн - документацию или чтобы позволить
пользователю перемещаться по коду
интерактивно;
добавление строк документации в ваш код - это
хорошая практика, постарайтесь к ней привыкнуть.
Внутри функции вычисляется значение
факториала числа n и оно сохраняется в
переменной f.
Функция завершается инструкцией return f,
которая завершает работу функции и
возвращает значение переменной f.
Инструкция return может встречаться в
произвольном месте функции, ее исполнение
завершает работу функции и возвращает
указанное значение в место вызова.
Если функция не возвращает значения, то
инструкция return используется без
возвращаемого значения, также
В функциях, не возвращающих значения,
инструкция return может отсутствовать.
Теперь можно использовать функцию несколько раз.
В этом примере трижды вызываем функцию factorial для
вычисления трех факториалов: factorial(n), factorial(k),
factorial(n-k).
n = int(input())
k = int(input())
print( factorial(n) // \
(factorial(k)*factorial(n-k)) )
Можно, например, объявить функцию binomial, которая
принимает два целочисленных параметра n и k и
вычисляет число сочетаний из n по k:
def binomial(n, k):
return factorial(n)//(factorial(k) * \
factorial(n - k))
Тогда в основной программе можем вызвать функцию
binomial для нахождения числа сочетаний из n по k :
print ( binomial(n, k) )
Рассмотри задачу нахождения наибольшего из
двух или трех чисел. Функцию нахождения
максимума из двух чисел можно написать так:
def max(a, b):
if a > b:
return a
else:
return b
Теперь можем реализовать функцию max3,
находящую максимум трех чисел:
def max3(a, b, c):
return max(max(a, b), c)
Функция max3 дважды вызывает функцию max
для двух чисел: сначала, чтобы найти
максимум из a и b, потом чтобы найти
максимум из этой величины и c.
Локальные и глобальные переменные
Внутри функции можно использовать переменные,
объявленные вне этой функции
def f():
print(a)
a = 1
f()
Здесь переменной a присваивается значение 1, и функция
f печатает это значение, несмотря на то, что в функции f эта
переменная f не инициализируется.
Но в момент вызова функции f переменной a уже
присвоено значение, поэтому функция f может вывести его
на экран.
Такие переменные - объявленные вне функции, но
доступные внутри функции, называются глобальными.
Но если инициализировать какую-то
переменную внутри функции, использовать
эту переменную вне функции не удастся.
Например:
def f():
a=1
f()
print(a)
Получим
NameError: name 'a' is not defined.
Такие переменные, объявленные внутри
функции, называются локальными.
Эти переменные становятся недоступными после
выхода из функции.
Интересным получится результат, если попробовать
изменить значение глобальной переменной внутри
функции:
def f():
a = 1
print(a)
a = 0
f()
print(a)
Будут выведены числа 1 и 0.
То есть несмотря на то, что значение переменной a
изменилось внутри функции, то вне функции оно
осталось прежним!
Это сделано в целях “защиты” глобальных переменных
от случайного изменения из функции
например, если функция будет вызвана из цикла по переменной i, а
в этой функции будет использована переменная i также для
организации цикла, то эти переменные должны быть различными)
Если внутри функции модифицируется значение
некоторой переменной, то переменная с таким именем
становится локальной переменной, и ее модификация
не приведет к изменению глобальной переменной с
таким же именем.
#Эпиграф(ошибка рекурсии…):
def ShortStory():
print("У попа была собака, он ее
любил.")
print("Она съела кусок мяса, он ее
убил,")
print("В землю закопал и надпись
написал:")
ShortStory()
примере функции вычисления факториала.
print('rv=',s1)
s2=concat("111", '222', '333', sep=".")
print('rv=',s2)
Распаковка списков параметров
Обратная ситуация возникает когда параметры уже
содержатся в списке или в кортеже, но должны быть
распакованы для вызова функции, требующей
отдельных позиционных параметров.
Например, встроенная функция range() ожидает
отдельные параметры start и stop соответственно.
Если они не доступны раздельно, для распаковки
аргументов из списка или кортежа в вызове функции
используйте *-синтаксис:
>>> list(range(3, 6)) # обычный вызов с
# отдельными параметрами
[3, 4, 5]
>>> args = [3, 6]
>>> list(range(*args)) # вызов с распакованными из
# списка параметрами
[3, 4, 5]
словари могут получать именованные параметры
через **-синтаксис:
def par(volt, state='stiff', act='go'):
print("action=", act, end=' ')
print("volt=",volt,end=' ')
print("state=", state)
>>> f=m_i(54)
>>> print(f)
<function m_i.<locals>.<lambda> at 0x00000198277E81F0>
>>> f(0)
54
>>> f(1)
55
>>>
Списки
Большинство программ работает не с отдельными
переменными, а с набором переменных. Во многих
задачах нужно иметь возможность работать со всеми
элементами последовательности. В большинстве языков
программирования для этого используется объект
программы, называемый массивом.
В Питоне «формально» массивы как объект программы
существует, но имеется возможность (а некоторые авторы
рекомендуют) использовать «обобщенную» структуру
данных - список
Список представляет собой последовательность
из n элементов, пронумерованных целыми числами
от 0 до (n-1)
Список можно задать перечислением элементов списка в
квадратных скобках, например:
Primes = [2, 3, 5, 7, 11, 13]
Rainbow = ['Red', 'Orange', 'Yellow', 'Green', 'Blue', \
'Indigo', 'Violet']
В списке Primes 6 элементов:
Primes[0] == 2, Primes[1] == 3, Primes[2] == 5,
Primes[3] == 7, Primes[4] == 11, Primes[5] == 13.
Список Rainbow состоит из 7 элементов, каждый из
которых является строкой.
Элементы списка можно индексировать отрицательными
числами с конца, например:
Primes[-1] == 13, Primes[-6] == 2.
Длину списка, то есть количество элементов в нем, можно
узнать при помощи функции len, например:
len(Primes) == 6.
В Питоне предусмотрено несколько способов создания
списка и работы с его элементами
Можно создать пустой список (не содержащий элементов,
длины 0). Пустой список обозначается как [ ]
В конец списка можно добавлять элементы при помощи
метода append.
Например:
программа вводит количество элементов в списке n, а потом
n элементов списка по одному вводятся и из них
формируется список:
A = []
for i in range( int(input() ):
A.append(int(input())
В этом примере создается пустой список, далее считывается
количество элементов в списке, затем по одному
считываются элементы списка и добавляются в его конец.
Для списков целиком определены следующие
основные операции:
конкатенация списков “+” - добавление одного
списка в конец другого
повторение списков “*” «умножение списка на
число».
Например:
A = [1, 2, 3]
B = [4, 5]
C=A+B
D=B*3
список C будет равен [1, 2, 3, 4, 5]
список D будет равен [4, 5, 4, 5, 4, 5].
Например, можно по другому
организовать процесс считывания
списков:
сначала считать размер списка и создать
список из нужного числа элементов,
затем организовать цикл по переменной i
начиная с числа 0 и в теле цикла
считывать и «определять» i-й элемент
списка:
A = [0] * int(input())
for i in range(len(A)):
A[i] = int(input())
Вывести элементы списка A можно одной
инструкцией print(A), при этом будут выведены
квадратные скобки вокруг элементов списка и
запятые между элементами списка.
Такой вывод неудобен, чаще требуется просто
вывести все элементы списка в одну строку
или по одному элементу в строке.
Рассмотрим два примера:
for i in range(len(A)):
print(A[i])
Здесь в цикле по индексу элемента i выводится
элемент списка с индексом i.
for elem in A:
print(elem, end = ' ')
print()
В этом примере элементы списка выводятся
в одну строку, разделенные пробелом, при
этом в цикле меняется не индекс элемента
списка, а само значение переменной.
В цикле
for elem in ['red', 'green', 'blue']
переменная elem будет последовательно
принимать значения 'red', 'green', 'blue'
Методы split и join
Элементы списка могут вводиться по одному в
строке. Строку можно считать функцией input().
После этого можно использовать метод строки
split, возвращающий список строк, «разрезав»
исходную строку на части по пробелам.
Пример:
A = input().split()
Если при запуске этой программы ввести строку 1
2 3, то список A будет равен ['1', '2', '3'].
Обратите внимание, что список будет состоять из
строк, а не из чисел.
Если хочется получить список именно из
чисел, то можно затем элементы списка
по одному преобразовать в числа:
for i in range(len(A)):
A[i] = int(A[i])