Как сделать последовательность чисел в python

Обновлено: 07.07.2024

Часто возникает ситуации, когда нужно выполнить некоторое действие с последовательностью объектов той или иной природы. С самой простой из них мы уже давно знакомы: перебор целых чисел в арифметической прогрессии.

Рассмотрим более сложный пример, перебор чисел Фибоначчи. Конечно же можно писать так: Но это не слишком-то эффективно, мы будем считать числа Фибоначчи каждый раз с самого начала, хотя следующее число может быть элементарно получено из двух предыдущих.

ОК, можно сделать и так: С числами Фибоначчи получилось даже не так страшно, но если на вычисление очередного объекта требуется десятки строчек кода, то наше do_something(. ) утонет в обвязке.

Ну ладно, тогда есть ещё одно решение: сделать список чисел Фибоначчи: Уже почти божественно. Но предположим, что число n равно 100000. Тогда мы зачем-то будем хранить 100000 чисел Фибоначчи, хотя в любой момент времени нам нужно не более двух (одним пользуемся, второе нужно для вычисление следующего числа). Кроме того, может оказаться, что на шаге 179 нужно прерваться, и 99821 чисел были вычислены совершенно зря.

Ленивые вычисления и генераторы

Было бы идеально, если бы функция fibonacci(n) вычисляла очередное число Фибоначчи только в тот момент, когда оно действительно понадобится, и при этом запоминало своё состояние — два текущих числа Фибоначчи — для быстрого вычисления очередного числа. Такая стратегия называется ленивыми вычислениями. Её можно было бы реализовать, используя глобальные переменные. Однако в языке Python специально для таких задач существуют генераторы (generators) (не путать с генераторами списков, словарей и множеств (list, dictionary, set comprehension)).

Пример генератора чисел Фибоначчи и нескольких способов им воспользоваться:

Итак, для того, чтобы сделать из обычной функции генератор, нужно вместо return использовать yield . В результате получится не функция, которую можно вызвать и получить результат её работы, а итерируемый объект, из которого можно последовательно выдёргивать результаты его работы до тех пор, пока не будет исполнена последняя строчка кода генератора, либо не будет выполнен выход командой return . При этом после выдачи результата командой yield состояние генератора, все его внутренние переменные сохраняются. При следующей попытке выдернуть элемент из генератора работа начнётся со строчки, следующей за yield .

Чтобы изучить работу генератора чисел Фибоначчи, попробуйте запустить следующий код:

Итак, достаточно внутри функции хоть раз воспользоваться командой yield , чтобы сделать из неё генератор. После этого её нельзя вызвать так, как обычно (попробуйте print(fibonacci(5)) ), но можно использовать в for , list , sorted , map , zip , enumerate и так далее.

Распаковка

Для того, чтобы сделать использование функций ещё удобнее, в Python есть оператор * — распаковка. Его можно применять только применительно к параметрам вызываемой функции. При этом происходит следующее: из объекта, к которому применяется распаковка, извлекаются отдельные элементы и передаются в качестве отдельных параметров: Рассмотрим пример: Здесь функция func1() возвращает кортеж из трёх чисел, а функция func2() принимает на вход три элемента. Результат работы первой функции можно передать сразу во вторую, если распаковать результат её работы.

Другой пример использования распаковки --- это передача одного и того же набора параметров в разные функции:

Очень удобно использовать распаковку — внутри функции print : Таким образом, можно быстро выводить содержимое списков, результаты работы генераторов или функций, возвращающих кортежи или списки.

Также при помощи распаковки можно передавать числовые параметры из стандартного ввода в функцию в одну строчку:

01: Квадраты чисел Фибоначчи

Напишите генератор square_fibonacci(n) , генерирующий последовательность квадратов чисел Фибоначчи. Выведите результат при помощи функции print и распаковки.

Ввод Вывод

02: Генератор факториалов

Напишите генератор factorials(n) , генерирующий последовательность факториалов натуральных чисел.

Ввод Вывод

03: Генератор треугольных чисел

Напишите генератор triangular_numbers(n) , генерирующий последовательность треугольных чисел.

Ввод Вывод

04: Степени числа по модулю n

Напишите генератор mod_powers(a, n) , генерирующий последовательность степеней числа \(a\) по модулю \(n\) \(a^0, a^1, \ldots, a^k \pmod\) до тех пор, пока очередная степень не будет равна 1. Гарантируется, что числа \(a\) и \(n\) взаимно просты.

