__toc__

Типи даних. Давайте на хвилинку відкладемо в бік вашу першу програму, і поговоримо про типи даних. В Python кожне значення має тип, але ви не повинні оголошувати тип змінної. Як це працює? Покладаючись на початково присвоєне змінній значення, Python визначає якому типу воно належить і запам’ятовує його самостійно.

Python має багато вбудованих типів даних. Ось деякі найважливіші:

Логічні (Булеві) змінні приймають значеня True або False. Числа можуть бути цілими (1 і 2), з десятковими дробами (1.1 і 1.2), звичайними дробами (1/2 and 2/3), чи навіть комплексними. Рядки є послідовностями символів Юнікоду (наприклад HTML документ) Байти та масиви байтів (наприклад зображення в форматі JPEG) Списки є впорядкованими послідовностями значень. Кортежі є впорядкованими незмінними послідовностями значень. Множини є невпорядкованими наборами значень. Словники є невпорядкованими наборами пар ключ-значення.

Звичайно існує ще багато типів крім вищеперелічених. В Python все - об’єкт, тому є такі типи як модуль, функція, клас, метод, файл і навіть відкомпільований код. Ви вже зустрічались з деякими з них: модулі мали імена, функції мали докстрінґи. Ви дізнаєтесь про класи в розділі Класи та ітератори, і про файли в розділі Файли.

Рядки і байти достатньо важливі і достатньо складні щоб присвятити їм окремий розділ. Давайте спершу розглянемо інші.

Булевий тип

Булеві змінні приймають лише істинне чи хибне значення. Python має для цих значень дві відповідні константи: True та False, які можна використовувати для присвоєння значень змінним. Окрім констант, булеві значення можуть приймати вирази. А в деяких місцях (наприклад, в операторі if) Python навіть очікує того, що значення виразу можна буде привести до булевого типу. Такі місця називаються булевими контекстами. Ви можете використати майже будь-який вираз в булевому контексті, і Python намагатиметься визначити його істинність. Різні типи даних мають різні правила щодо того, які значення є істинними, а які - хибними в булевому контексті. (Сенс останніх речень стане зрозумілішим, коли ви побачите деякі приклади далі в цьому розділі.)

Візьмімо для прикладу цей шматочок коду з humansize.py:

if size < 0: raise ValueError('number must be non-negative')

size - ціле число, 0 теж ціле, а < - оператор над числами. Результат виразу size < 0 завжди булевий. Ви можете переконатись в цьому самостійно в інтерактивній оболонці Python:

>>> size = 1 >>> size < 0 False >>> size = 0 >>> size < 0 False >>> size = -1 >>> size < 0 True

Від Python 2 була успадкована цікава особливість: за потреби вважати булеві значення числами. True це 1, а False - 0:

>>> True + True 2 >>> True - False 1 >>> True * False 0 >>> True / False Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: int division or modulo by zero

Ей, ей, ей! Ніколи не робіть так. Забудьте навіть, що я вам про таке розповідав. Серйозно.

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

>>> type(1) <class 'int'>

Функцію type() можна використовувати, щоб визначати тип значення змінної. Як можна було очікувати, 1 - ціле (int).

>>> isinstance(1, int) True

Для перевірки приналежності типу можна використовувати функцію isinstance().

>>> 1 + 1 2

Додавання двох цілих дає нам цілий результат.

>>> 1 + 1.0 2.0 >>> type(2.0) <class 'float'>

Результатом додавання цілого та дробового числа є дробове. Для виконання додавання Python приводить ціле число до типу float і повертає результат цього ж типу.

Перетворення цілих в дробові та навпаки Щойно ви бачили, що деякі оператори (такі, як додавання) за потреби перетворюють цілі числа в дробові. Ви можете зробити це саме самостійно.

>>> float(2) 2.0 Можна явно перетворювати int у float, використовуючи функцію float()

>>> int(2.0) 2 Нічого дивного і в тому, що ви можете зробити навпаки за допомогою функції int

>>> int(2.5) 2 Функція int просто відкидає дробову частину, а не округлює.

>>> int(-2.5) -2 Функція int для від’ємних повертає найменше ціле число, більше або рівне даному (тобто теж просто відкидає дробову частину). Тому не плутайте її з функцією math.floor.

