Осваиваем Python. Унция 1. Типы данных.

    image
    Продолжаю своё начинание. Данная статья является логическим продолжением первой. Было приятно читать ваши комментарии. Я надеялся, что данный цикл статей окажется для кого-то полезным, но совершенно не предполагал, что заинтересовавшихся будет довольно большое количество. Это заставляет относится к делу серьёзнее и ответственнее.
    Без лишних слов, сразу к делу.


    Как было сказано ранее, практически всё с чем мы имеем дело, программируя на питоне — это объекты. Типы объектов могут быть либо встроенными, либо описанные программистом с помощью классов. В этой статье речь пойдёт о встроенных типах объектов. Они из себя представляют:
    • Числа
    • Строки
    • Кортежи
    • Списки
    • Словари
    • Множества


    Числа, строки и кортежи



    Причина того, что эти типы оказались сведёнными в один раздел, кроется в одном очень важном моменте. Без понимания которого можно допустить трудно обнаруживаемые ошибки. Дело в том, что данные типы в отличии от списков и словарей являются неизменяемыми объектами. Т.е. создав их однажды — изменить их значение не представляется возможным. Возникает справедливый вопрос: каким тогда образом работают следующие инструкции?

    >>> 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.
    Спасибо за внимание! Мы продолжим :)
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 55
    • –4
      хабракат!
      • +10
        *лениво* — чего тебе?
      • 0
        а NoneType куда забыли?
        • 0
          Формат статьи — что-то обязательно окажется обрезанным рамками.
          • +1
            по поводу «градуса» — мне кажется можно было бы заинтересовать новичков красивыми примерами функционального кода на питоне — reduce, list comprehensions. по-моему местное большинство — почитатели php — им это было бы в новинку, и, следовательно, интересно.
            • +1
              будут… нада ж тока с функциями разобраться
            • 0
              И все же, какая связь между питоном и унцией? Еще как-то понятно, если бы изучали silverlight или методологию получения доходов с e-gold…

              Почему не попугаи?!
              • +1
                Связь такая, что в унциях измеряется золото ;)
                • 0
                  Черт. Из-за обилия подобных статей на хабре долго выбирал какой язык начать учить (занимаюсь front-end разработкой, решил познакомиться с чем-нибудь для общего развития).
                  Вы только что меня купили. :)
                  • 0
                    Это радостно слышать! Сегодня будет продолжение.
          • 0
            интересно, как новичку :)
            • 0
              спасибо, оч. интересно, хотелось бы побольше примеров с расшифровкой что и как в данных примерах происходит, ну или ссылочек подкиньте где достать хорошо комментированый код.
              • 0
                питон — это хорошо
                люблю статьи про питон! :)

                НО. но не понимаю зачем в примерах кода на питоне часто используют копипаст из консоли питона? мне одному неудобно читать код с префиксом ">>>"? если да, то прошу прощения за замечание, иначе просьба авторам статей об этом замечательном языке программирования — ну не удобно же читать код с префиксом ">>>"

                спасибо за понимание
                и за статью :)
                • +2
                  Ну какбы показывается, что вот это вводим, а получаем вот это. Очень даже удобно, имхо.
                  • +3
                    не хочу показаться назойливым, но хотя бы минимальное форматирование текста можно сделать? допустим, пропустить строку между соседними парами «ввода-вывода»? читать же удобнее будет
                    • 0
                      Наверное, в следующей статье автор уделит больше внимания коду.
                  • +1
                    просто чтобы понятнее было — что мы вводим, а что выводим
                    пример же может быть и не в две строки
                  • +1
                    а в python 3.0 ввели литералы для множеств

                    L = set(['h','a','h','a'])

                    можно написать так

                    L = {'h','a','h','a'}
                    • +2
                      > В роли ключей могут выступать любые неизменяемые объекты

                      Если более точно, то ключами могут быть любые объекты, которые хэшируемы (термин hashable из глоссария Python'a). При этом, говорить о неизменяемости нужно именно хэш-значения, но не самого объекта. Например, объект, порожденный от пользовательского класса — изменяем (мы можем динамически добавлять новые слоты в него, например), но, тем не менее, имеет неизменяемое хэш-значение (которое также равно его id: id(obj) == obj.__hash__ — True).
                      • 0
                        > id(obj) == obj.__hash__

                        id(obj) == obj.__hash__() # опечатка, __hash__ — метод
                      • –1
                        А я-то думал, что питонов, как и удавов, будут мерять в попугаях, а не унциях…
                        • 0
                          А это значит, если возвращаться к тому с чего мы начали разговор, что, если создать список X, затем сделать присваивание X=Y, а затем изменить X, то Y тоже изменится. Тут нужно переменные местами поменять.
                        • 0
                          «Осваиваем Haskell. Монада первая.» :))
                          • +1
                            Да, гиковость, пожалуйста, подкрутите. :) Я хоть с питоном и не знаком, но все же интереснее будет читать о его отличительных чертах, а не о той части, которая более-менее одинакова во всех динамических языках.
                            Лично мне еще было бы любопытно бы в какой-нибудь из заключающих унций прочитать про особенности портированных версий питона (конкретно — IronPython): какие там есть ограничения, как меняется производительность и т.п.
                            • +1
                              Не все знакомы с динамическими языками в принципе
                            • 0
                              И еще тем, кто хочет учить питон. На python.ru лежит замечательная книга «Язык программирования Python», при этом на русском.
                              • 0
                                В чём её отличительные особенности от перевода официальной документации?
                                • 0
                                  Это и есть перевод официальной документации, туториала и еще чего-то. Только всё оформленов одном файле и с приятным качеством.
                                • +1
                                  тогда уж лучше сразу сюда:

                                  ru.wikibooks.org/wiki/Python
                                • +1
                                  Как я понимаю, статьи описывают 2.Х, тогда ИМХО лучше сразу делать пометки об изменениях в 3.0
                                  • 0
                                    Унция питонов. А лучше будет «попугай первый», хоть питон и не удав.
                                    • 0
                                      А интересно, где больше попугаев: в питоне или удаве? :)
                                      • +1
                                        Питоны они разные. в индийских (читай — индусских) питонах — в два раза больше.
                                    • 0
                                      Хорошая на мой взгляд документация по питону находится здесь: http://ru.diveintopython.org/toc.html
                                      • +1
                                        только переведенные части заканчиваются быстро…
                                      • 0
                                        Жду статью про функциональное программирование на питоне, то ли я балбес, то ли мозг не хочет понимать эту тему
                                        • 0
                                          что вы понимаете под «функциональным программированием»?
                                        • 0
                                          очень интересно, но я ничего не понял. С чего начинать лучше? уровень нулевой, образование гуманитарное. Изучить хочу не для работы, а чисто из интереса.
                                          И да, это не только про питона, а о моих познаниях в программировании в целом
                                          • 0
                                            А это уже тема отдельной статьи. Лично я бы начал с конкретных практических примеров, например, обработки строк и текстовых файлов. В хозяйстве всегда пригодится.
                                          • НЛО прилетело и опубликовало эту надпись здесь
                                            • 0
                                              А как же функции (в том числе методы классов), классы и модули? Это тоже встроенные типы в Python. А еще файлы, слайсы, объекты кода, да много чего еще. Я понимаю, что формат статьи, но хотя бы ссылку на иерархию типов дать можно. И упомянуть о возможности введения собственных типов в расширениях тоже можно.
                                              • +2
                                                Очень радует, что в последнее время на хабре появился такой интерес к Python. Спасибо Вам за хорошую статью. Только, почему-то в статье почти ничего не сказано о том, что данные в кортежах, списках и словарях могут храниться абсолютно разные, например:

                                                >>> M = [1, 'hello', [2, 5, { 'one': (4, 7), 2: «hello world» }], (7, 8)]

                                                >>> M[2]
                                                [2, 5, {2: 'hello world', 'one': (4, 7)}] #здесь видно, что словари сортируются по ключам

                                                >>> M[2][2]
                                                {2: 'hello world', 'one': (4, 7)}

                                                >>> M[2][2][2]
                                                'hello world'

                                                >>> M[2][2]['one']
                                                (4, 7)

                                                >>> M[2][2]['one'][0]
                                                4
                                                >>> M[1]
                                                'hello'

                                                Благодаря этому очень легко создаются двумерные массивы:

                                                >>> m = [[1, 2 ,3], [4, 5, 6], [7, 8, 9]]

                                                >>> m
                                                [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

                                                >>> m[1][1]
                                                5

                                                >>> for col in m:
                                                … print col

                                                [1, 2, 3]
                                                [4, 5, 6]
                                                [7, 8, 9]

                                                Причем кортежи, списки и словари могут содержать в качестве элементов и функции:

                                                >>> def Print_Hello( username = 'world' ):
                                                … print 'Hello %s!' % username


                                                >>> Print_Hello()
                                                Hello world!

                                                >>> S = [1, Print_Hello, 2]

                                                >>> S[1]

                                                >>> S[1]('Habrahabr')
                                                Hello Habrahabr!

                                                Или:
                                                >>> def Func():
                                                … return «Hello world!»


                                                >>> K = [1, Func()]

                                                >>> K
                                                [1, 'Hello world!']

                                                Все примеры показаны на списках, но все это справедливо и для кортежей, и для словарей.
                                                • +2
                                                  Спасибо за хорошее дополнение!
                                                • –3
                                                  Есть же целый блог по питону. Зачем плодить сущности? Тем более, что переводов туториала чуть более, чем дофига.
                                                  • 0
                                                    Какая наиболее популярная библиотека для создания пользовательских интерфейсов на питоне?
                                                    • 0
                                                      Наиболее популярные: Tkinter, PyGTK, PyQt, wxWidgets.
                                                  • 0
                                                    Это я конечно знаю уже, но тем не менее спасибо!
                                                    С нетерпением жду начала разбора джанго:)
                                                    • 0
                                                      может дать ссылки на статьи из блога Python и продолжить с того момента где закончилось? или освещать не упомянутые там моменты, чтобы не повторяться?
                                                      • 0
                                                        Для оптимизации скорости выполнения при объявлении числового или короткого строкового объекта

                                                        А насколько длинным должен быть строковый объект, чтобы значение выражения x is y вернуло False при фактическом равенстве строк?
                                                        • 0
                                                          Очень очень ждем продолжения!
                                                          • 0
                                                            интересно после копипаста кто нибудь проверял это?
                                                            >>> 'string'[0:5:-2]
                                                            'nrs'

                                                            оно не работает! ибо «идти» нужно с конца последовательности, т.е. рабочий пример должен быть таким:
                                                            >>> 'string'[5:0:-2]
                                                            'git'

                                                            кстати, стоит подумать дважды, чтобы понять, что будет при отрицательном step

                                                            docs.python.org/2/library/stdtypes.html

                                                            The slice of s from i to j with step k is defined as the sequence of items with index x = i + n*k such that 0 <= n < (j-i)/k. In other words, the indices are i, i+k, i+2*k, i+3*k and so on, stopping when j is reached (but never including j). If i or j is greater than len(s), use len(s). If i or j are omitted or None, they become “end” values (which end depends on the sign of k). Note, k cannot be zero. If k is None, it is treated like 1.

                                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                            Самое читаемое