Ввод Вывод

05: Биномиальные коэффициенты

Напишите генератор binomial_coefficients(n) , генерирующий последовательность биномиальных коэффициентов \(C^0_n, C^1_n, \ldots, C^n_n\). Запрещается использовать факториалы.

Ввод Вывод

06: Квадратный корень и Вавилон

Еще 4000 лет назад вавилонские ученые составляли наряду с таблицами умножения и таблицами обратных величин таблицы квадратов чисел и квадратных корней из чисел. При этом они умели находить приблизительное значение квадратного корня из любого целого числа. Для извлечения корня из числа \(a\) они использовали последовательность \(x_1 = 1\), \(x_ = \displaystyle\frac\left(x_n + \displaystyle\frac\right)\), предел которой как раз равен \(\sqrt\).

Напишите генератор babylonian_sequence(a) , генерирующий данную последовательность до тех пор, пока отличие \(x_n^2\) от \(a\) не станет меньше \(10^\).

Ввод Вывод

Генераторы и рекурсия

Так же как и в функциях, в генераторах можно использовать рекурсию. Вот пример генератора, который порождается все последовательности длины n из букв a, b : Здесь точно также нужно следить за тем, чтобы рекурсия не стала бесконечно глубокой.

R ange — это встроенная функция Python, которая возвращает итерируемый объект ( range object ), содержащий целые числа. С помощью функция range() можно сгенерировать последовательность чисел с определенным шагом — далее их можно легко перебирать с помощью цикла for .

В статье подробно рассказываю, как работает range() , чем отличается её реализация в Python 2 и Python 3, а также приведу практические примеры использования.

Синтаксис

Функцию range() можно использовать с одним или несколькими параметрами. В документации Python синтаксис выглядит следующим образом:

У функции 3 параметра:

  • start — начало последовательности [включительно] (не обязательный параметр, по умолчанию равен 0).
  • stop — задает точку остановки последовательности [значение не включено в последовательность] (обязательный параметр).
  • step — шаг последовательности (не обязательный параметр, по умолчанию равен 1).

Функция range() возвращает объект класса range :

☝️ При работе с range() важно помнить следующее:

  • Значение stop не входит в последовательность;
  • Все аргументы функции должны быть целыми числами (положительными или отрицательными);
  • При отрицательном шаге step нужно помнить, что значение start должно быть больше значения stop ;
  • Значение step не должно быть равно 0, иначе Python вызовет исключение " ValueError ".

📃 Более подробное описание функции можно посмотреть в официальной документации или через help("range") :

class range(object) | range(stop) -> range object | range(start, stop[, step]) -> range object | | Return an object that produces a sequence of integers from start (inclusive) | to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, . j-1. | start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3. | These are exactly the valid indices for a list of 4 elements. | When step is given, it specifies the increment (or decrement). | .

for i in range

Чаще всего range() используется в циклах for .

Основной кейс — выполнение цикла N-раз:

С помощью range() можно перебрать все значения в последовательности:

str = 'abcdef' for i in range(len(str)): print(str[i], end=' ') > a b c d e f

Или найти сумму первых 10-ти целых чисел.

А так можно перебрать значения последовательности через одного:

s = 'a1b2c3d4e5f6g7h8' for i in range(0, len(s), 2): print(s[i], end=' ') > a b c d e f g h

С помощью функции range() можно организовать сдвиг букв в слове на одну позицию и получить все возможные варианты такого сдвига:

s = 'питон' for i in range(len(s)): s = s[1:] + s[:1] print(s, end=' ') > итонп тонпи онпит нпито питон

Или получить все числа из заданного диапазона, делящиеся на любое нужное. Например, напечатаем таблицу умножения на 8:

count = 1 for i in range(8, 80, 8): print(count, ' * 8 = ', i) count += 1 > 1 * 8 = 8 > 2 * 8 = 16 > 3 * 8 = 24 > 4 * 8 = 32 > 5 * 8 = 40 > 6 * 8 = 48 > 7 * 8 = 56 > 8 * 8 = 64 > 9 * 8 = 72

Операции с range

Объект range поддерживает все операции, доступные последовательностям (кроме сложения и умножения):

Также объект range можно привести к списку ( list ) или множеству ( set ):

>>> numbers = range(13) >>> numbers_list = list(numbers) >>> type(numbers_list) >>> numbers_list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] >>> numbers_set = set(numbers) >>> type(numbers_set) >>> numbers_set