>>> 1.12345678901234567890 1.1234567890123457 Десяткові дроби мають точність до 15 знаків після коми.

>>> type(1000000000000000) <class 'int'> Цілі можуть бути як завгодно великими.

Основні числові операції З числами можна робити все:

>>> 11 / 2 5.5 Оператор / виконує ділення чисел з плаваючою крапкою. Він повертає float, навіть якщо чисельник та знаменник цілі.

>>> 11 // 2 5 Оператор // виконує хитрий вид цілочисельного ділення. Коли результат додатній, ви можете вважати його відкиданням (не округленням) дробової частини звичайного ділення, але будьте обережними з цим.

>>> −11 // 2 −6 При цілочисельному діленні від’ємних чисел оператор // округлює "вгору" до найближчого цілого. Хоча, говорячи формально, він округлує вниз, тому що -6 менше за -5.

>>> 11.0 // 2 5.0 Оператор // не завжди повертає цілі. Якщо чисельник чи знаменник дробові, // повертає float, яке, щоправда, все одно округлене до найближчого цілого.

>>> 11 ** 2 121 Оператор ** означає піднесення до степеня.

>>> 11 % 2 1 Оператор % повертає остачу від цілочисельного ділення.

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

>>> import fractions Щоб почати використовувати звичайні дроби, потрібно імпортувати модуль fractions.

>>> x = fractions.Fraction(1, 3) >>> x Fraction(1, 3) Щоб створити дріб, використовують об’єкт типу Fraсtion і передають його конструктору чисельник та знаменник.

>>> x * 2 Fraction(2, 3) З дробами можна виконувати звичайні математичні дії, результатом яких буде новий об’єкт Fraсtion.

>>> fractions.Fraction(6, 4) Fraction(3, 2) Об’єкт Fraсtion автоматично скорочує дроби.

>>> fractions.Fraction(0, 0) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "fractions.py", line 96, in __new__ raise ZeroDivisionError('Fraction(%s, 0)' % numerator) ZeroDivisionError: Fraction(0, 0) Python не дозволить створити дріб з нульовим знаменником.

Тригонометрія В Python також доступні тригонометричні функції.

>>> import math >>> math.pi 3.1415926535897931 Модуль math має константу для - відношення довжини кола до його діаметру.

>>> math.sin(math.pi / 2) 1.0 math містить всі базові тригонометричні функції: sin(), cos(), tan() і навіть такі, як asin().

>>> math.tan(math.pi / 4) 0.99999999999999989 Щоправда, варто зауважити, що Python не дає абсолютної точності. tan(π / 4) мусить повертати 1.0, а не 0.99999999999999989.

Числа в булевому контексті

Ви можете використовувати числа в булевому контексті, такому, як умова в операторі if. Нульові значення вважаються хибними, ненульові - істинними.

>>> def is_it_true(anything): ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... Ви знали, що можна описувати свої функції прямо в інтерактивній сесії Python? Просто натискайте Enter в кінці кожного рядка і додайте один порожній рядок в кінці функції.

>>> is_it_true(1) yes, it's true >>> is_it_true(-1) yes, it's true >>> is_it_true(0) no, it's false У булевому контексті всі цілі, окрім нуля, дорівнюють True, 0 - False.

>>> is_it_true(0.1) yes, it's true >>> is_it_true(0.0) no, it's false Ненульові десяткові дроби - True, 0.0 - False. Будьте обережними з цим! Найменша похибка округлення (цілком ймовірна річ, як ви могли побачити в попередньому розділі) - і Python буде перевіряти 0.0000000000001 замість 0.0 та отримає значення True.

>>> import fractions >>> is_it_true(fractions.Fraction(1, 2)) yes, it's true >>> is_it_true(fractions.Fraction(0, 1)) no, it's false Звичайні дроби теж можна використати в булевому контексті. Fraction(0, n) - хибне для будь-якого n. Усі інші дроби істинні.

Списки Списки - це робоча кобилка мови Python. Коли я кажу "список", ви можете подумати "масив, розмір якого я повинен задати наперед і який мусить містити елементи одного типу і т.д.". Не думайте так. Списки набагато крутіші за масиви.

