Программирование на Python

Кортежи

Разбить на страницы
Показывать лекцию целиком

Кортеж (tuple) - понятие, широко используемое в математике. Для программиста кортеж - это некоторая запись, поля которой могут быть разного типа. Кортеж наследует свойства последовательности, так что элементы кортежа имеют индексы, можно получить прямой доступ к элементу кортежа по его индексу, можно выполнять срезы, получая подпоследовательности элементов, можно выполнять операцию конкатенации кортежей.

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

Константа, имеющая тип кортеж, - это последовательность элементов возможно разного типа, заключенная в круглые скобки.

Доступ к элементам кортежа

Кортеж - это потомок последовательности. Следовательно, возможен доступ к элементу кортежа по его индексу. Доступ к подпоследовательности элементов кортежа задается соответствующим срезом. Если в кортеже n элементов, то индекс элемента должен находиться в пределах от 0 до n - 1. Это же верно для начального индекса среза. Конечный индекс среза может выходить за допустимые пределы, - такой срез задает подпоследовательность, заканчивающуюся последним элементом кортежа.

Кортеж является неизменяемым типом, поэтому доступ возможен только для чтения, но не для записи.

Рассмотрим пример:

  
#Примеры работы с кортежами - class tuple
def test1():    
    #кортежи - индексируемый, неизменяемый тип
    cort1 = (2, 5, ('two', 'five'))
    cort2 = (2, 5, [2, 5], {2, 5}, {'two' : "два", 'five' : "пять"}, ('two', 'five') )
    print(cort1, type(cort1))
    print(cort2)
    item = cort1[2]
    slice1 = cort1[1:5]
    print (item)
    print(slice1)
    #item1 = cort1[3]
    #cort1[2] = 77
    #cort2[3:5] = (55, 77)
test1()

Результаты работы:

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

Конструирование кортежа

Сформировать кортеж можно не только заданием константного кортежа. Конструирование кортежа аналогично конструированию множества. Для множеств метод set, примененный к итерированному объекту преобразует объект в множество. Для кортежей метод tuple преобразует итерируемый объект в кортеж. Зададим строку текста или список. Метод tuple, примененный к строке, создает кортеж, элементами которого являются символы строки. Этот же метод, примененный к списку, создает кортеж, элементами которого являются элементы списка.

Пример:

def test2():
    #создание кортежа по данным строки текста и списка
    s= "Объект_2020"
    cort1 = tuple(s)
    print("s = ", s, " tuple(s) = ", cort1)
    s = [1, 2, 3, "one", "two", "three"]
    cort2 = tuple(s)
    print("s = ", s, " tuple(s) = ", cort2)
test2()

Результаты работы:

Заметьте, метод tuple, также как методы set и str, - это методы приведения данных к нужному типу, задаваемому именем метода приведения. Метод str, например, позволяет данные разных типов приводить к строковому типу str, а метод tuple позволяет выполнить обратное преобразование, приводя строку к типу tuple. В языке Python методы приведения существуют для многих типов. Когда программист создает собственный тип данных (класс), то в методы класса, как правило, включаются методы приведения

Операции над кортежами

Над кортежами определены две операции - сложение кортежей и умножение на число, задаваемые привычными знаками операций: + и *. Используя эти операции, можно строить выражение над кортежами. Операция сложения - это операция конкатенации (сцепления) кортежей. Операция умножения кортежа на целое число n - это n-кратная конкатенация кортежа. При вычислении выражения над кортежами операция умножения имеет, естественно, более высокий приоритет.

Пример:

def test3():
    #операции над кортежами - сложение и умножение на число
    cort = ('a', 'b', 'c')
    cort1 = cort
    print(cort)
    print(cort1)
    cort = cort + ('d', 'e', 'f')
    cort1 = cort1* 3
    print(cort)
    print(cort1)
    cort3 = ('a', 'b') + ('c', 'd') * 2
    print(cort3)
test3()

Результат:

Методы, применимые к кортежам

Рассмотрим методы, применимые к кортежам.

Метод len позволяет определить число элементов кортежа.

Методы list и str преобразуют кортеж соответственно в список и строку.

Метод in позволяет определить, принадлежит ли элемент кортежу.

Метод index позволяет узнать индекс вхождения элемента в кортеж. Он может приводить к возникновению ошибки, если элемента в кортеже нет. Поэтому, чаще всего, используется охраняемый вызов метода.

Метод count позволяет узнать число вхождений некоторого элемента в кортеж.

Пример:

def test4():
    cort = ('a', 'b') + ('a', 'd') * 2 + tuple("abc")
    print(cort)
    n = len(cort)
    print("length of cort = ", n)
    list_cort = list(cort)
    print("list of cort = ",list_cort)
    str_cort = str(cort)
    print("str_cort = ", str_cort)
    count_a = cort.count('a')
    print('count_a = ', count_a)
    count_f = cort.count('f')
    print('count_f = ', count_f)
    index_c = cort.index('c')
    print("index_c = ", index_c)
    if 'f' in cort:
        index_f = cort.index('f')
        print("index_f = ", index_f)
    else:
        print("Нет вхождения 'f' в словарь ")
test4()

Результаты работы:

Моделирование методов вставки, замены, удаления элементов кортежа и подкортежей

Для кортежа не определены методы Insert, Replace, Remove, которые выполняют операции по вставке, замене и удалению элементов кортежа или его подкортежей. Однако, операция конкатенации в сочетании со срезами легко моделирует соответствующие функции. Соответствующие приемы моделирования уже демонстрировались при описании работы со строками, которые также представляют неизменяемый тип. Покажем еще раз как это делается на примере работы с кортежами.

Если нужно вставить новый элемент или кортеж, начиная с позиции k, то конкатенация среза исходного кортежа до позиции k с добавляемым кортежем и срезом, начинающимся в позиции k дает решение поставленной задачи. Также просто задаются выражения, позволяющие заменять один элемент (подкортеж) другим элементом (подкортежем). Удаление элемента (подкортежа) делается еще проще. Рассмотрим соответствующий тест:

def test5():
   #Вставка, замена, удаление подкортежа
   cort = (1, 3, 9, 11)
   cort_p = cort
   print("cort = ", cort)
   print("cort_p = ", cort_p)
   #вставка подкортежа
   cort = cort[: 2] + (5, 7) + cort[2:]
   print("Вставка: ", cort)
   #замена подкортежа
   cort = cort[: 2] + (4, 5, 6, 7, 8) + cort[4 :]
   print("Замена: ", cort)
   #удаление подкортежа
   cort = cort[: 3] + cort[6 :]
   print("Удаление: ", cort)
   #Поиск и Удаление элемента по значению
   if 4 in cort:
       index = cort.index(4)
       cort = cort[: index] + cort[index + 1:]
       print("Удаление по значению: ", cort)
   print("cort_p = ", cort_p)
test5()

Результаты:

Итоги

Кортеж - тип данных во многом похожий на список. Кортеж может содержать элементы разных типов. Кортеж является потомком последовательности и потому возможен доступ к элементам по индексу, срезы задают подкортежи в кортеже.

Основное отличие кортежа от списка состоит в том, что списки относятся к изменяемым типам, а кортежи к неизменяемым. В некоторых учебниках по Python можно найти утверждение, что кортежи используются тогда, когда используются константные объекты, не меняющиеся в ходе выполнения программы. Конечно, если объект не меняется, то, естественно, задавать его кортежем. Но неизменяемость не эквивалентна константности, - это более общее понятие.

Представьте себе ситуацию, когда пациент пришел в поликлинику и принес свою медицинскую карту - card. Три врача A, B, C работают с этим пациентом, с его картой. А_card, B_card, C_card - псевдонимы одного объекта. Каждый врач, проводит анализы, ставит диагноз, назначает лечение, что отражается в карте пациента. Если все действия каждого врача должны быть доступны его коллегам, то карта должна быть объектом изменяемого типа и действия врачей эквивалентны выполнению методов: А_card.update, B_card.update, C_card.update, обновляя состояние карты. Но бывает ситуация, когда лечение пациента - это врачебная тайна, известная только врачу и пациенту. Тогда карта должна быть объектом неизменяемого типа и действия каждого врача с картой эквивалентны выполнению методов: А_card = F(А_card), B_card = F(B_card), C_card = F(C_card). В этом случае все три карты перестают быть псевдонимами и ссылаются на разные объекты.

Изменяемые и неизменяемые типы моделируют разные ситуации, возникающие в прикладных областях. Оба типа являются важными инструментами в арсенале программиста.