range и тип float

По умолчанию функция range() позволяет использовать только целые числа в качестве параметров. Если вы передадите значение с плавающей точкой, то Python вызовет исключение TypeError :

numbers = range(1.5) print(numbers) > Traceback (most recent call last): File "test.py", line 1, in numbers = range(1.5) TypeError: 'float' object cannot be interpreted as an integer

Чтобы сгенерировать последовательность из чисел с плавающей точкой, можно использовать стороннюю библиотеку NymPy (её нужно предварительно установить). В ней есть функция arange() , похожая на стандартную range() :

import numpy as np float_numbers = np.arange(4.6, 5.8, 0.3) print(float_numbers) > [4.6 4.9 5.2 5.5 5.8]

Если вы не хотите устанавливать библиотеку NymPy, то можно написать собственную функцию, например так:

def f_range(start, stop, step): while start [4.6, 4.9, 5.2, 5.5, 5.8]

Отличия между range в python2 и python3

Range() в Python2 и Python3 — это разные функции, которые отличаются друг от друга.

В Python2 функция range() возвращает объект list , то есть она выдает все числа сразу и помещает из в оперативную память. Поэтому, при генерации длинных последовательностей, увеличивается расход памяти и время работы.

Функция xrange() в Python2 и range() в Python3 не генерируют вся последовательность чисел сразу, а выдают нужные значения по мере необходимости, при переходе к следующей итерации цикла.

Таким образом, xrange() используемая в Python2 и range() в Python3 являются аналогами.

Best Practices

range в обратном порядке (python reverse range)

Получить последовательность в обратном порядке можно с помощью отрицательного аргумента step :

Обратите внимание, что start > stop , и stop не входит в последовательность.

range включительно

step = 2 numbers = range(2, 10 + step, step) for i in numbers: print(i, end=' ') > 2 4 6 8 10

range до бесконечности

Так как у функции range() есть обязательный параметр stop , бесконечный цикл сделать не получится.

Но это можно сделать через itertools :

import itertools import time for i in itertools.count(): print(f"iter -> ") time.sleep(1) > iter -> 0 > iter -> 1 > iter -> 2 > .

Или через бесконечный цикл while :

import time i = 0 while True: print(f"iter -> ") i += 1 time.sleep(1) > iter -> 0 > iter -> 1 > iter -> 2 > .

range → в список (list) или множество (set)

С помощью range можно сгенерировать список ( list ):

Или сгенерировать множество ( set ):

Функция range() генерирует последовательность целых чисел и обычно используется для организации перебора в циклах for . При этом аргументами могут быть только целые числа, использование типов float, string и других недопустимо. Передаваемые значения могут быть как положительные, так и отрицательные, но step не может быть равен нулю.

Последовательности могут быть как изменяемыми, так и неизменяемыми. Размерность и состав созданной однажды неизменяемой последовательности не может меняться, вместо этого обычно создаётся новая последовательность.

Последовательности поддерживают сравнение (обычно производится лексикографически).
Пользовательские последовательности подчиняются Протоколу последовательностей.

Примеры последовательностей в стандартной библиотеке:

Список (list)изменяемая
Кортеж (tuple)неизменяемая
Диапазон (range)неизменяемая
Строка (str, unicode)неизменяемая
Массив (array.array)изменяемая

Адресация элементов

Доступ к значениям последовательностей производится при помощи индексов — целых чисел, означающих позиций элементов.

Нумерация индексов начинается с 0 (нуля).

Если по указанному индексу значение отсутствует, возбуждается исключение IndexError.

Сравнение последовательностей

При сравнение используется лексикографический порядок, сравниваются два элемента, идущих друг за другом, начиная с первого. Вложенные последовательности одинакового типа сравниваются рекурсивно. Последовательности равны, если их элементы равны.

+py3.0 При лексикографическом сравнении для строк используются номера кодовых точек Юникода.

Проход по элементам

Проход по элементам последовательности производится при помощи for in:

Количество элементов

Количество элементов в последовательности можно получить, используя функцию len().

Слияние (конкатенация)

Конкатенация двух последовательностей производится при помощи + .

Повторение

Повторение (множение) элементов последовательностей производится при помощи * .

Рекомендуемые методы

Пользовательским последовательностям по примеру таковых же из стандартной библиотеки рекомендуется реализовать следующие методы.