Створення списку Створити список дуже просто - помістіть список значень, розділених комою, в квадратні дужки:

>>> a_list = ['a', 'b', 'mpilgrim', 'z', 'example'] >>> a_list ['a', 'b', 'mpilgrim', 'z', 'example'] Створюємо список з п’яти елементів. Їхній порядок зберігається, що не є випадковим, бо список - впорядкований набір елементів.

>>> a_list 'a' Нумерація елементів списку починається з нуля. Першим елементом непорожнього списку a_list є a_list.

>>> a_list 'example' Останнім елементом списку a_list з п’яти елементів є a_list. Тому що нумерація починається з нуля.

>>> a_list[-1] 'example' Від’ємні індекси в масиві задають відповідні по порядку елементи, якщо рахувати справа наліво. Останнім елементом непорожнього списку a_list завжди є a_list[-1].

>>> a_list[-3] 'mpilgrim' Якщо від’ємні індекси для вас трохи заплутані, думайте про них так: a_list[-n] == a_list[len(a_list) - n]. Тому в нашому випадку: a_list[-3] == a_list[5 - 3] == a_list.

Зрізання списків

Щойно створивши список, ви можете отримати будь-яку його частину як новий список. Ця частина називатиметься зрізом.

>>> a_list ['a', 'b', 'mpilgrim', 'z', 'example'] >>> a_list[1:3] ['b', 'mpilgrim'] Ви можете отримати зріз списку, задавши два індекси. Отримане значення - новий список, який містить всі елементи списку по порядку, починаючи від першого індексу (тут a_list) і аж до другого (тут a_list), але не включаючи його.

>>> a_list[1:-1] ['b', 'mpilgrim', 'z'] Зріз утворюється і тоді, коли один чи обидва з індексів від’ємні. Якщо це допоможе, можете думати так: ми читаємо список зліва направо. Першим індексом задається перший елемент з тих, які нам потрібні. Елемент, що задається другим індексом, - перший з тих, які нам не потрібні. Повертаються лише ті значення, які потрібні.

>>> a_list[0:3] ['a', 'b', 'mpilgrim'] Нумерація елементів в списку починається з нуля, тому a_list[0:3] поверне перші три елементи списку, починаючи з a_list аж до a_list невключно.

>>> a_list[:3] ['a', 'b', 'mpilgrim'] Якщо лівий індекс зрізу дорівнює нулю, його можна не вказувати. Тому a_list[:3] - це те саме, що й a_list[0:3].

>>> a_list[3:] ['z', 'example'] Аналогічно, якщо правий індекс - довжина списку, його теж можна не вказувати. Тому a_list[3:] - такий самий, як a_list[3:5], бо цей список має п’ять елементів. Тут є приємна симетрія. В даному п’ятиелементному списку a_list[:3] повертає перші три елементи, а a_list[3:] - останні два. Взагалі, a_list[:n] поверне перших n елементів, а a_list[n:] - решту, незалежно від довжини списку. (Якщо n - більше чи рівне довжини списку, всі елементи попадуть в перший зріз, а решта відповідно буде порожньою.)

>>> a_list[:] ['a', 'b', 'mpilgrim', 'z', 'example'] Якщо пропустити обидва індекси, всі елементи списку будуть включені до зрізу. Але це те саме, що й оригінальна змінна a_list. Це новий список, який містить ті самі елементи, що й оригінал. a_list[:] - скорочення для створення копії списку.

Додавання елементів до списку Існує чотири способи додавання елементів в список.

>>> a_list = ['a'] >>> a_list = a_list + [2.0, 3]

Оператор + конкатенує два списки, щоб утворити новий. Список може містити довільну кількість елементів (обмежень на розмір списку немає, окрім, звісно, об’єму доступної пам’яті). Проте ви мусите пам’ятати, що конкатенація списків створює додатковий список в пам’яті. В даному випадку він негайно присвоюється існуючій змінній a_list. Тому цей рядок коду насправді працює в два етапи: створення нового списку, і потім присвоєння. Якщо список довгий, то в проміжку між етапами програма може потребувати досить великі об’єми пам’яті.

>>> a_list ['a', 2.0, 3]