Python: колекції, частина 3: конкатенація, додавання і видалення елементів

imageПродовжимо вивчати загальні принципи роботи зі стандартними колекціями (модуль collections в ній не розглядається) Python. Розглядатимуться способи конкатенації (об'єднання) колекцій з формуванням нової або зміною вихідної, а також способи додавати та видаляти елементи змінювані колекції.

Дана стаття є продовженням моєї статті "Python: колекції, частина 2: індексування, зрізи, сортування".

Для кого: для вивчають Python і вже мають початкове уявлення про колекціях і роботі з ними, які бажають систематизувати і поглибити свої знання, скласти їх у цілісну картину.

ЗМІСТ:

  1. Конкатенація рядків, кортежів, списків, словників без зміни вихідних.
  2. Конкатенація множин без зміни вихідних.
  3. Конкатенація списку, словника і змінюваного безлічі зі зміною вихідної колекції.
  4. Додавання і видалення елементів змінюваних колекцій.
  5. Особливості роботи із змінною і не змінною колекцією.
1 Конкатенація рядків, кортежів, списків, словників без зміни вихідних
Розглянемо способи об'єднання рядків, кортежів, списків, словників без зміни вихідних колекцій — коли з кількох колекцій створюється нова колекція того ж тип без зміни початкових.

  1. Конкатенація рядків (string) і кортежів (tuple) можлива з використанням оператор додавання «+»
    str1 = 'abc'
    str2 = 'de'
    str3 = str1 + str2
    print(str3) # abcde
    
    tuple1 = (1, 2, 3)
    tuple2 = (4, 5)
    tuple3 = tuple1 + tuple2
    print(tuple3) # (1, 2, 3, 4, 5)
    

  2. конкатенації списків (list) можливі два варіанти без зміни вихідного списку:
    • Додаємо всі елементи другого списку до елементів першого, (аналог метод .extend() але без зміни вихідного списку ):
      a = [1, 2, 3]
      b = [4, 5]
      c = a + b 
      print(a, b, c) # [1, 2, 3] [4, 5] [1, 2, 3, 4, 5]
      

    • Додаємо другий список як один елемент без зміни вихідного списку (аналог методу.append() але без зміни вихідного списку):
      a = [1, 2, 3]
      b = [4, 5]
      c = a + [b]
      print(a, b, c) # [1, 2, 3] [4, 5] [1, 2, 3, [4, 5]]
      
  3. словником (dict) все не зовсім просто.

    Скласти два словника щоб отримати третій оператором + Пітон не дозволяє «TypeError: unsupported operand type(s) for +: 'dict' and 'dict'».

    Це можна зробити по-іншому комбінуючи методи .copy() і .update():
    dict1 = {'a': 1, 'b': 2}
    dict2 = {'c': 3, 'd': 4}
    dict3 = dict1.copy()
    dict3.update(dict2)
    print(dict3) # {'a': 1, 'c': 3, 'b': 2, 'd': 4}
    

    У Пітоні 3.5 з'явився новий більш витончений спосіб:
    dict1 = {'a': 1, 'b': 2}
    dict2 = {'c': 3, 'd': 4}
    dict3 = {**dict1, **dict2}
    print(dict3) # {'a': 1, 'c': 3, 'b': 2, 'd': 4}
    
2. Конкатенація множин без зміни вихідних
Для обох типів множин (set, frozenset) можливі різні варіанти комбінації множин (вихідні множини при цьому не змінюються — повертається нове безліч)
image
# Задамо початково дві множини (скопіювати перед кожним прикладом нижче)
a = set(['a', 'b'])
b = set([ 'b', 'c']) # відступ перед b для наочності

  1. Об'єднання (union):
    c = a.union(b) # c = b.union(a) дасть такий же результат 
    # c = a + b # Звичайна конкатенація оператором + не працює
    # TypeError: unsupported operand type(s) for +: 'set' and 'set'
    print© # {'a', 'c', 'b'}
    

  2. Перетин (intersection):
    c = a.intersection(b) # c = b.intersection(a) дасть такий же результат
    print© # {'b'}
    Перетин більше 2-х множин відразу:
    a = set(['a', 'b'])
    b = set([ 'b', 'c'])
    c = set([ 'b', 'd'])
    d = a.intersection(b, c) # Перший варіант запису
    d = set.intersection(a, b, c) # Другий варіант запису (скорочений)
    print(d) # {'b'}
    

  3. Різниця (difference) — результат залежить від того, яке кількість з якого віднімаємо:
    c = a.difference(b) # c = a - b інший спосіб запису дає той же результат
    print© # {'a'}
    c = b.difference(a) # c = b - a інший спосіб запису дає той же результат
    print© # {'c'}
    

  4. Симетрична різниця (symmetric_difference) Це свого роду протилежна операція перетину — вибирає елементи з обох множин, які не перетинаються, тобто всі крім співпадаючих:
    c = b.symmetric_difference(a) 
    # c = a.symmetric_difference(b) # дасть такий же результат
    print© # {'a', 'c'}
    

3 Конкатенація списку, словника і змінюваного безлічі зі зміною вихідної колекції
  1. список
    • Додаємо всі елементи другого списку до елементів першого з измением першого списку методом .extend():
      a.extend(b) 
      print(a, b) # [1, 2, 3, 4, 5] [4, 5]
      

    • Додаємо другий список як один елемент із зміною першого списку методом .append():
      a.append(b)
      print(a, b) # [1, 2, 3, [4, 5]] [4, 5]
      

  2. Для зміни словники з додавання елементів іншого словника використовується метод .update().
    Зверніть увагу: для відповідних ключів словника при цьому оновлюються значення:
    dict1 = {'a': 1, 'b': 2}
    dict2 = {'a': 100, 'c': 3, 'd': 4}
    dict1.update(dict2)
    print(dict1) # {'a': 100, 'c': 3, 'b': 2, 'd': 4}
    

  3. змінюваного безлічі (set), крім операцій, описаних в попередньому розділі, також можливі їх аналоги, але вже зі зміною вихідного безлічі — ці методи закінчуються на _update. Результат залежить від того, яке безліч яким оновлюємо.

    • .difference_update()
      a = set(['a', 'b'])
      b = set([ 'b', 'c'])
      a.difference_update(b)
      print(a, b) # {'a'} {'b', 'c'}
      a = set(['a', 'b'])
      b = set([ 'b', 'c'])
      b.difference_update(a)
      print(a, b) # {'a', 'b'} {'c'}
      

    • .intersection_update()
      a = set(['a', 'b'])
      b = set([ 'b', 'c'])
      a.intersection_update(b)
      print(a, b) # {'b'} {'b', 'c'}
      
      a = set(['a', 'b'])
      b = set([ 'b', 'c'])
      b.intersection_update(a)
      print(a, b) # {'b', 'a'} {'b'}
      

    • .symmetric_difference_update()
      a = set(['a', 'b'])
      b = set([ 'b', 'c'])
      a.symmetric_difference_update(b) 
      print(a, b) # {'c', 'a'} {'c', 'b'}
      
      a = set(['a', 'b'])
      b = set([ 'b', 'c'])
      b.symmetric_difference_update(a)
      print(a, b) # {'a', 'b'} {'c', 'a'}
      
    4 Додавання і видалення елементів змінюваних колекцій
    Додавання і видалення елементів колекцію можливо тільки для змінюваних колекцій: списку (list), безлічі (тільки set, не frozenset), словника (dict). Причому для списку, який є індексованою колекцією, також важливо на яку позицію ми додаємо елемент.
    image

    ПРИМІТКИ:
    • Приклади використання методу .insert(index, element)
      my_list = [1, 2, 3]
      my_list.insert(0, 0) # index = 0 - вставляємо в початок
      print(my_list) # [0, 1, 2, 3]
      
      my_list.insert(10, 4) # Індекс виходить за межі списку - просто додамо в кінець
      print(my_list) # [0, 1, 2, 3, 4]
      
      my_list.insert(-10, -1) # Індекс виходить за кордону в мінус - додамо в початок
      print(my_list) # [-1, 0, 1, 2, 3, 4]
      
      my_list = [1, 2, 3]
      my_list.insert(1, 1.5) # Вставимо між 1 і 2 (індексація з нуля!)
      # Тобто вставляється на позицію з вказаним індексом, а те значення що на ній було 
      # і ті що правіше - зсуваються на 1 індекс вправо
      print(my_list) # [1, 1.5, 2, 3]
      
    • Приклади використання оператора del
      # Працює зі списком
      my_list = [1, 2, 3, 4, 5, 6, 7]
      del my_list[1] # Видалення елемента з індексом
      print(my_list) # [1, 3, 4, 5, 6, 7]
      del my_list[-3:-1] # Видалення елементів обраних зрізом
      print(my_list) # [1, 3, 4, 7]
      # del my_list[10] # IndexError: list assignment index out of range
      
      # Працює зі словником
      my_dict = {'a': 1, 'b': 2, 'c': 3}
      del my_dict['b']
      print(my_dict) # {'a': 1, 'c': 3}
      # del my_dict [z'] # KeyError при спробі видалити не сушествующий
      
    • додавання та Видалення елементів списку зрізом розглядається у другій статті.
    • Приклад роботи .append ().extend() розглядається третій главі цієї статті.
    5 Особливості роботи із змінною і не змінною колекцією
    1. Рядок незмінна колекція — якщо ми її змінюємо — ми створюємо новий об'єкт!
      str1 = 'abc'
      print(str1, id(str1)) # abc 140234080454000
      str1 += 'de'
      print(str1, id(str1)) # abcde 140234079974992 - Це НОВИЙ об'єкт, з іншим id!
      

      Приклад коду з двома початково ідентичними рядками.
      str1 = 'abc'
      str2 = str1
      print(str1 is str2) # True - це два посилання на один і той самий об'єкт!
      str1 += 'de' # Тепер мінлива str1 посилається на інший об'єкт!
      print(str1 is str2) # False - тепер це два різних об'єкта!
      print(str1, str2) # abcde abc - різні значення
      

    2. Список змінюємо і тут треба бути дуже уважним, щоб не допустити серйозну помилку! Порівняйте даний приклад з прикладом з рядками вище:
      list1 = [1, 2, 3]
      list2 = list1
      print(list1 is list2) # True - це два посилання на один і той самий об'єкт!
      # А далі переконуємося, наскільки це важливо:
      list1 += [4]
      print(list1, list2) # [1, 2, 3, 4] [1, 2, 3, 4] 
      # змінилося значення ОБОХ змінних, так як обидві змінні посилаються на один об'єкт!
      

      А якщо потрібна незалежна копія, з якою можна працювати окремо?
      list1 = [1, 2, 3]
      list2 = list(list1) # Перший спосіб копіювання
      list3 = list1[:] # Другий спосіб копіювання
      list4 = list1.copy() # Третій спосіб копировани - тільки в Python 3.3+
      print(id(list1), id(list2), id(list3), id(list4)) 
      # 4 id різні, що означає, що ми створили 4 різних об'єкта
      
      list1 += [4] # міняємо вихідний список
      print(list1, list2, list3, list4) # [1, 2, 3, 4] [1, 2, 3] [1, 2, 3] [1, 2, 3] 
      # як ми і хотіли - змінивши початковий об'єкт, його копії залишилися незачепленими
      


    У наступних статтях планується продовження:

    • (скоро) Тонкощі генерації колекцій.
    • (можливо в майбутньому) Модуль collections.

    Запрошую до обговорення:

    • Якщо я десь допустив неточність або не врахував щось важливе — пишіть в коментарях, важливі коментарі будуть пізніше додано статтю з зазначенням вашого авторства.
    • Якщо якісь моменти не зрозумілі і потрібне уточнення — пишіть ваші запитання в коментарях — або я або інші читачі дадуть відповідь, а слушні запитання з відповідями будуть пізніше додано статтю.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.