Базовые__contains__(), __iter__()
Для изменяемых последовательностейappend(), count(), extend(), index(), insert(), pop(), remove(), reverse(), sort()
Для поддержки слияния и повторения__add__(), __iadd__(), __imul__(), __mul__(), __radd__(), __rmul__()

Для перегрузки математических операций (умножение — повторение, а сложение — конкатенация) следует использовать только указанные методы. Прочие методы для работы с числами реализовываться не должны.


При создании коллекций элементов на Python циклы for заменяются однострочными выражениями. Python поддерживает четыре типа особенных генераторов, называемых также включениями:

  1. Списковые включения (генераторысписков, Listcomps).
  2. Словарные включения (генераторы словарей, Dictcomps).
  3. Множественные включения (генераторы множеств, Setcomps).
  4. Генераторные выражения (GenExp).

Синтаксис генератора списков устроен следующим образом:

Часть с условием if указывается опционально.

Пример

Давайте создадим список чисел, исключив из него все отрицательные значения — для начала решим задачу с помощью обычного цикла for :

Для быстрого, лаконичного и наглядного создания словарей язык программирования Python предлагает воспользоваться специальным сокращением для циклического перебора элементов, известным как “генератор словарей”.

Синтаксис генератора словарей устроен следующим образом:

Пример

Давайте возведем в квадрат все числовые значения словаря при помощи словарного включения:

Генератор множества одновременно похож на словарное включение и на списковое включение: фигурные скобки, как у словарей, остальной синтаксис выражения — как у списков. Основное отличие генератора множеств от словарного включения заключается в том, что для генерации словаря указываются ключ и значение через двоеточие, а для генерации множества — одно только значение.

Синтаксис генератора множеств устроен следующим образом:

Пример

Давайте создадим список произвольных чисел и множество парных чисел на его основе:

При помощи генератора множеств подобная программа пишется в одну строчку:

Подобно включениям, выражение генератора предлагает сокращенный синтаксис для цикла for .

Синтаксис генераторных выражений следующий:

Пример

Давайте возведем в квадрат все четные числа списка и отбросим все нечетные.

Для начала решим задачу с помощью обычного цикла for :

С помощью выражения-генератора можно вообще забыть о потребности в функции square_even() и сделать то же самое с помощью одной строки кода:

При взгляде на синтаксис генераторных выражений, сразу же в голову приходит мысль: как написать кортежное включение?

Генераторное выражение можно передавать в качестве параметра любой функции-конструктору стандартных типов данных Python:

Только что вы узнали о четырех типах генераторов последовательностей в Python.

Теперь важно научиться избегать соблазна заменить все циклы for в ваших проектах на включения: давайте обсудим, в каких случаях генераторы последовательностей не подходят.

Короче говоря, не используйте включения, когда они снижают качество вашего кода!

Хороший пример — это работа со вложенными циклами for . Если написать вложенный цикл for в виде включения, то код станет короче на несколько строк, но его качество рискует ухудшиться.

Давайте рассмотрим матрицу; она часто представляется в Python как список из списков. Если вы хотите отобразить матрицу в одном измерении, то можете применить двойное списковое включение:

Код лаконичен, но, возможно, не так интуитивно понятно, что он делает: если вместо включения написать вложенный цикл for, то программа сразу станет более понятным:

Наконец, давайте посмотрим на производительность включений в сравнении с обычным циклом for :


Аналогичный бенчмарк для генераторов множеств и словарей дает схожие результаты: включение работает немного быстрей.

Для генераторных выражений сравнение с циклом for + yield бессмысленно: оба возвращают объект-генератор почти мгновенно. Время не тратится на вычисление значений, поскольку генераторы не хранят значения.

Следовательно, не стоит универсально везде применять включения для повышения производительности программ. Выигрыш в скорости выполнения незначителен по сравнению с вредом, наносимым длинными и многословными включениями. Применяйте генераторы последовательностей только тогда, когда это очистит ваш код без снижения его качества.

Включения превращают циклы for в однострочные выражения.

Python поддерживает четыре вида включений для стандартных структур данных:

  1. Списковые включения.
  2. Словарные включения.
  3. Множественные включения.
  4. Генераторные выражения.

Разумное применение включений улучшает качество вашего кода, но откажитесь от слепой замены всех циклов на выражения, ведь иногда замена вложенного цикла for на включение снижает понятность кода.

Включения выполняются быстрее, чем цикл for , однако разница — всего 10%, поэтому вместо производительности отдавайте предпочтение качеству кода.

Читайте также: