Єдина Країна!

Головне меню

Наша кнопка

Українські уроки про ІТ

Друзі

Підтримка української армії


Головна Програмування - Python Структури даних в Python

Структури даних в Python
Написав Invader   
Понеділок, 04 березня 2013 17:16
Переглядів: 17128

Python ua:Структури даних

 

Вступне слово

Структури даних це просто структури, які можуть тримати певні дані разом. Іншими словами, вони використовуються для зберігання колекції (набору) пов’язаних даних.

В Python існує 4 вбудовані типи для структур даних — список (list), кортеж (tuple), словник (dictionary) і набір (set).

Розглянемо їх далі..

 

Список (list) в Python

Список — це структура даних яка містить впорядкований набір елементів, тобто ти можеш зберігати послідовнісь елементів у списку. Це легко собі уявити, якщо думати про це як про список покупок, який містить речі, які потрібно купити. Список має розміщуватися всередині квадратних дужок. Елементи списку розділяються комою. Список — змінний тип даних. Ти можеш додавати, видаляти і редагувати елементи списку.

Коротке введення в об’єкти і класи

Тут ми трохи поговоримо про такі штуки як об’єкти і класи.

Список — це приклад використання об’єктів і класів. Коли ти використовуєш змінну i присвоюєш їй значення, скажімо 5, то ти можеш думати про це в категоріях об’єктно-орієнтованого програмування — ти створюєш об’єкт (екземпляр) з іменем i класу (типу) int. Насправді ти можеш прочитати help(int) для того щоб зрозуміти це краще.

Клас також може мати методи — функції визначені для використання тільки по відношенню до цього класу. Ти можеш використовувати ці функції тільки тоді, коли в тебе є об’єкт відповідного класу. Наприклад, Python має спеціальний метод append для класу, який дозволяє додавати елемент в кінець списку. Наприклад, myList.append('an item') додасть елемент рядкового типу до списку myList. Зверни увагу на використання крапкової нотації для доступу до методів об’єктів.

Клас також може містити поля. Поля — це не що інше як змінні визначені для використання тільки зі своїм класом. Та ж історія що і з методами — ці змінні/імена можна використовувати тільки тоді, коли є об’єкт відповідного класу. Для доступу до полів використовується крапкова нотація, наприклад, myList.field

Приклад:

 
#!/usr/bin/python
# Filename: using_list.py
# Це мій список покупок
shoplist = ['apple', 'mango', 'carrot', 'banana']

print('I have', len(shoplist), 'items to purchase.')

print('These items are:', end=' ')
for item in shoplist:
	print(item, end=' ')

print('\nI also have to buy rice.')
shoplist.append('rice')
print('My shopping list is now', shoplist)

print('I will sort my list now')
shoplist.sort()
print('Sorted shopping list is', shoplist)

print('The first item I will buy is', shoplist[0])
olditem = shoplist[0]
del shoplist[0]
print('I bought the', olditem)
print('My shopping list is now', shoplist)  

Виведе:

$ python using_list.py
I have 4 items to purchase.
These items are: apple mango carrot banana
I also have to buy rice.
My shopping list is now ['apple', 'mango', 'carrot', 'banana', 'rice']
I will sort my list now
Sorted shopping list is ['apple', 'banana', 'carrot', 'mango', 'rice']
The first item I will buy is apple
I bought the apple
My shopping list is now ['banana', 'carrot', 'mango', 'rice']

 

Як це працює:

Змінна shoplist це список покупок для того хто збирається на ринок. У shoplist ми зберігаємо назви того, що треба купити. Ти можеш додати об’єкт будь-якого типу до списку, включаючи числа і навіть, інші списки.

Ми також використали цикл for…in для ітерації по елементам списку. На даний момент тобі треба зрозуміти, що списки це також і послідовність. Про специфіку послідовностей ми поговоримо згодом.

Зверни увагу на використання іменованого аргументу end в функції print. Його тут було використано для того, щоб вказати на те що замість традиційного символу нового рядка нам потрібен символ пробілу в кінці виводу.

Далі, ми додали елемент в кінець списку скориставшись методом append об’єкту типу "список". Тоді, ми перевірили чи елемент насправді було додано до списку вивівши його вміст на екран функцією print.

Далі, список був відсортований методом sort. Важливо розуміти що список було відсортовано на місці, тобто даний метод змінює сам список переданий йому. Він не повертає новий відсортований список. Це відрізняється від того як працють рядки. Ось що ми мали на увазі, коли казали, що списки можна змінювати, а рядки ні.

