Кортежи в языке Python имеют тип (класс) tuple и представляют собой
неизменяемые последовательности элементов, значениями которых могут быть данные разных типов. По
сути это списки, которые нельзя после создания изменять.
Подобно другим рассмотренным типам кортежи могут быть созданы как в виде литералов, так и с
помощью консруктора класса – встроенной функции tuple([iterable])
(см. подраздел 8.1 лаб. раб. №1).
При использовании литерала в круглые скобки помещают элементы кортежа,
разделенные запятыми:
>>>
a_tuple=(3.45,
'JS'
, [1,2])
>>>
a_tuple
(3.45, 'JS', [1, 2]).
Можно круглые скобки не указывать, перечисляя элементы кортежа через
запятые. Результат будет тот же:
>>>
a_tuple=3.45,
'JS'
, [1,2]
>>>
a_tuple
(3.45, 'JS', [1, 2]).
Выполняется и обратная операция – отдельным объектам
присваиваются значения элементов кортежа:
>>>
a,b,c=a_tuple
>>>
a
3.45
>>>
b
'JS'
>>>
c
[1, 2].
При использовании функции tuple([iterable])
в качестве ее аргумента указывается итерабельный тип, из элементов которого будет создан кортеж:
>>>
a_list=[0.01,
'Web'
, 37,
True
]
>>>
b_tuple=
tuple
(a_list)
>>>
b_tuple
(0.01, 'Web', 37, True).
При вызове конструктора без аргумента:
>>>
tuple
()
()
создается пустой кортеж – (),
который в логическом контексте соответствует False (любой другой кортеж – True).
Поскольку кортежи являются неизменяемыми последовательностями:
>>>
from
collections
import
Sequence, MutableSequence
>>>
isinstance
(a_tuple, Sequence)
True,
>>>
isinstance
(a_tuple, MutableSequence)
False,
они поддерживают все операции, свойственные этим типам объектов
(см подраздел 1.4.2 лаб. раб. №3).
Например, операцию добавления элемента к кортежу:
>>>
a_tuple+=
'a'
,
'b'
(3.45, 'JS', [1, 2], 'a', 'b').
Однако при добавлении одноэлементного кортежа:
>>>
a_tuple+=(77)
возникает ошибка:
TypeError: can only concatenate tuple (not "int") to tuple,
т.е. присоединить к кортежу можно только кортеж (не целое число). Дело в том, что (77) было
воспринято не как одноэлементный кортеж, а как выражение целого типа. Поэтому одноэлементный кортеж
необходимо задать следующим образом:
>>>
a_tuple+=(77,)
>>>
a_tuple
(3.45, 'JS', [1, 2], 'a', 'b', 77).
Работа с кортежами выполняется быстрее, чем со списками. Поэтому, если
имеется набор значений, который не будет меняться, его лучше реализовать как кортеж. Кортежи
делают код безопаснее в том случае, если нужно защитить данные от записи.
Примером использования кортежей служит разработка игры
"Анаграмма", рассмотренная в подразделе 1.3. Поскольку при этом возникает
нобходимость получения случайных величин, рассмотрим методы их генерации, представленные в модуле
random.
Загрузим модуль random и определим с помощью встроенной функции
dir()
(см. подразделы 8.1 лаб. раб. №1 и
2.4 лаб. раб. №6 ) пространство имен этого модуля:
>>>
import
random
>>>
dir
(random)
['BPF', 'LOG4', 'NV_MAGICCONST', 'RECIP_BPF', 'Random', 'SG_MAGICCONST', 'SystemRandom', 'TWOPI',
'_BuiltinMethodType', '_MethodType', '_Sequence', '_Set', '__all__', '__builtins__', '__cached__',
'__doc__', '__file__', '__initializing__', '__loader__', '__name__', '__package__', '_acos',
'_ceil', '_cos', '_e', '_exp', '_inst', '_log', '_pi', '_random', '_sha512', '_sin', '_sqrt',
'_test', '_test_generator', '_urandom', '_warn', 'betavariate', 'choice', 'expovariate',
'gammavariate', 'gauss', 'getrandbits', 'getstate', 'lognormvariate', 'normalvariate',
'paretovariate', 'randint', 'random', 'randrange', 'sample', 'seed', 'setstate', 'shuffle',
'triangular', 'uniform', 'vonmisesvariate', 'weibullvariate'];
Как видно из приведенного выше списка имен, модуль
random содержит большое количество методов, связанных с генерацией
случайных чисел (точнее, псевдослучайных чисел). Из них рассмотрим следующие:
Необходимо отметить, что модуль random не должен быть использован в приложениях, где требуется криптографическая безопастность генератора псевдослучайных чисел. Вместо него применяйте метод ssl.RAND_bytes() модуля ssl.
Рассмотрим программу ana.py, которая предназначена для создания игры
"Анаграмма" (анаграммы – это слова, образованные из исходного слова путем перестановки букв).
Суть игры заключается в следующем: программа выбирает слово (из списка заранее приготовленных),
переставляет в нем случайным образом буквы, формируя анаграмму, и предлагает ее пользователям. Их
задачей является отгадать исходное слово:
# Создание анаграмм
import
random
WORDS=
'компьютер'
,
'питон'
,
'сервер'
,
'клиент'
,
'браузер'
,
'протокол'
,
'программа'
,
'процессор'
,
'контекст'
word=random.choice(WORDS)
correct=word
ana=
''
while
word:
pos=random.randrange(
len
(word))
ana+=word[pos]
word=word[:pos]+word[pos+1:]
print
(
'''
<<Игра АНАГРАММА>>
Для выхода нажмите Enter '''
)
print
(
'Вот анаграмма: '
,ana.upper())
ans=
input
(
'Попробуй отгадать слово '
)
while
ans != correct
and
ans !=
''
:
print
'Ответ неправильный'
)
ans=
input
(
'Попробуй еще раз '
)
if
ans == correct:
print
'Молодец!'
)
print
'Спасибо за игру'
)
input
(
).
Поскольку при создании анаграмм выбор слова и перестановку букв в нем
необходимо осуществлять случайным образом, программа начинается с подключения модуля
random (см. подраздел 1.2), который содержит необходимые методы для выполнения
случайного выбора.
Набор исходных слов, из которых будут формироваться анаграммы задается
в виде кортежа, имя которого (WORDS) задано заглавными буквами. Это сделано для того, чтобы
показать, что его значениями являются константы. Использование констант делает программу более
понятной и легко читаемой.
Необходимо однако сказать, что правило задавать константы заглавными
буквами в языке Python является прежде всего соглашением между программистами и интерпретатором не
поддерживается, т.е. значения, имена которых заданы заглавными буквами можно изменить точно так,
как значения, имена которых заданы строчными буквами. Но в силу указанных выше причин этого делать
не следует.
Отметим, что в программе элементы кортежа при перечислении указываются
с новой строки без использования символов обратного слэша, как это предусмотрено при задании
длинных операторов (см. подраздел 6.1
лаб. раб. №1) и длинных строк (см. подраздел 2.1
лаб. раб. №2). Это допускается делать при перечислении элементов последовательностей, указанных в
круглых "()", квадратных "[]" и фигурных "{}" скобках.
Для выбора одного из слов кортежа WORDS используется метод
choice() модуля random
(см. подраздел 1.2, который случайным образом выбирает один из элементов кортежа
и сохраняет его в переменной word.
Затем начинается собственно процесс формирования анаграммы в
переменной ana, которая вначале является пустой строкой. При этом в цикле,
пока переменная word не примет значение '',
что в логическом контексте означает False, будут выполняться следующие
действия:
После выхода из цикла переменная word становится пустой строкой, а в
переменной ana сформирована анаграмма.
Вторая часть программы связана с организацией игры с пользователем:
Диапазоны (англ. ranges), как новый тип последовательностей range,
появились в языке Python, начиная с версий 3.x. До этого функция xrange(),
которая в 3.x не используется, возвращала последовательность чисел класса
list.
Для создания элементов класса range
необходимо использовать конструктор – встроенную функцию
range([start,] stop [, step])
(см. подраздел 8.1 лаб. раб. №1), которая
возвращает неизменяемую виртуальную последовательность
чисел от start до stop - 1 с шагом
step. Значениями по умолчанию для необязательных аргументов
start и step являются соответственно 0 и 1:
>>>
r=
range
(10)
>>>
r
range(0, 10)
>>>
for
_
in
r:
print
(_, end=
' '
)
0 1 2 3 4 5 6 7 8 9
>>>
r=
range
(-5,6)
>>>
r
range(-5, 6)
>>>
for
_
in
r:
print
(_, end=
' '
)
-5 -4 -3 -2 -1 0 1 2 3 4 5
>>>
r=
range
(1,12,2)
>>>
r
range(1,12,2)
>>>
for
_
in
r:
print
(_, end=
' '
)
1 3 5 7 9 11
Можно представить числа, формируемые функцией
range(), в виде последовательности определенного типа, использовав
соответствующий конструктор, например, в виде списка:
>>>
list
(
range
(1,12,2))
[1, 3, 5, 7, 9, 11],
или в виде кортежа:
>>>
tuple
(
range
(20,10,-3))
(20, 17, 14, 11).
Если stop не превышает
start, то формируется пустая последовательность чисел, логическим
значением которой является False:
>>>
bool
(
range
(1,1))
False
Если step = 0 :
>>>
r=
range
(1,5,0)
ValueError:
range() arg 3 must not be zero,
возникает исключение: 3-й аргумент функции range() не может быть 0.
Будучи неизменяемой последовательностью:
>>>
from
collections
import
Sequence, MutableSequence
>>>
isinstance
(range(7), Sequence)
True,
>>>
isinstance
(range(7), MutableSequence)
False,
тип range, как и типы list и
tuple, поддерживает все общие операции, свойственные неизменяемым
последовательностям
(см. подраздел 1.4.2 лаб. раб. №3), кроме операции
конкатенации ("+"). Например, можно получить значение элемента последовательности по его индексу:
>>>
range
(7)[5]
5.
Для работы с двоичными данными в языке Python имеются встроенные типы данных bytes и bytearray, которые поддерживаются типом memoryview, использующим буферный протокол (buffer protocol) для доступа к другим, находящимся в памяти, двоичным объектам без необходимости их копирования.
Объекты bytes являются неизменяемыми последовательностями одиночных
байтов. Поскольку многие двоичные протоколы базируются на ASCII-кодировании текста, объкты
bytes предлагают несколько методов, которые допускают работу только с
ASCII-совместимыми данными и тесно связаны со строковыми объектами.
Во-первых, синтаксис литералов bytes во
многом совпадает с синтаксисом строковых литералов, за исключением того, что добавляется префикс
b:
Только ASCII-символы разрешается использовать в литералах объекта
bytes (независимо от объявленного кодирования исходного кода):
>>>
b'кириллица'
SyntaxError: bytes can only contain ASCII literal characters.
Поэтому любые значения литералов bytes, превыщающие 127, должны быть
преобразованы в литералы bytes с использованием соответствующих
ESC-последовательнвостей.
Так же как строковые литералы, литералы
bytes
могут использовать префикс r для экранирования ESC-последовательностей.
Литералы и строк и объектов bytes в общем случае могут иметь следующие
варианты префикса: r | R |
b | B | br
| Br | bR | BR.
Хотя литералы и представление объектов
bytes базируются на ASCII-тексте, они на самом деле ведут себя как
незменяемые последовательности целых чисел, значение каждого из которых x
находится в пределах 0 <= x < 256. При попытках выйти за это органичение вызывет ошибку
ValueError.
Помимо использования литеральной формы объекты
bytes также можно создавать с помощью конструктора класса –
встроенной функции bytes([source[, encoding[, errors]]])
(см. подраздел 8.1 лаб. раб. №1). Необязательный аргумент
source используется для указания одного из нескольких вариантов создания
объекта bytes:
Отметим, что для объекта b типа bytes
b[0] будет целым числом, в то время как b[0:1]
объектом bytes длины 1: Объекты bytearray являются изменяемым вариантом объектов
bytes, т.е. представляет собой изменяемую последовательность целых чисел
x в диапазоне 0 <= x < 256. Оба типа – и bytes, и bytearray,
являясь последовательностями: Все остальные строковые методы поддерживаются, хотя иногда с небольшими различиями в
функциональности:
Экземпляры как типа bytes, так и типа
bytearray поддерживают метод
decode(encoding="utf-8", errors="strict"), который является обратным по
отношению к методу str.encode() и возвращает строку, являющуюся
результатом декодирования заданной последовательности байтов. По умолчанию кодировка имеет значение
'utf-8', обработка ошибки – "strict", что означает выработку исключения UnicodeError при
обнаружении ошибки кодирования, другими возможными значениями являются: 'ignore', 'replace' и
'xmlcharrefreplace', а также любое другое имя, которое зарегистрировано в codecs.register_error.
Приведем примеры использования методов encode() для строк и
decode() для объектов bytes: 1 Разработать программу на языке Python, которая выполняет следующее:
2. Разработать программу, которая:
Таблица 1 – Перечень индивидуальных заданий
>>>
b=
bytes
(
range
(5))
>>>
b[0]
0,
>>>
b[0:1]
b'\x00'.
Этим объекты типа bytes отличаются от текстовых
строк, где индексное значение и срез строки длиной 1 означают строку длины 1:
>>>
s=
"cat"
>>>
s[0]
'c',
>>>
s[0:1]
'c'.
3.2 Тип bytearray
Литеральные формы создания объектов типа
bytearray не используются. Эти объекты могут быть созданы с помощью
конструктора класса – встроенной функции
bytearray([source[, encoding[, errors]]])
(см. подраздел 8.1 лаб. раб. №1).
Необязательный аргумент source используется для указания нескольких
вариантов создания объекта bytearray:
>>>
bytearray
(5)
bytearray(b'\x00\x00\x00\x00\x00');
>>>
bytearray
([7,255,0])
bytearray(b'\x07\xff\x01');
>>>
bytearray
(
'cat'
,
'utf-8'
)
bytearray(b'cat');
>>>
bytearray
()
bytearray(b'').
3.3 Операции над объектами типов bytes и bytearray
>>>
from
collections
import
Sequence
>>>
isinstance
(bytes(2), Sequence)
True,
>>>
isinstance
(bytearray(2), Sequence)
True,
поддерживают все операции, присущие базовым последовательностям
(см. подраздел 1.4.2 лаб. раб. №3).
Благодаря общему использованиюю ASCII текста, как базиса для двоичного
протокола, объекты типов bytes) и bytearray)
используют почти все методы, присущие текстовым строкам
(см. подраздел 2.6 лаб. работы №1), за исключением:
>>>
a=
'cat'
>>>
a.replace(
'a'
,
'u'
)
'cut',
>>>
b=
b'cat'
>>>
b.replace(
b'a'
,
b'u'
)
b'cut';
>>>
'cat'
.encode(encoding=
'utf-8'
)
b'cat',
>>>
b'cat'
.decode()
'cat',
>>>
b=
"питон"
.encode()
>>>
b
b'\xd0\xbf\xd0\xb8\xd1\x82\xd0\xbe\xd0\xbd',
>>>
b.decode()
'питон'.
Индивидуальные задания
Номер
п/пТип
элементаДиапазон Вывод Вариант
1 1,2,3,5 1,25 1 1
2 2,3,5,6 2,32,2 2 2
3 3,4,5,6 -10,10 3 3
4 1,6,3,5 -7,21,3 1 4
5 2,5,4,3 11 2 5
6 1,2,3,5 1,60,5 3 1
7 2,3,5,6 20,0,-2 1 2
8 3,4,5,6 1,25 2 3
9 1,6,3,5 2,32,2 3 4
10 2,5,4,3 -10,10 1 5
11 1,2,3,5 -7,21,3 2 1
12 2,3,5,6 11 3 2
13 3,4,5,6 1,60,5 1 3
14 1,6,3,5 20,0,-2 2 4
15 2,5,4,3 1,25 3 5
16 1,2,3,5 2,32,2 1 1
17 2,3,5,6 -10,10 2 2
18 3,4,5,6 -7,21,3 3 3
19 1,6,3,5 11 1 4
20 2,5,4,3 1,60,5 2 5