Основы Python — кратко. Часть 3. Списки, кортежи, файлы.

    В общем-то последняя из готовых глав. Остальные будут выходить чуть реже, поскольку еще не написаны (но я уверен что будут, хотя это зависит только от ваших пожеланий, уважаемые читатели :)

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

    В общем, те кому не интересно — читают следующую новость, а остальных — прошу пройти .

    Python для начинающих. Глава третья. «List, tuple, etc.»

    Кортежи.
    Кортежи (англ. tuple) используется для представления неизменяемой последовательности разнородных объектов. Они обычно записываются в круглых скобках, но если неоднозначности не возникает, то скобки можно опустить.

    >>> t = (2, 2.05, "Hello")
    >>> t
    (2, 2.0499999999999998, 'Hello')
    >>> (a, b, c) = t
    >>> print a, b, c
    2 2.05 Hello
    >>> z, y, x = t
    >>> print z, y, x
    2 2.05 Hello
    >>> a=1
    >>> b=2
    >>> a,b=b,a
    >>> print a,b
    2 1
    >>> x = 12,
    >>> x
    (12,)

    Как видно из примера, кортеж может быть использован и в левой части оператора присваивания. Значения из кортежа в левой части оператора присваивания связываются с аналогичными элементами правой части. Этот факт как раз и дает нам такие замечательные возможности как массовая инициализация переменных и возврат множества значений из функции одновременно. Последний пример демонстрирует создание кортежа из одного элмента (его часто называют синглтоном).

    Списки

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

    Простое перечисление:
    >>> a = [2, 2.25, "Python"]
    >>> a
    [2, 2.25, 'Python']

    Преобразуем строку в список
    >>> b = list("help")
    >>> b
    ['h', 'e', 'l', 'p']

    Создание с помощью списковых включений. В данном случае мы берем кубы всех нечетных чисел от 0 до 19. Этому синтаксису я планирую посвятить отдельное занятие.
    >>> c = [x ** 3 for x in range(20) if x%2==1]
    >>> c
    [1, 27, 125, 343, 729, 1331, 2197, 3375, 4913, 6859]

    Для работы со списками определен ряд операторов и функций:
    len(s) Длина последовательности s
    x in s Проверка принадлежности элемента последовательности. В новых версиях Python можно проверять принадлежность подстроки строке. Возвращает True или False
    x not in s = not x in s
    s + s1 Конкатенация последовательностей
    s*n или n*s Последовательность из n раз повторенной s. Если n < 0, возвращается пустая последовательность.
    s[i] Возвращает i-й элемент s или len(s)+i-й, если i < 0
    s[i:j:d] Срез из последовательности s от i до j с шагом d будет рассматриваться ниже
    min(s) Наименьший элемент s
    max(s) Наибольший элемент s
    s[i] = x i-й элемент списка s заменяется на x
    s[i:j:d] = t Срез от i до j (с шагом d) заменяется на (список) t
    del s[i:j:d] Удаление элементов среза из последовательности

    Кроме того, для списков определен ряд методов.
    append(x) Добавляет элемент в конец последовательности
    count(x) Считает количество элементов, равных x
    extend(s) Добавляет к концу последовательности последовательность s
    index(x) Возвращает наименьшее i, такое, что s[i] == x. Возбуждает исключение ValueError, если x не найден в s
    insert(i, x) Вставляет элемент x в i-й промежуток
    pop(i) Возвращает i-й элемент, удаляя его из последовательности
    reverse() Меняет порядок элементов s на обратный
    sort([cmpfunc]) Сортирует элементы s. Может быть указана своя функция сравнения cmpfunc

    Для преобразования кортежа в список есть функция list, для обратной операции — tuple.

    Об индексировании списков и выделении подпоследовательностей следует еще раз упомянуть отдельно (этот механизм работает аналогично и для строк). Для получения элемента используются квадратные скобки, в которых находится индекс элемента. Элементы нумеруются с нуля. Отрицательное значение индекса указывает на элементы с конца. Первый с конца списка (строки) элемент имеет индекс -1.

    >>> s = [0, 1, 2, 3, 4]
    >>> print s[0], s[-1], s[3]
    0 4 3
    >>> s[2] = -2
    >>> print s
    [0, 1, -2, 3, 4]
    >>> del s[2]
    >>> print s
    [0, 1, 3, 4]

    Сложнее обстоят дела со срезами. Для получения срезов последовательности в Пайтоне принято указывать не номера элементов, а номера «промежутков» между ними. Перед первым элементом последовательности промежуток имеет индекс 0, перед вторым – 1 и так далее. Отрицательные значения отсчитывают элементы с конца строки.
    В общем виде срез записывается в следующем виде:
    список[начало: конец: шаг]
    По умолчанию начало среза равно 0, конец среза равен len(список), шаг равен 1. Если шаг не указывается, второй символ «:» можно опустить.
    С помощью среза можно указать подмножество для вставки списка в другой список, даже при нулевой длине. Это удобно для вставки списка в строго определенной позиции.

    >>> l = range(12)
    >>> l
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
    >>> l[1:3]
    [1, 2]
    >>> l[-1:]
    [11]
    >>> l[::2]
    [0, 2, 4, 6, 8, 10]
    >>> l[0:1]=[-1,-1,-1]
    >>> l
    [-1, -1, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
    >>> del l[:3]
    >>> l
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
    

    Словари

    Словарь (хэш, предопределенный массив) – изменяемая структура данных, предназначенная для хранения элементов вида ключ: значение. Все легко показывается на примере.

    Создаем хеши.
    >>> h1 = {1:"one", 2:"two", 3:"three"}
    >>> h2 = {0:"zero", 5:"five"}
    >>> h3 = {"z":1, "y":2, "x":3}
    #Цикл по паре ключ-значение
    >>> for key, value in h1.items():
    ...     print key, " ", value
    ...
    1   one
    2   two
    3   three
    
    #Цикл по ключам
    >>> for key in h2.keys():
    ...     print key, " ", h2[key]
    ...
    0   zero
    5   five
    
    #Цикл по значениям
    >>> for v in h3.values():
    ...     print v
    ...
    2
    3
    1
    
    #Добавление элементов из другого хеша
    >>> h1.update(h3)
    
    #Количество пар в хеше
    >>> len(h1)
    6

    Тип file

    Объекты этого типа предназначены для работы с внешними данными. Чаще всего данному объекту соответствует файл на диске, но это далеко не всегда так. Файловые объекты должны поддерживать основные методы: read(), write(), readline(), readlines(), seek(), tell(), close() и т.п.

    Следующий пример показывает копирование файла:
    f1 = open("file1.txt", "r")
    f2 = open("file2.txt", "w")
    for line in f1.readlines():
      f2.write(line)
    f2.close()
    f1.close()

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

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

    import urllib
    f1 = urllib.urlopen("http://python.onego.ru") 

    Задачи:
    — Разработать программу «массовой закачки» URL-ов из файла urls.txt
    — Разработать программу, скачивающую страницу по указанному URL со всем ее содержимым.
    — Написать программу, которая получив на входе произвольный список удалит из него все повторяющиеся элементы.
    Метки:
    Поделиться публикацией
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 58
    • 0
      в избранное. хорошая работа.
      но "Dive Into Python" уже почитал чуть-чуть)))
      • 0
        так продолжайте. оно того стоит :)
        жаль только перевод обрывается слишком рано...
        • +1
          так у меня образование переводчика есть... :) при чем основное...

          я литературу, в основном, на английском и читаю)))
          • 0
            А не хотите доперевести, если время есть? ;)
            • 0
              хм... сейчас я имею несколько проектов. времени не очень то и есть свободного.
              филолог то я украинский. я русский плоховато знаю. делаю очень много орфографических ошыбок. а если делать что-то, то делать качественно. :)
              • 0
                мужик, ты хоть на урк. переведи умаляю, братьев словян больше, переведуть =)
      • 0
        Уже одну утилитку для работы написал на питоне(или пайтоне?) после того, как ты начал писать о нем.

        Спасибо, продолжай в том же духе!
        • –2
          не поверите! аж две. длинной в целых 17 и 21 строчку. так удобненько, просто нереально. только очень медленно получается

          а если серьезно - я не уловил повода вашего сарказма.
          • 0
            Если серьезно, я не понял, о каком сарказме идет речь.

            Я серьезно благодарен за статью и серьезно доволен скоростью написания небольших и не сложных программ.
            • +1
              прошу прощения. конкретный недосып делает свое злое дело :(
              увидел сарказм там где его в помине не было.
              просто мой парсер неправильно распарсил вашу фразу. еще раз извините.
              • 0
                Я вас понимаю :) Радуюсь тому моменту, что с сегодняшнего дня отпуск и вдоволь отосплюсь(мечта).
        • 0
          автор молодец, продолжай в том же духе!
          • 0
            спасибо
            только сегодня делал на питоне парсер :)
            правда меня доканал синтаксис вроде этого

            dic = {}
            dic['key1'] = {}
            dic['key2'] = {}
            dic['key1']['key3'] = 5
            dic['key2']['key4'] = 6

            явное обьявление словарем в строках 2-3 меня доканывает :) непривычно
            • 0
              ну нет в пайтоне РНР-style массивов :)
              • 0
                Можно чуть короче:
                 dic = {'key1': {'key3':5}, 'key2': {'key4':6}}
                • 0
                  нельзя короче по причине того что ключи формируются динамически
                  Это в моем конкретном случае просто невозможно.
                  Хотя с вашей формой записи согласен для заранее известной структуры словаря
                  • 0
                    > dic = {}
                    > dic['key1'] = {}
                    > dic['key2'] = {}
                    > dic['key1']['key3'] = 5
                    > dic['key2']['key4'] = 6

                    а разве на php есть реализация такого массива с заранее неизвестной структурой? )
                    • 0
                      $dic['key1']['key3'] = 5;
                      $dic['key2']['key4'] = 6;

                      оно?)
              • 0
                Насколько правильно делать так:
                s={1:'one',2:'two'}
                for i in s:
                print i

                Вместо использзования цикла
                for i in s.keys():
                print i
                • 0
                  для класса dict определен метод __iter__ возвращающий итератор по ключам.
                  так что, принципиально ничем не отличается.
                  • 0
                    вполне правильно
                    как и так:
                    >>> for k, v in s.iteritems():
                    ... print k, v
                    ...
                    1 one
                    2 two


                    вообще, я думаю что наиболее правильно как раз использовать .iterkeys(), .itervalues() и .iteritems(), хотя это мое предположение
                  • –6
                    Ой, в рот мне "пайтон"!
                    • 0

                      Создание с помощью списковых включений. В данном случае мы берем кубы всех нечетных чисел от 1 до 20. Опечатка - от 0 до 19.

                      • 0
                        это не опечатка, честно. это я стормозил. простите, сейчас поправлю.
                      • 0
                        в принципе, ниче так. правда, на мой взгляд, немного скучновато.
                        я бы еще настоятельно рекомендовал добавить сюда такие полезности как sorted, перегон из списка пар в словарь и наоборот, а также map/zip и т.п.
                        • 0
                          все будет, если не будет форсмажора :) но не сразу...
                        • +2
                          Написать программу, которая получив на входе произвольный список удалит из него все повторяющиеся элементы.

                          самый простой пример:

                          my_list = [1,2,3,4,1,2,6,9,2,3,8,4,5,76,2,5,6,7]
                          unique_list = list(set(my_list))
                          # [1, 2, 3, 4, 5, 6, 7, 8, 9, 76]
                          • 0
                            мне кажется, порядок элементов имеет значение...
                            • 0
                              ну скажем про порядок речи не шло. так что как первый вариант это подходит :)
                              хотя про функцию set речь не шла
                              но вариант сохраняющий порядок - остается на повестке дня :)))
                              • 0
                                как это можно сделать "в лоб":
                                s=[1,2,3,2,3,4,5,1,3,0]
                                c=[]
                                for i in s:
                                if i not in c:
                                c.append(i)
                                • +1
                                  интересно почему такой вариант:

                                  a = [1,2,3,4,1,2,6,9,2,3,8,4,5,76,2,5,6,7]
                                  b = [ e for i,e in enumerate(a) if e not in a[i+1:] ]
                                  print b

                                  не сохраняет порядок? (хотя по идее должен).
                                  у меня в результате [1, 9, 3, 8, 4, 76, 2, 5, 6, 7]
                                  • +1
                                    не должен. смотри, ты проверяешь первый элемент. он есть в хвосте и ты его пропускаешь.
                                    тоесть ты оставляешь только последние вхождения уникальных элементов.
                                    я сделал так:
                                    [x for i, x in enumerate(l) if l.index(x) == i]
                                    но это тоже жусть.
                                    • 0
                                      а можно расписать словами как расшифровывается эта конструкция ?:)
                                      был бы очень признателен
                                      • +1
                                        ну, l.index(x) - возвращает индекс первого вхождения х в l.
                                        enumerate(l) возвращает итератор, выдающий пары значений вида (i, l[i]), где i=0..len(l).
                                        таким образом мы идем по списку l, получая из него по-очереди пары индекс-значение, и если индекс элемента совпадает с индексом его первого вхождения в l, то мы его оставляем в "результате".

                                        синтаксис "списочных генераторов" я распишу позже...
                                        • +1
                                          да, конечно.

                                          фактически, мы строим новый список, итерируя по старому: включаем новый элемент в список (левая часть, та что до оператора for) если выполнено некоторое условие (правая часть, та что if).

                                          итак, enumerate возвращает список пар вида (индекс-елемента, значение-элемента). мы итерируем по нему и проверяем, если индекс текущего элемента равен индексу первого вхождения этого элемента в исходный список, дополняем новый список текущим элементом.
                                          • 0
                                            спасибо - меня просто смутил синтаксис
                                            надеюсь cleg в след уроке обьяснит более подробно :)
                                            • 0
                                              куда ж он денется... :)
                                      • +1
                                        Вот так сохраняет и в прошлом случае тоже сохранял, только с конца.
                                        a = [1,2,3,4,1,2,6,9,2,3,8,4,5,76,2,5,6,7]
                                        b = [ e for i,e in enumerate(a) if e not in a[:i] ]
                                        print b
                                        • 0
                                          всё, понял ошибку.
                                          засиживаться после работы - вредно :)
                                      • 0
                                        родил решение в одну строчку, но получился жесткач какой-то... страшно показывать :)
                                        • 0
                                          мне уже стало интересно, покажите пожалуйста :)
                                          • +1
                                            написал выше. дублирую:
                                            [x for i, x in enumerate(l) if l.index(x) == i]
                                          • 0
                                            Быть може так:
                                            b=[a[i] for i in range(len(a)) if a[i] not in a[:i]]
                                            (a - исходная последовательность)

                                            Кто короче?
                                    • 0
                                      Подглядываете в Pleac? :)
                                    • 0
                                      Тупой и банальный алгоритм, сохраняющий порядок :)
                                      >>> my_list = [1,2,3,4,1,2,6,9,2,3,8,4,5,76,2,5,6,7]
                                      >>> ulist = []
                                      >>> for i in my_list:
                                      ... if i not in ulist:
                                      ... ulist.append(i)
                                      ...
                                      >>> ulist
                                      [1, 2, 3, 4, 6, 9, 8, 5, 76, 7]
                                      • 0
                                        это правильно но не элегантно - да и потребует дополнительного расхода памяти на больших обьемах данных.
                                        в вашем варианте я бы лично добавил del из изначального массива елемента который мы прошли
                                        либо переделал бы алгоритм без использования дополнительного массива
                                      • +1
                                        а django будете обучать?
                                        • 0
                                          посмотрим :) тут самому пайтону еще чить и учить...
                                          но конечно было бы неплохо. постараюсь в общем...
                                        • 0
                                          "В данном случае мы берем кубы всех нечетных чисел от 0 до 19."
                                          ...
                                          "[1, 9, 25, 49, 81, 121, 169, 225, 289, 361]"
                                          Но это квадраты, а не кубы. Поправьте, пожалуйста :)
                                          • 0
                                            ок. спасибо :( столько раз на рвоном месте ошибиться - непростительно для меня.
                                          • 0
                                            import urllib

                                            urls = open(«urls.txt», «r»)

                                            for url in urls.readlines():
                                            #tab#outfile = open(url.rstrip()+«.htm», «w»)
                                            #tab#outurl=urllib.urlopen(«http://»+url.rstrip())
                                            #tab#for line in outurl.readlines():
                                            #tab##tab#outfile.write(line)
                                            #tab#outurl.close()
                                            #tab#outfile.close()
                                            • 0
                                              ну в принципе тоже вариант :)

                                              ЗЫ добавил кармы, по идее должны теперь работать у вас теги
                                              • 0
                                                а какие ещё варианты возможны?
                                                • 0
                                                  ну, как минимуму сократить
                                                  outfile.write(outurl.read())

                                                  кстати — логичнее было бы назвать inurl — оно ж все-таки входящее :)
                                            • 0
                                              % — скажите пожалуйста что этот знак означает в Пиайтоне? В примере он указывается, а что делает не пойму ???
                                            • 0
                                              Подскажите как пользоваться count (x) для определения одинаковых элементов в строке?

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