Коли ми вже купили щось зі списку, то нам потрібно це щось видалити з нього. Ми досягли цього використанням інструкції del. Оскільки потрібно видалити перший елемент списку, то ми пишемо del shoplist[0].

Якщо хочеш дізнатися про всі методи об’єкту "список", то тоді зверніться до help(list).

 

Кортеж (tuple) в Python

Головна відміннсть між кортежем і списком полягає в тому, що кортеж є незмінним. Не можна змінити к-ть елементів кортежу, чи , наприклад, певний елемент кортежу. Крім того, для оголошення кортежу потрібно використовувати такі дужки — () замість []. Елементи кортежу відокремлюються комами.

Кортеж зазвичай використовується у тих випадках, коли інструкція чи визначена користувачем функція, може безпечно припустити, що елементи кортежу не зміняться.

Приклад:

#!/usr/bin/python
# Filename: using_tuple.py
zoo = ('python', 'elephant', 'penguin') # дужки необов’язкові
print('Number of animals in the zoo is', len(zoo))

new_zoo = ('monkey', 'camel', zoo)
print('Number of cages in the new zoo is', len(new_zoo))
print('All animals in new zoo are', new_zoo)
print('Animals brought from old zoo are', new_zoo[2])
print('Last animal brought from old zoo is', new_zoo[2][2])
print('Number of animals in the new zoo is', len(new_zoo)-1+len(new_zoo[2]))

Виведе:

$ python using_tuple.py
Number of animals in the zoo is 3
Number of cages in the new zoo is 3
All animals in new zoo are ('monkey', 'camel', ('python', 'elephant', 'penguin'))
Animals brought from old zoo are ('python', 'elephant', 'penguin')
Last animal brought from old zoo is penguin
Number of animals in the new zoo is 5

Як це працює:

Змінна zoo посилається на кортеж. Функція len може бути використана і з кортежем.

Тепер ми переміщаємо цих тварин в новий зоопарк (змінна new_zoo) оскільки старий зоопарк закрився. Таким чином кортеж new_zoo містить тих тварин які були там з моменту створення і тварин зі старого зоопарку. Назад в реальність, зверни увагу на те що кортеж всередині іншого кортежу залишається кортежем.

Доступ до елементів кортежу можна отримати вказуючи позицію (індекс) елементу всередині квадратних дужок. Це називається індексним оператором. Доступ до третього елементу new_zoo ми отримали за допомогою такої конструкції: new_zoo[2]. А для того щоб вказати третій елемент всередині третього елементу кортежу new_zoo new_zoo[2][2]. Така конструкція стане доволі простою як тільки ти зрозумієш ідіому (Ідіома — стійкий неподільний зворот мови, що передає єдине поняття, зміст якого не визначається змістом його складових елементів).

Дужки

Не зважаючи на те що дужки є необов'язковими я завжди їх використовую для того, щоб явно вказати на те що це є кортеж. Наприклад, print(1,2,3) і print( (1,2,3) ) означають дві різні речі — перша інструкція виводить на екран три різних числа, друга виводить кортеж (який містить три числа).

Кортеж без елементів або з 1 елементом

Порожній кортеж можна створити просто вказавши пару порожніх дужок: empty = (). Проте кортеж з одним елементом не такий простий. Для того щоб створити такий кортеж треба вказати кому, яка слідує за першим (і єдиним) його елементом для того щоб Python міг відрізнити кортеж від об’єкту оточеного дужками який використовується в якомусь виразі. Кортеж з одним елементом: singleton = (2 ,).

Зауваження для Perl програмістів

Список всередині іншого списку не втрачає своєї ідентичності, тобто його не буде "розпаковано" і його елементи не стануть елементами списку в якому він знаходиться (список не "розчиниться" всередині іншого списку). Те ж можна сказати і по відношенню до кортежу всередині кортежа, кортежу всередині списку, списку всередині кортежу etc. Що стосується Python, то вони просто об’єкти, які містять інші об’єкти, це все.

 

Словники в Python

Словник це ніби адресна книга де ти можеш знайти адресу або контактні дані певної особи знаючи тільки її/його ім’я. Іншими словами ми асоцюємо ключі (імена) із значеннями(контактними даними). Зауваж, що ключ має бути унікальним інакше ти не зможеш знайти потрібну інформацію, якщо у тебе є дві особи з абсолютно однаковими іменами.

Зауваж, що в якості ключів для словника можуть виступати тільки незмінні об’єкти (такі як рядки). Але це правило не стосується значень словника.