Страницы:

Кортеж (tuple) - понятие, широко используемое в математике. Для программиста кортеж - это некоторая запись, поля которой могут быть разного типа. Кортеж наследует свойства последовательности, так что элементы кортежа имеют индексы, можно получить прямой доступ к элементу кортежа по его индексу, можно выполнять срезы, получая подпоследовательности элементов, можно выполнять операцию конкатенации кортежей.

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

Константа, имеющая тип кортеж, - это последовательность элементов возможно разного типа, заключенная в круглые скобки.

Доступ к элементам кортежа

Кортеж - это потомок последовательности. Следовательно, возможен доступ к элементу кортежа по его индексу. Доступ к подпоследовательности элементов кортежа задается соответствующим срезом. Если в кортеже n элементов, то индекс элемента должен находиться в пределах от 0 до n - 1. Это же верно для начального индекса среза. Конечный индекс среза может выходить за допустимые пределы, - такой срез задает подпоследовательность, заканчивающуюся последним элементом кортежа.

Кортеж является неизменяемым типом, поэтому доступ возможен только для чтения, но не для записи.

Рассмотрим пример:

  
#Примеры работы с кортежами - class tuple
def test1():    
    #кортежи - индексируемый, неизменяемый тип
    cort1 = (2, 5, ('two', 'five'))
    cort2 = (2, 5, [2, 5], {2, 5}, {'two' : "два", 'five' : "пять"}, ('two', 'five') )
    print(cort1, type(cort1))
    print(cort2)
    item = cort1[2]
    slice1 = cort1[1:5]
    print (item)
    print(slice1)
    #item1 = cort1[3]
    #cort1[2] = 77
    #cort2[3:5] = (55, 77)
test1()

Результаты работы:

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

Конструирование кортежа

Сформировать кортеж можно не только заданием константного кортежа. Конструирование кортежа аналогично конструированию множества. Для множеств метод set, примененный к итерированному объекту преобразует объект в множество. Для кортежей метод tuple преобразует итерируемый объект в кортеж. Зададим строку текста или список. Метод tuple, примененный к строке, создает кортеж, элементами которого являются символы строки. Этот же метод, примененный к списку, создает кортеж, элементами которого являются элементы списка.

Пример:

def test2():
    #создание кортежа по данным строки текста и списка
    s= "Объект_2020"
    cort1 = tuple(s)
    print("s = ", s, " tuple(s) = ", cort1)
    s = [1, 2, 3, "one", "two", "three"]
    cort2 = tuple(s)
    print("s = ", s, " tuple(s) = ", cort2)
test2()

Результаты работы:

Заметьте, метод tuple, также как методы set и str, - это методы приведения данных к нужному типу, задаваемому именем метода приведения. Метод str, например, позволяет данные разных типов приводить к строковому типу str, а метод tuple позволяет выполнить обратное преобразование, приводя строку к типу tuple. В языке Python методы приведения существуют для многих типов. Когда программист создает собственный тип данных (класс), то в методы класса, как правило, включаются методы приведения

Операции над кортежами

Над кортежами определены две операции - сложение кортежей и умножение на число, задаваемые привычными знаками операций: + и *. Используя эти операции, можно строить выражение над кортежами. Операция сложения - это операция конкатенации (сцепления) кортежей. Операция умножения кортежа на целое число n - это n-кратная конкатенация кортежа. При вычислении выражения над кортежами операция умножения имеет, естественно, более высокий приоритет.

Пример:

def test3():
    #операции над кортежами - сложение и умножение на число
    cort = ('a', 'b', 'c')
    cort1 = cort
    print(cort)
    print(cort1)
    cort = cort + ('d', 'e', 'f')
    cort1 = cort1* 3
    print(cort)
    print(cort1)
    cort3 = ('a', 'b') + ('c', 'd') * 2
    print(cort3)
test3()

Результат:

Методы, применимые к кортежам

Рассмотрим методы, применимые к кортежам.

Метод len позволяет определить число элементов кортежа.

Методы list и str преобразуют кортеж соответственно в список и строку.

Метод in позволяет определить, принадлежит ли элемент кортежу.

Метод index позволяет узнать индекс вхождения элемента в кортеж. Он может приводить к возникновению ошибки, если элемента в кортеже нет. Поэтому, чаще всего, используется охраняемый вызов метода.

