Продолжаю своё начинание. Данная статья является логическим продолжением первой. Было приятно читать ваши комментарии. Я надеялся, что данный цикл статей окажется для кого-то полезным, но совершенно не предполагал, что заинтересовавшихся будет довольно большое количество. Это заставляет относится к делу серьёзнее и ответственнее.
Без лишних слов, сразу к делу.
Как было сказано ранее, практически всё с чем мы имеем дело, программируя на питоне — это объекты. Типы объектов могут быть либо встроенными, либо описанные программистом с помощью классов. В этой статье речь пойдёт о встроенных типах объектов. Они из себя представляют:
- Числа
- Строки
- Кортежи
- Списки
- Словари
- Множества
Числа, строки и кортежи
Причина того, что эти типы оказались сведёнными в один раздел, кроется в одном очень важном моменте. Без понимания которого можно допустить трудно обнаруживаемые ошибки. Дело в том, что данные типы в отличии от списков и словарей являются неизменяемыми объектами. Т.е. создав их однажды — изменить их значение не представляется возможным. Возникает справедливый вопрос: каким тогда образом работают следующие инструкции?
>>> x = 2
>>> x
2
>>> x = 3
>>> x
3
>>> x = 'string'
>>> x
'string'
Инструкция x = 2 создаёт числовой объект со значением 2 и присваивает ссылку на этот объект переменной x. Далее инструкция x = 3 создаёт новый числовой объект со значением 3 и присваивает ссылку на него переменной x. А объект со значением 2 удаляется из памяти автоматическим сборщиком мусора т.к. была потеряна последняя ссылка на этот объект.
Благодаря этому справедливо следующее:
>>> x = y = 3 # переменные x и y содержат одну и ту же ссылку на объект 3
>>> x = 2 # переменная x теперь содержит ссылку на другой объект 2
>>> x
2
>>> y # y по-прежнему ссылается на объект 3
3
В тему будет упомянуть про оператор is. Этот оператор возвращает значение True, когда слева и справа от него находятся переменные содержащие указатели на один и тот же объект. Возникает вопрос о странном поведении этого оператора:
>>> x = 2
>>> y = 2 # создано два разных объекта
>>> x is y # по идее должно быть возвращено значение False
True
Здесь дело в кэширующих внутренних механизмах самого интерпретатора. Для оптимизации скорости выполнения при объявлении числового или короткого строкового объекта — в кэше создаётся пара ссылка и значение. И в дальнейшем при объявлении такого же объекта — не создаётся новый объект, а используется уже созданный. Напрашивается вывод о несостоятельности использования оператора is для числовых и строковых типов данных.
Дальше всё просто!
Типы числовых литералов:
- целые числа неограниченной длины — интерпретатор сам определит необходимость использования объектов неограниченной длины и сделает необходимые преобразования. Более нет необходимости следить за переполнениями.
- Числа с плавающей точкой
- восьмеричные и шестнадцатеричные числа
- комплексные числа
Некоторые операции над числами:
>>> print 2 ** 150 # 2 в степени 150
1427247692705959881058285969449495136382746624
>>> print int(5.89),round(5.89),round(5.89,1) # округление вниз, вверх, с точностью до 1 знака
5 6.0 5.9
>>> import math
>>> math.pi
3.1415926535897931
>>> print math.sin(math.pi/2)
1.0
>>> import random
>>> random.randint(1,100) # случайное целое число в диапазоне от 1 до 100
19
Строки:
Строки в апострофах и в кавычках — это одно и то же
Строки в тройных кавычках — в тройные кавычки можно заключить целый блок строк, например целиком HTML или XML документ.
Неформатированные строки — строки вида r«\n\t» — последовательности в такой строке не будут заменены на спец. Символы
Строки символов юникода — u'string' # теряет актуальность в версии 3.0 подробнее об изменениях 3.0
Базовые операции над строками:
>>> print str(len('string'))*3 # len() — возвращает количество символов в строке
666 # * — перегруженый оператор, делающий повтор строки указанное число раз
>>> 'r' in 'string' # оператор in возвращает True если подстрока найдена в строке
True
>>> 'string'.replace('r','') # замена одной подстроки на другую
'sting'
>>> 'string'.find('ri') # возвращает номер смещения искомой подстроки
2
>>> 'a,b,c'.split(',') # функция разделения на подстроки по указанному символу или подстроке
['a', 'b', 'c']
Более полную информацию о строковых методах можно получить, введя в интерактивном режиме команду help(str).
Так же строки уже были описаны моим будущим соавтором этого цикла статей тут
Индексирование, выборка и срезы последовательностей данных.
Думаю, о том, что к элементам строки можно получать доступ по их индексам, как в массиве — особо долго рассказывать не нужно.
>>> 'string'[1]
't'
>>> 'string'[-2] # второй элемент с конца строки
'n'
Срез — достаточно мощный инструмент выборки данных из последовательностей, который используется не только в строках но и в коллекциях, речь о которых пойдёт в этой статье чуть ниже.
Общий вид:
S[i:j:h], где S — строка, i — значение смещения, левая граница (включительно), j — значение смещения, правая граница (она не входит в срез), h — значение шага.
Примеры:
>>> 'string'[0:4]
'stri'
>>> 'string'[:-2]
'stri'
>>> 'string'[0:5:2]
'srn'
>>> 'string'[0:5:-2]
'nrs'
Говоря о строках, конечно, нельзя забыть о регулярных выражениях. В Python для их использования необходимо импортировать модуль re
Я надеюсь, что о них удастся поговорить отдельно.
Кортежи
Кортеж — это упорядоченная, неизменяемая коллекция объектов произвольных типов, поддерживающая произвольное число уровней вложенности.
Основы синтаксиса так же уже описывал cleg в статье
Списки и словари
Списки и словари являются изменяемыми встроенными типами данных. А это значит, если возвращаться к тому с чего мы начали разговор, что, если создать список Y, затем сделать присваивание X=Y, а затем изменить X, то Y тоже изменится. За этим нужно внимательно следить! Для того, чтобы этого не происходило, необходимо создать новый объект эквивалентный исходному, например, так: X=Y[:]
Иллюстрация:
>>> M = L = range(2,12,3)
>>> print M,L
[2, 5, 8, 11] [2, 5, 8, 11]
>>> L[2] = 112
>>> print M,L
[2, 5, 112, 11] [2, 5, 112, 11]
>>> M = L[:]
>>> L[2] = 0
>>> print M,L
[2, 5, 112, 11] [2, 5, 0, 11]
Или, если требуется обеспечить неизменность созданного объекта — использовать вместо списков кортежи.
Списки — потрясающе гибкий инструмент, представляющий из себя упорядоченную коллекцию элементов, который может включать в себя какие угодно объекты с каким угодно уровнем вложенности.
Словарь — является неупорядоченной коллекцией объектов, доступ к элементам которой предоставляется не с помощью смещения, а с помощью ключа.
За основами синтаксиса так же можно перейти к статье clega
Здесь я лишь внесу некоторые дополнения и замечания по использованию словарей:
- операции над последовательностями неприменимы к словарям т.к. словари — это не последовательность, а отображение.
- Ключи не обязательно должны быть строками. В роли ключей могут выступать любые неизменяемые объекты. Т.е. если рассматривать встроенные типы данных, то — это числа, строки и кортежи. Ясно, что при использования чисел, словарь превращается в подобие списка, однако, остаётся при этом неупорядоченным. Используя в качестве ключа кортежи, появляется возможность использовать составные ключи. Экземпляры пользовательских классов так же могут выступать в качестве ключей при условии, что они реализуют определённые методы указывающие интерпретатору на то, что объект является неизменяемым.
Множества
Множества — это контейнеры для других объектов. Множества создаются встроенной функцией set и поддерживают типичные математические операции над множествами
>>> M = set('habrahabr')
>>> L = set(['h','a','h','a'])
>>> M, L
(set(['a', 'h', 'r', 'b']), set(['a', 'h']))
>>> M & L
set(['a', 'h'])
>>> M | L
set(['a', 'r', 'h', 'b'])
>>> M - L
set(['r', 'b'])
>>> bool(M - L)
True
>>> pusto = set()
>>> bool(pusto)
False
Элементами множества могут стать любые неизменяемые объекты.
После того, как мы проделали определённые операции над множествами — их можно разместить обратно в список, например, так:
>>> S = []
>>> for i in M - L:
... S.append(i)
...
>>> S
['r', 'b']
На этом всё на сегодня.
Пользуясь терминологией Радио-Т хочется задать вопрос :) Куда подкрутить градус гиковости, по вашему мнению? Если вверх, то на мой взгляд, циклы и ветвления стоит раскрыть только с точки зрения особенностей присущих Python.
Спасибо за внимание! Мы продолжим :)