Пари ключ-значення вказуються в словнику використовуючи наступну нотацію: словник = {ключ1 : значення1, ключ2 : значення2}. Пари ключ-значення розділені двокрапкою, а самі пари розділяються комами.

Запам’ятай, що пари ключ-значення жодним чином не впорядковані. Якщо потрібно, щоб вони йшли в певному порядку, то доведеться самостійно їх відсортувати перед використанням.

Словники, які ти будеш використовувати є екземплярами/об’єктами класу dict.

Приклад:

#!/usr/bin/python
# Filename: using_dict.py
# 'ab' скорочення від адресної книги
ab = {  'Swaroop':'swaroops.com',
	'Larry':'larry-wall.org',
	'Matsumoto':'matz-ruby-lang.org',
	'Spammer':'spammer.com'
	}
	
print("Swaroop's address is", ab['Swaroop'])

# Видалення пари ключ-значення
del ab['Spammer']

print('\nThere are {0} contacts in the address-book\n'.format(len(ab)))

for name, address in ab.items():
	print('Contact {0} at {1}'.format(name, address))
	
# Додавання нової пари
ab['Guido'] = 'guido-python.org'

#Додаємо до словника нову пару ключ-значення
if 'Guido' in ab: # Або ab.has_key('Guido')
	print("\nGuido's address is", ab['Guido'])

Виведе:

$ python using_dict.py
Swaroop's address is swaroops.com
There are 3 contacts in the address-book
Contact Swaroop at swaroops.com
Contact Matsumoto at matz-ruby-lang.org
Contact Larry at larry-wall.org
Guido's address is guido-python.org

 

Як це працює:

Ми створили словник ab використовуючи відповідний синтаксис. Потім ми отримали доступ до пар ключ-значення використавши індексний оператор

Ми можемо видаляти пари ключ-значення використовуючи нашого старого друга — інструкцію del. Для цього лише потрібно вказати потрібний ключ потрібного словника.

Далі, ми скориставшись методом items словника (даний метод повертає список кортежів в якому кожен кортеж складається з пари елементів — ключа і значення), отримали доступ до кожної пари ключ-значення. Ми отримали цю пару і привласнили її значення відповідним змінним name і address використовуючи цикл for…in. І потім вивели на екран ці значення всередині циклу for.

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

Для перевірки того чи існує потрібна нам пара ключ-значення можна скористатися оператором in або методом has_key класу dict. Ти можеш переглянути документацію, для того щоб дізнатися повний список методів, виконавши команду help(dict).

Іменовані аргументи і словники

Якщо ти вже використовував іменовані аргументи у власних функціях, то ти вже використовував словники! Просто подумай про це — пара ключ-значення вказана тобою в списку аргументів визначення функції; і коли ти отримуєш доступ до змінних всередині функції, це просто доступ по ключу до словника (який називається символьною таблицею в термінології  компілятора).

 

Послідовності в Python

Списки, кортежі і рядки є прикладами послідовностей, але що таке послідовності і що в них особливого?

Серед головних можливостей наявність тестів на входження (вирази in і not in) і операції індексування. Операція індексування дозволяє отримати певний елемент в послідовності напряму.

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

Приклад:

#!/usr/bin/python
# Filename: seq.py
 
shoplist = ['apple', 'mango', 'carrot', 'banana']
name = 'swaroop'
 
# Операція індексування
print('Еелемент 0 це', shoplist[0])
print('Еелемент 1 це', shoplist[1])
print('Еелемент 2 це', shoplist[2])
print('Еелемент 3 це', shoplist[3])
print('Еелемент -1 це', shoplist[-1])
print('Еелемент -2 це', shoplist[-2])
print('Символ 0 це', name[0])

# Зріз списку
print('Еелементи з 1 по 3 це', shoplist[1:3])
print('Еелементи з 2 до кінця це', shoplist[2:])
print('Еелементи з 1 по -1 це', shoplist[1:-1])
print('Еелементи з початку до кінця це', shoplist[:])
 
# Зріз рядка
print('Символи з 1 по 3 це', name[1:3])
print('Символи з 2 до кінця це', name[2:])
print('Символи з 1 по -1 це', name[1:-1])
print('Символи з початку до кінця це', name[:])

Виведе:

$ python seq.py
Еелемент 0 це apple
Еелемент 1 це mango
Еелемент 2 це carrot
Еелемент 3 це banana
Еелемент -1 це banana
Еелемент -2 це carrot
Символ 0 це s
Еелементи з 1 по 3 це ['mango', 'carrot']
Еелементи з 2 до кінця це ['carrot', 'banana']
Еелементи з 1 по -1 це ['mango', 'carrot']
Еелементи з початку до кінця це ['apple', 'mango', 'carrot', 'banana']
Символи з 1 по 3 це wa
Символи з 2 до кінця це aroop
Символи з 1 по -1 це waroo
Символи з початку до кінця це swaroop