Метод count позволяет узнать число вхождений некоторого элемента в кортеж.

Пример:

def test4():
    cort = ('a', 'b') + ('a', 'd') * 2 + tuple("abc")
    print(cort)
    n = len(cort)
    print("length of cort = ", n)
    list_cort = list(cort)
    print("list of cort = ",list_cort)
    str_cort = str(cort)
    print("str_cort = ", str_cort)
    count_a = cort.count('a')
    print('count_a = ', count_a)
    count_f = cort.count('f')
    print('count_f = ', count_f)
    index_c = cort.index('c')
    print("index_c = ", index_c)
    if 'f' in cort:
        index_f = cort.index('f')
        print("index_f = ", index_f)
    else:
        print("Нет вхождения 'f' в словарь ")
test4()

Результаты работы:

Моделирование методов вставки, замены, удаления элементов кортежа и подкортежей

Для кортежа не определены методы Insert, Replace, Remove, которые выполняют операции по вставке, замене и удалению элементов кортежа или его подкортежей. Однако, операция конкатенации в сочетании со срезами легко моделирует соответствующие функции. Соответствующие приемы моделирования уже демонстрировались при описании работы со строками, которые также представляют неизменяемый тип. Покажем еще раз как это делается на примере работы с кортежами.

Если нужно вставить новый элемент или кортеж, начиная с позиции k, то конкатенация среза исходного кортежа до позиции k с добавляемым кортежем и срезом, начинающимся в позиции k дает решение поставленной задачи. Также просто задаются выражения, позволяющие заменять один элемент (подкортеж) другим элементом (подкортежем). Удаление элемента (подкортежа) делается еще проще. Рассмотрим соответствующий тест:

def test5():
   #Вставка, замена, удаление подкортежа
   cort = (1, 3, 9, 11)
   cort_p = cort
   print("cort = ", cort)
   print("cort_p = ", cort_p)
   #вставка подкортежа
   cort = cort[: 2] + (5, 7) + cort[2:]
   print("Вставка: ", cort)
   #замена подкортежа
   cort = cort[: 2] + (4, 5, 6, 7, 8) + cort[4 :]
   print("Замена: ", cort)
   #удаление подкортежа
   cort = cort[: 3] + cort[6 :]
   print("Удаление: ", cort)
   #Поиск и Удаление элемента по значению
   if 4 in cort:
       index = cort.index(4)
       cort = cort[: index] + cort[index + 1:]
       print("Удаление по значению: ", cort)
   print("cort_p = ", cort_p)
test5()

Результаты:

Итоги

Кортеж - тип данных во многом похожий на список. Кортеж может содержать элементы разных типов. Кортеж является потомком последовательности и потому возможен доступ к элементам по индексу, срезы задают подкортежи в кортеже.

Основное отличие кортежа от списка состоит в том, что списки относятся к изменяемым типам, а кортежи к неизменяемым. В некоторых учебниках по Python можно найти утверждение, что кортежи используются тогда, когда используются константные объекты, не меняющиеся в ходе выполнения программы. Конечно, если объект не меняется, то, естественно, задавать его кортежем. Но неизменяемость не эквивалентна константности, - это более общее понятие.

Представьте себе ситуацию, когда пациент пришел в поликлинику и принес свою медицинскую карту - card. Три врача A, B, C работают с этим пациентом, с его картой. А_card, B_card, C_card - псевдонимы одного объекта. Каждый врач, проводит анализы, ставит диагноз, назначает лечение, что отражается в карте пациента. Если все действия каждого врача должны быть доступны его коллегам, то карта должна быть объектом изменяемого типа и действия врачей эквивалентны выполнению методов: А_card.update, B_card.update, C_card.update, обновляя состояние карты. Но бывает ситуация, когда лечение пациента - это врачебная тайна, известная только врачу и пациенту. Тогда карта должна быть объектом неизменяемого типа и действия каждого врача с картой эквивалентны выполнению методов: А_card = F(А_card), B_card = F(B_card), C_card = F(C_card). В этом случае все три карты перестают быть псевдонимами и ссылаются на разные объекты.

Изменяемые и неизменяемые типы моделируют разные ситуации, возникающие в прикладных областях. Оба типа являются важными инструментами в арсенале программиста.

Вернуться к учебному плану