Пользователь
0,0
рейтинг
25 июля 2008 в 17:03

Разработка → Основы 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 со всем ее содержимым.
— Написать программу, которая получив на входе произвольный список удалит из него все повторяющиеся элементы.
Павел Дмитриев @cleg
карма
149,8
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (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
                спасибо :)
            • 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) для определения одинаковых элементов в строке?

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