Як це працює:

Спершу ми побачили, як використовувати індекси для того щоб дістатися до окремих елементів послідовності. Щоразу коли ти вказуєш число для послідовності всередині квадратних дужок, як в програмі вище, Python поверне елемент який відповідає вказаній тобою позиції всередині послідовності. Запам’ятай, що Python починає рахувати з 0. Тому shoplist[0] виведе 1-й елемент а shoplist[3] виведе 4-й.

Індексом також може бути негативне число. У цьому випадку позиція вираховується з кінця послідовності. Отже, shoplist[-1] посилається на останній елемент послідовнсті а shoplist[-2] вибирає другий елемент з кінця (передостанній).

Операція зрізу використовується вказуючи ім’я послідовності за якою слідують необов’язкові два числа розділені двокрапкою всередині квадратних дужок. Зауваж, що це дуже схоже на операцію індексування. Запам’ятай, що числа опціональні, але двокрапка ні.

Перше число (перед двокрапкою) в операції зрізу позначає позицію початку зрізу, а друге число вказує на кінець зрізу. Якщо початок зрізу не вказувати явно, то Python почне з 1-го елементу послідовності. Якщо пропущено друге число після двокрапки, то Python закінчить операцію зрізу на останньому елементі. Зверни увагу на те що нижня межа зрізу буде починатися саме з 1-го вказаного числа (число перед двокрапкою), але верхня межа, закінчиться якраз перед другим вказаним індексом послідовнсті. Іншими словами, стартова позиція включається у зріз, але остання позиція виключається зі зрізу.

Таким чином, shoplist[1:3] поверне зріз послідовності починаючи з позиції 1, включаючи позицію 2, але зупиниться на позиції 3, і тому, повернеться зріз з 2 елементів. Схожим чином, shoplist[:] поверне копію всієї послідовності.

Існує можливість робити зрізи використовуючи від’ємні числа. Числа зі знаком мінус викорстовуються для позицій з кінця послідовності. Наприклад, shoplist[:-1] поверне зріз послідовності в якому немає останнього елемента послідовнсті, але присутні всі інші елементи.

Також можна вказати третій параметр для послідовності, який буде вказувати на крок для зрізування (типово, крок дорівнює 1):

>>> shoplist = ['apple', 'mango', 'carrot',' banana']
>>> shoplist[::1]
['apple', 'mango', 'carrot', 'banana']
>>> shoplist[::2]
['apple', 'carrot']
>>> shoplist[::3]
['apple', 'banana']
>>> shoplist[::-1]
['banana', 'carrot', 'mango', 'apple']

Зауваж, що коли крок дорівнює 2, то ми отримуємо елементи з позицією 0, 2,… Коли ж крок дорівнює трьом, то елементи з позицією 0, 3, etc.

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

 

Набір(множина) в Python

Набори(множини) — це невпорядковані колекції простих об’єктів. Вони використовуються, тоді коли існування об’єктів в колекції є більш важливим ніж порядок їхнього розташування, чи те скільки разів вони зустрічаються.

Використовуючи набори ти маєш можливість перевіряти приналежність (членство) тих чи інших об’єктів до множини, визначати те чи знаходиться один набір всередині іншого, знаходити перетин між двома наборами, і т.д.

>>> bri = set(['brazil', 'russia', 'india'])
>>> 'india' in bri
True
>>> 'usa' in bri
False
>>> bric = bri.copy()
>>> bric.add('china')
>>> bric.issuperset(bri)
True
>>> bri.remove('russia')
>>> bri & bric #Або bri.intersection(bric)
{'brazil', 'india'}

Як це працює:

Вищенаведений приклад зрозумілий без пояснень, тому що в ньому використовується базова теорія множин з курсу математики, вивчена в школі.

 

Посилання в Python

Коли ти створюєш об’єкт і присвоюєш його якійсь змінній, змінна всього лише посилається на об’єкт, але не представляє власне сам об’єкт! Саме так, ім’я змінної вказує на ту частину пам’яті твого комп’ютера, де зберігається об’єкт. Це називається прив’язуванням імені до об’єкта.

Загалом, тобі не треба про це турбуватися, але існує один тонкий момент пов’язаний з посиланнями, про який слід пам’ятати:

Приклад:

#!/usr/bin/python
# Filename: reference.py

print('Simple assignment')
shoplist = ['apple', 'mango', 'carrot', 'banana']
mylist = shoplist # mylist — це просто інше ім’я яке вказує на об’єкт shoplist!

del shoplist[0] # Я придбав перший елемент у списку, тому видаляю його

print('shoplist is', shoplist)
print('mylist is', mylist)
# Зауваж, що shoplist і mylist містять один і той самий список
# без 'apple', таким чином підтверджуючи те, що вони вказують на один об’єкт

print('Copy by making a full slice')
mylist = shoplist[:] # копіювання шляхом повного зрізу

del mylist[0] # видалити 1-й елемент

print('shoplist is', shoplist)
print('mylist is', mylist)
# зверни увагу на те що тепер, два списки різні

Виведе:

$ python reference.py
Simple Assignment
shoplist is ['mango', 'carrot', 'banana']
mylist is ['mango', 'carrot', 'banana']
Copy by making a full slice
shoplist is ['mango', 'carrot', 'banana']
mylist is ['carrot', 'banana']

Як це працює:

Більша частина пояснення винесена в коментарі.

Запам’ятай, що якщо ти хочеш зробити копію списку чи чогось подібного, чи складних об’єктів (саме складних, а не таких простих  як цілі числа (які теж об’єкти)), то тоді ти можеш використати оператор зрізу. Якщо ти просто присвоїв ім’я змінної іншій змінній, то вони будуть просто посилатися на один і той же об’єкт, що може спричинити проблеми якщо ти не будеш обережним.

Зауваження для програмістів на Perl

Запам’ятай, що оператор присвоєння для списків не створює копію. Потрібно використовувати оператор зрізу для копіювання послідовностей.

Більше про рядки

Ми вже раніше детально говорили про рядки. Що ще про них можна дізнатися? Ну, ти знав, що рядки також є об’єктами, і вони також мають свої методи, які роблять все, від перевірки частини рядка і до усунення пробілів!

Рядки, які ти використовуєш в програмі є об’єктами класу str. Деякі корисні методи даного класу демонструються в наступному прикладі. Для повного списку подібних методів дивись help(str).

Приклад:

#!/usr/bin/python
# Filename: str_methods.py

name = 'Swaroop' # це об’єкт типу str

if name.startswith('Swa'):
	print('Yes, the string starts with "Swa"')
	
if 'a' in name:
	print('Yes, it contains the string "a"')
	
if name.find('war') != -1:
	print('Yes, it contains the string "war"')
	
delimiter = '_*_'
mylist = ['Brazil', 'Russia', 'India', 'China']
print(delimiter.join(mylist))  

Виведе:

$ python str_methods.py
Yes, the string starts with "Swa"
Yes, it contains the string "a"
Yes, it contains the string "war"
Brazil_*_Russia_*_India_*_China

Як це працює:

В цьому прикладі ми побачили багато методів рядкового типу. Метод startwith використовується для з’ясування того чи починається рядок із вказаного набору символів. Оператор in використаний для перевірки того чи вказаний рядок є частиною іншого рядка.

Метод find використаний для знаходження позиції вказаного рядка всередині іншого рядка. Він поверне -1 якщо нічого не знайдено. Клас str також має лаконічний метод для об’єднання елементів послідовності з рядком (метод join), який виступає в ролі розмежовувача між елементами послідовності; і який поверне в програму більший рядок, згенерований з вказаного.

 

Підсумок

Ми детально розглянули різноманітні вбудовані структури даних Python. Ці структури даних матимуть велике значення при написанні програм.

Тепер, коли ми вже маємо багато уявлення про базові речі в Python, ми далі побачимо як спроектувати і написати реальну Python`івську програму.

 

Автор перекладу - Дмитро Юрченко.


( 10 Проголосувало )
Коментарі
Добавити новий
Oleg  - Більше про рядки - метод "startwith"   |2015-02-09 03:24:56
Правильніше буде "startswith"
Адміністратор   |2015-02-15 00:43:13
avatar Дякую, поправив
Залишити коментар
Ім`я:
e-mail:
 
Тема:
 
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch:
:(:shock::X:side::):P:unsure::woohoo::huh::whistle:;):s
:!::?::idea::arrow:
 
Введіть цей настирливий код
Русская редакция: www.freedom-ru.net & www.joobb.ru

3.26 Copyright (C) 2008 Compojoom.com / Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved."

 

Підписка

Хто онлайн?

Немає
На даний момент 35 гостей на сайті

Український рейтинг
TOP.TOPUA.NET