
Хочете навчитися програмувати на Python з нуля? У цій статті ми детально розглянемо створення базових скриптів та керування ходом програми — ключові навички для новачків. Ви дізнаєтеся, як зробити файл виконуваним, як передавати аргументи в скрипт через argv
, та як організувати введення інформації від користувача.
Якщо говорити в цілому, то скрипт – це звичайний файл. У цьому файлі зберігається послідовність команд, які необхідно виконати. Почнемо із базового скрипту. Виведемо на стандартний потік виведення кілька рядків.
Для цього потрібно створити файл access_template.py з таким вмістом:
access_template = ['switchport mode access', 'switchport access vlan {}', 'switchport nonegotiate', 'spanning-tree portfast', 'spanning-tree bpduguard enable'] print('\n'.join(access_template).format(5))
Спочатку елементи списку об’єднуються в рядок, який розділений символом \n
, а в рядок є номер VLAN, використовуючи форматування рядків. Після цього потрібно зберегти файл і перейти до командного рядка.
Так виглядає виконання скрипту:
$ python access_template.py switchport mode access switchport access vlan 5 switchport nonegotiate spanning-tree portfast spanning-tree bpduguard enable
Ставити розширення .py
у файлу необов’язково, але, якщо ви використовуєте Windows, це бажано робити, оскільки Windows використовує розширення файлу визначення того, як обробляти файл.
В курсі всі скрипти, які створюватимуться, використовують розширення .py. Можна сказати, що це гарний тон – створювати скрипти Python з таким розширенням.
Для того, щоб файл був виконуваним, і не потрібно було щоразу писати python перед викликом файлу, потрібно:
зробити файл виконуваним (для Linux)
у першому рядку файлу має бути рядок або, залежно від того, яка версія Python використовується за умовчанням
#!/usr/bin/env python
#!/usr/bin/env python3
Приклад файлу access_template_exec.py:
#!/usr/bin/env python3 access_template = ['switchport mode access', 'switchport access vlan {}', 'switchport nonegotiate', 'spanning-tree portfast', 'spanning-tree bpduguard enable'] print('\n'.join(access_template).format(5))
Після цього:
chmod +x access_template_exec.py
Тепер можна викликати файл таким чином:
$ ./access_template_exec.py
Дуже часто скрипт вирішує якусь загальну задачу. Наприклад, скрипт обробляє якось файл конфігурації. Набагато краще буде передавати ім’я файлу як аргумент скрипту, а потім використовувати вже вказаний файл. Модуль sys дозволяє працювати з аргументами скрипта за допомогою argv.
Приклад access_template_argv.py:
from sys import argv interface = argv[1] vlan = argv[2] access_template = ['switchport mode access', 'switchport access vlan {}', 'switchport nonegotiate', 'spanning-tree portfast', 'spanning-tree bpduguard enable'] print('interface {}'.format(interface)) print('\n'.join(access_template).format(vlan))
Перевірка роботи скрипту:
$ python access_template_argv.py Gi0/7 4 interface Gi0/7 switchport mode access switchport access vlan 4 switchport nonegotiate spanning-tree portfast spanning-tree bpduguard enable
Аргументи, які були передані скрипту, підставляються як значення шаблону.
Тут треба пояснити кілька моментів:
argv – це список
всі аргументи знаходяться у списку у вигляді рядків
argv містить не лише аргументи, які передали скрипту, але й назву самого скрипту
У цьому випадку у списку argv знаходяться такі елементи:
['access_template_argv.py', 'Gi0/7', '4']
Спочатку йде ім’я самого скрипта, потім аргументи в тому ж порядку.
Іноді потрібно отримати інформацію від користувача, наприклад, запросити пароль.
Для отримання інформації від користувача використовується функція input
:
In [1]: print(input('Твой любимый протокол маршрутизации? ')) Твій улюблений протокол маршрутизації? OSPF OSPF
В даному випадку інформація відразу виводиться користувачеві, але крім цього інформація, яку ввів користувач, може бути збережена в якусь змінну і може використовуватися далі в скрипті.
In [2]: protocol = input('Твій улюблений протокол маршрутизації? ') Твій улюблений протокол маршрутизації? OSPF In [3]: print(protocol) OSPF
У дужках зазвичай пишеться якесь питання, яке уточнює, яку інформацію потрібно запровадити.
Запит інформації зі скрипту (файл access_template_input.py):
interface = input('Enter interface type and number: ') vlan = input('Enter VLAN number: ') access_template = ['switchport mode access', 'switchport access vlan {}', 'switchport nonegotiate', 'spanning-tree portfast', 'spanning-tree bpduguard enable'] print('\n' + '-' * 30) print('interface {}'.format(interface)) print('\n'.join(access_template).format(vlan))
У перших двох рядках запитується інформація користувача. Рядок використовується для того, щоб візуально відокремити запит інформації від виводу.print('\n' + '-' * 30)
Виконання скрипту:
$ python access_template_input.py Enter interface type and number: Gi0/3 Enter VLAN number: 55 ------------------------------ interface Gi0/3 switchport mode access switchport access vlan 55 switchport nonegotiate spanning-tree portfast spanning-tree bpduguard enable
Досі весь код виконувався послідовно – усі рядки скрипту виконувались в тому порядку, в якому вони записані у файлі. У цьому розділі розглядаються можливості Python в керуванні ходом програми:
відгалуження в ході програми за допомогою конструкції
if/elif/else
повторення дій у циклі за допомогою конструкцій
for
таwhile
обробка помилок за допомогою конструкції
try/except
Конструкція if/elif/else
дозволяє робити відгалуження під час програми. Програма йде у гілку під час виконання певної умови.
У цій конструкції тільки if є обов’язковим, elif та else опціональні:
Перевірка if завжди йде першою.
Після оператора if має бути якась умова: якщо ця умова виконується (повертає True), то дії в блоці if виконуються.
За допомогою elif можна зробити кілька розгалужень, тобто перевіряти вхідні дані на різні умови.
Блок elif це той же if, але тільки наступна перевірка. Грубо кажучи, це «а якщо…»
Блоків elif може бути багато.
Блок else виконується у тому випадку, якщо жодна з умов if або elif не була істинною.
Приклад конструкції:
In [1]: a = 9 In [2]: if a == 10: ...: print('a равно 10') ...: elif a < 10: ...: print('a меньше 10') ...: else: ...: print('a больше 10') ...: a менше 10
Конструкція if побудована на умовах: після if та elif завжди пишеться умова. Блоки if/elif виконуються лише коли умова повертає True, тому перше з чим треба розібратися – це що є істинним, а що є хибним у Python.
У Python, крім очевидних значень True і False, решті всіх об’єктів також відповідає помилкове або справжнє значення.
Справжнє значення:
будь-яке ненульове число
будь-який непустий рядок
будь-який непустий об’єкт
Хибне значення:
0
None
порожній рядок
порожній об’єкт
Наприклад, так як порожній список це помилкове значення, перевірити, чи порожній список, можна так:
In [12]: list_to_test = [1, 2, 3] In [13]: if list_to_test: ....: print("В списке есть объекты") ....: В списку є об'єкти
Той самий результат можна було б отримати трохи інакше:
In [14]: if len(list_to_test) != 0: ....: print("В списке есть объекты") ....: В списку є об'єкти
Оператори порівняння , які можуть використовуватися в умовах:
In [3]: 5 > 6 Out[3]: False In [4]: 5 > 2 Out[4]: True In [5]: 5 < 2 Out[5]: False In [6]: 5 == 2 Out[6]: False In [7]: 5 == 5 Out[7]: True In [8]: 5 >= 5 Out[8]: True In [9]: 5 <= 10 Out[9]: True In [10]: 8 != 10 Out[10]: True
Зверніть увагу, що рівність перевіряється подвійним
==
.
Приклад використання операторів порівняння:
In [1]: a = 9 In [2]: if a == 10: ...: print('a равно 10') ...: elif a < 10: ...: print('a меньше 10') ...: else: ...: print('a больше 10') ...: а менше 10
Оператор in
дозволяє виконувати перевірку на наявність елемента у послідовності (наприклад, елемента у списку або підрядки у рядку):
In [8]: 'Fast' in 'FastEthernet' Out[8]: True In [9]: 'Gigabit' in 'FastEthernet' Out[9]: False In [10]: vlan = [10, 20, 30, 40] In [11]: 10 in vlan Out[11]: True In [12]: 50 in vlan Out[12]: False
При використанні словників умова in виконує перевірку за ключами словника:
In [15]: r1 = { ....: 'IOS': '15.4', ....: 'IP': '10.255.0.1', ....: 'hostname': 'london_r1', ....: 'location': '21 New Globe Walk', ....: 'model': '4451', ....: 'vendor': 'Cisco'} In [16]: 'IOS' in r1 Out[16]: True In [17]: '4451' in r1 Out[17]: False
В умовах можуть також використовуватися логічні оператори and
, or
, not
:
In [15]: r1 = { ....: 'IOS': '15.4', ....: 'IP': '10.255.0.1', ....: 'hostname': 'london_r1', ....: 'location': '21 New Globe Walk', ....: 'model': '4451', ....: 'vendor': 'Cisco'} In [18]: vlan = [10, 20, 30, 40] In [19]: 'IOS' in r1 and 10 in vlan Out[19]: True In [20]: '4451' in r1 and 10 in vlan Out[20]: False In [21]: '4451' in r1 or 10 in vlan Out[21]: True In [22]: not '4451' in r1 Out[22]: True In [23]: '4451' not in r1 Out[23]: True
У Python оператор and
повертає не булеве значення, а значення одного з операндів.
Якщо обидва операнди є істиною, результатом виразу буде останнє значення:
In [24]: 'string1' and 'string2' Out[24]: 'string2' In [25]: 'string1' and 'string2' and 'string3' Out[25]: 'string3'
Якщо один із операторів є брехнею, результатом виразу буде перше хибне значення:
In [26]: '' and 'string1' Out[26]: '' In [27]: '' and [] and 'string1' Out[27]: ''
Оператор or
, як і оператор and, повертає значення одного з операндів.
Оцінюючи операндів повертається перший справжній операнд:
In [28]: '' or 'string1' Out[28]: 'string1' In [29]: '' or [] or 'string1' Out[29]: 'string1' In [30]: 'string1' or 'string2' Out[30]: 'string1'
Якщо всі значення є помилковими, повертається останнє значення:
In [31]: '' or [] or {} Out[31]: {}
Важлива особливість роботи оператора or
– операнди, які перебувають після істинного, не обчислюються:
In [33]: '' or sorted([44, 1, 67]) Out[33]: [1, 44, 67] In [34]: '' or 'string1' or sorted([44, 1, 67]) Out[34]: 'string1'
Приклад скрипта check_password.py, який перевіряє довжину пароля та чи є в паролі ім’я користувача:
# -*- coding: utf-8 -*- username = input('Введіть ім'я користувача: ') password = input('Введіть пароль: ') if len(password) < 8: print('Пароль занадто короткий') elif username in password: print('Пароль містить ім'я користувача') else: print('Встановлено пароль для користувача {}'.format(ім'я користувача))
Перевірка скрипту:
$ python check_password.py Введіть ім’я користувача: nata Введіть пароль: nata1234 Пароль містить ім’я користувача $ python check_password.py Введіть ім’я користувача: nata Введіть пароль: 123nata123 Пароль містить ім’я користувача $ python check_password.py Введіть ім’я користувача: nata Введіть пароль: 1234 Надто короткий пароль $ python check_password.py Введіть ім’я користувача: nata Введіть пароль: 123456789 Пароль для користувача nata встановлений
Іноді зручніше використовувати тернарний оператор, ніж розгорнуту форму:
s = [1, 2, 3, 4] result = True if len(s) > 5 else False
Цим краще не зловживати, але в простих виразах такий запис може бути корисним.
Дуже часто одну й ту саму дію треба виконати для набору однотипних даних. Наприклад, перетворити всі рядки у списку у верхній регістр. Для виконання таких дій у Python використовується цикл for
.
Цикл for перебирає по одному елементи зазначеної послідовності та виконує дії, які вказані в блоці for для кожного елемента.
Приклади послідовностей елементів, якими може проходити цикл for:
рядок
список
словник
Функція range
будь-який об’єкт, що ітерується
Приклад перетворення рядків у списку у верхній регістр без циклу for:
In [1]: words = ['list', 'dict', 'tuple'] In [2]: upper_words = [] In [3]: words[0] Out[3]: 'list' In [4]: words[0].upper() # перетворення слова у верхній реєстр Out[4]: 'LIST' In [5]: upper_words.append(words[0].upper()) # перетворення та додавання в новий список In [6]: upper_words Out[6]: ['LIST'] In [7]: upper_words.append(words[1].upper()) In [8]: upper_words.append(words[2].upper()) In [9]: upper_words Out[9]: ['LIST', 'DICT', 'TUPLE']
Дане рішення має кілька нюансів:
одну і ту ж дію треба повторювати кілька разів
код прив’язаний до певної кількості елементів у списку words
Ті ж дії з циклом for:
In [10]: words = ['list', 'dict', 'tuple'] In [11]: upper_words = [] In [12]: for word in words: ...: upper_words.append(word.upper()) ...: In [13]: upper_words Out[13]: ['LIST', 'DICT', 'TUPLE']
Вираз означає «для кожного слова у списку words виконати дії у блоці for». При цьому слово це ім’я змінної, яке кожну ітерацію циклу посилається на різні значення.for word in words: upper_words.append(word.upper()).
Цикл for може працювати з будь-якою послідовністю елементів. Наприклад, вище використовувався список та цикл перебирав елементи списку. Аналогічним чином для роботи з кортежами.
При роботі з рядками цикл for перебирає символи рядка, наприклад:
In [1]: for letter in 'Test string': ...: print(letter) ...: T e s t s t r i n g
У циклі використовується змінна з іменем letter . Хоча ім’я може бути будь-яким, зручно, коли ім’я підказує, через які об’єкти проходить цикл.
Іноді у циклі необхідно використовувати послідовність чисел. У цьому випадку, найкраще використовувати функцію range
Приклад циклу for з функцією range():
In [2]: for i in range(10): ...: print(f'interface FastEthernet0/{i}') ...: interface FastEthernet0/0 interface FastEthernet0/1 interface FastEthernet0/2 interface FastEthernet0/3 interface FastEthernet0/4 interface FastEthernet0/5 interface FastEthernet0/6 interface FastEthernet0/7 interface FastEthernet0/8 interface FastEthernet0/9
У цьому циклі використовується range(10)
. Функція range генерує числа в діапазоні від нуля до вказаного числа (у даному прикладі – до 10), не включаючи його.
У цьому прикладі цикл проходить за списком VLAN, тому змінну можна назвати vlan:
In [3]: vlans = [10, 20, 30, 40, 100] In [4]: for vlan in vlans: ...: print(f'vlan {vlan}') ...: print(f' name VLAN_{vlan}') ...: vlan 10 name VLAN_10 vlan 20 name VLAN_20 vlan 30 name VLAN_30 vlan 40 name VLAN_40 vlan 100 name VLAN_100
Коли цикл йде за словником, то фактично він проходить за ключами:
In [34]: r1 = { ...: 'ios': '15.4', ...: 'ip': '10.255.0.1', ...: 'hostname': 'london_r1', ...: 'location': '21 New Globe Walk', ...: 'model': '4451', ...: 'vendor': 'Cisco'} ...: In [35]: for k in r1: ...: print(k) ...: ios ip hostname location model vendor
Якщо потрібно виводити пари ключ-значення в циклі, можна робити так:
In [36]: for key in r1: ...: print(key + ' => ' + r1[key]) ...: ios => 15.4 ip => 10.255.0.1 hostname => london_r1 location => 21 New Globe Walk model => 4451 vendor => Cisco
In [36]: for key in r1: ...: print(key + ' => ' + r1[key]) ...: ios => 15.4 ip => 10.255.0.1 hostname => london_r1 location => 21 New Globe Walk model => 4451 vendor => Cisco
Або скористатися методом items, який дозволяє проходити в циклі відразу по парі ключ-значення:
In [37]: for key, value in r1.items(): ...: print(key + ' => ' + value) ...: ios => 15.4 ip => 10.255.0.1 hostname => london_r1 location => 21 New Globe Walk model => 4451 vendor => Cisco
Метод items повертає спеціальний об’єкт view, який відображає пари ключ-значення:
In [38]: r1.items() Out[38]: dict_items([('ios', '15.4'), ('ip', '10.255.0.1'), ('hostname', 'london_r1'), ('location', '21 New Globe Walk'), ('model', '4451'), ('vendor', 'Cisco')])
Цикли for можна вкладати один одного.
У цьому прикладі у списку commands зберігаються команди, які потрібно виконати для кожного з інтерфейсів у списку fast_int:
In [7]: commands = ['switchport mode access', 'spanning-tree portfast', 'spanning-tree bpduguard enable'] In [8]: fast_int = ['0/1','0/3','0/4','0/7','0/9','0/10','0/11'] In [9]: for intf in fast_int: ...: print('interface FastEthernet {}'.format(intf)) ...: for command in commands: ...: print(' {}'.format(command)) ...: interface FastEthernet 0/1 switchport mode access spanning-tree portfast spanning-tree bpduguard enable interface FastEthernet 0/3 switchport mode access spanning-tree portfast spanning-tree bpduguard enable interface FastEthernet 0/4 switchport mode access spanning-tree portfast spanning-tree bpduguard enable ...
Перший цикл for проходить за інтерфейсами у списку fast_int, а другий за командами у списку commands.
Розглянемо приклад суміщення for та if.
Файл generate_access_port_config.py:
1 access_template = ['switchport mode access', 2 'switchport access vlan', 3 'spanning-tree portfast', 4 'spanning-tree bpduguard enable'] 5 6 access = {'0/12': 10, '0/14': 11, '0/16': 17, '0/17': 150} 7 8 for intf, vlan in access.items(): 9 print('interface FastEthernet' + intf) 10 for command in access_template: 11 if command.endswith('access vlan'): 12 print(' {} {}'.format(command, vlan)) 13 else: 14 print(' {}'.format(command))
Коментарі до коду:
У першому циклі for перебираються ключі та значення у вкладеному словнику access
Поточний ключ, на даний момент циклу, зберігається в змінній intf
Поточне значення, на даний момент циклу, зберігається в змінній vlan
Виводиться рядок interface FastEthernet з додаванням до нього номера інтерфейсу
У другому циклі for перебираються команди зі списку access_template
Оскільки до команди switchport access vlan треба додати номер VLAN:
всередині другого циклу for перевіряються команди
якщо команда закінчується на access vlan
виводиться команда, і до неї додається номер VLAN
У всіх інших випадках просто виводиться команда.
Результат виконання скрипту:
$ python generate_access_port_config.py interface FastEthernet0/12 switchport mode access switchport access vlan 10 spanning-tree portfast spanning-tree bpduguard enable interface FastEthernet0/14 switchport mode access switchport access vlan 11 spanning-tree portfast spanning-tree bpduguard enable interface FastEthernet0/16 switchport mode access switchport access vlan 17 spanning-tree portfast spanning-tree bpduguard enable interface FastEthernet0/17 switchport mode access switchport access vlan 150 spanning-tree portfast spanning-tree bpduguard enable
Цикл while – це ще один різновид циклу в Python.
У циклі while, як і у вираженні if, треба писати умову. Якщо умова істинна, виконуються дії всередині блоку while. При використанні циклів while необхідно звертати увагу на те, чи буде досягнуто такий стан, за якого умова циклу буде хибною.
Розглянемо простий приклад:
In [1]: a = 5 In [2]: while a > 0: ...: print(a) ...: a -= 1 # Эта запись равнозначна a = a - 1 ...: 5 4 3 2 1
Спочатку створюється змінна зі значенням 5.
Потім, у циклі while зазначено умову a > 0. Тобто, поки значення а більше 0, виконуватимуться дії у тілі циклу. В даному випадку буде виводитися значення змінної а.
Крім того, в тілі циклу при кожному проходженні значення а стає на одиницю менше.
Запис може бути трохи незвичайним. Python дозволяє використовувати такий формат замість .
a -= 1
a = a - 1
Аналогічним чином можна писати: , , .
a += 1
a *= 2
a /= 2
Так як значення а зменшується, цикл не буде нескінченним, і в якийсь момент вираз a> 0 стане хибним.
Наступний приклад побудований на основі прикладу про пароль з розділу про конструкцію if. За допомогою циклу while можна зробити так, що скрипт сам запитуватиме пароль заново, якщо він не відповідає вимогам.
Файл check_password_with_while.py:
# -*- coding: utf-8 -*- username = input('Введіть ім'я користувача: ') password = input('Введіть пароль: ') password_correct = False while not password_correct: if len(password) < 8: print('Пароль занадто короткий\n') password = input('Введіть пароль ще раз: ') elif username in password: print('Пароль містить ім'я користувача\n') password = input('Введіть пароль ще раз: ') else: print(f'Пароль для користувача {username} установлен') password_correct = True
У цьому випадку цикл while корисний, тому що він повертає скрипт знову на початок перевірок, дозволяє знову набрати пароль, але при цьому не вимагає перезапуску самого скрипта.
Тепер скрипт відпрацьовує так:
$ python check_password_with_while.py Введіть ім'я користувача: nata Введіть пароль: nata Пароль занадто короткий Введіть пароль ще раз: natanata Пароль містить ім'я користувача Введіть пароль ще раз: 123345345345 Пароль для користувача nata встановлений
Python має кілька операторів, які дозволяють змінювати поведінку циклів за замовчуванням.
Оператор break
дозволяє достроково перервати цикл:
break перериває поточний цикл і продовжує виконання наступних виразів
якщо використовується кілька вкладених циклів, break перериває внутрішній цикл і продовжує виконувати вирази, що йдуть за блоком * break може використовуватися в циклах for і while
Приклад із циклом for:
In [1]: for num in range(10): ...: if num < 7: ...: print(num) ...: else: ...: break ...: 0 1 2 3 4 5 6
Приклад із циклом while:
In [2]: i = 0 In [3]: while i < 10: ...: if i == 5: ...: break ...: else: ...: print(i) ...: i += 1 ...: 0 1 2 3 4
Використання break у прикладі із запитом пароля (файл check_password_with_while_break.py):
username = input('Введіть ім'я користувача: ') password = input('Введіть пароль: ') while True: if len(password) < 8: print('Пароль занадто короткий\n') elif username in password: print('Пароль містить ім'я користувача\n') else: print('Пароль для користувача{} установлен'.format(ім'я користувача)) # завершает цикл while break password = input('Введіть пароль ще раз: ')
Тепер можна не повторювати рядок у кожному відгалуженні, достатньо перенести його в кінець циклу.password = input('Введите пароль еще раз: ')
І як тільки буде введено правильний пароль, break виведе програму з циклу while.
Оператор continue повертає керування на початок циклу. Тобто, continue дозволяє «перестрибнути» вирази в циклі, що залишилися, і перейти до наступної ітерації.
Приклад із циклом for:
In [4]: for num in range(5): ...: if num == 3: ...: continue ...: else: ...: print(num) ...: 0 1 2 4
Приклад із циклом while:
In [5]: i = 0 In [6]: while i < 6: ....: i += 1 ....: if i == 3: ....: print("Пропускаем 3") ....: continue ....: print("Это никто не увидит") ....: else: ....: print("Текущее значение: ", i) ....: Текущее значение: 1 Текущее значение: 2 Пропускаем 3 Текущее значение: 4 Текущее значение: 5 Текущее значение: 6
Використання continue у прикладі із запитом пароля (файл check_password_with_while_continue.py):
username = input('Введите имя пользователя: ') password = input('Введите пароль: ') password_correct = False while not password_correct: if len(password) < 8: print('Пароль слишком короткий\n') elif username in password: print('Пароль содержит имя пользователя\n') else: print('Пароль для пользователя {} установлен'.format(username)) password_correct = True continue password = input('Введите пароль еще раз: ')
Тут вихід із циклу виконуються за допомогою перевірки прапора password_correct. Коли було введено правильний пароль, прапор виставляється рівним True, і з допомогою continue виконується перехід початку циклу, перескочивши останній рядок із запитом пароля.
Результат виконання буде таким:
$ python check_password_with_while_continue.py Введите имя пользователя: nata Введите пароль: nata12 Пароль слишком короткий Введите пароль еще раз: natalksdjflsdjf Пароль содержит имя пользователя Введите пароль еще раз: asdfsujljhdflaskjdfh Пароль для пользователя nata установлен
Оператор pass
нічого не робить. Фактично це така заглушка для об’єктів.
Наприклад, pass
може допомогти ситуації, коли потрібно прописати структуру скрипта. Його можна ставити у циклах, функціях, класах. І це не впливатиме на виконання коду.
Приклад використання pass:
In [6]: for num in range(5): ....: if num < 3: ....: pass ....: else: ....: print(num) ....: 3 4
У циклах for і while опціонально можна використовувати блок else.
У циклі for:
блок else виконується у разі, якщо цикл завершив ітерацію списку
але else не виконується , якщо в циклі був виконаний break
Приклад циклу for з else (блок else виконується після завершення циклу for):
In [1]: for num in range(5): ....: print(num) ....: else: ....: print("Числа закончились") ....: 0 1 2 3 4 Числа закончились
Приклад циклу for з else і break в циклі (через break блок else не виконується):
In [2]: for num in range(5): ....: if num == 3: ....: break ....: else: ....: print(num) ....: else: ....: print("Числа закончились") ....: 0 1 2
Приклад циклу for з else та continue у циклі (continue не впливає на блок else):
In [3]: for num in range(5): ....: if num == 3: ....: continue ....: else: ....: print(num) ....: else: ....: print("Числа закончились") ....: 0 1 2 4 Числа закончились
У циклі while:
блок else виконується в тому випадку, якщо умова в while хибно
else не виконується , якщо в циклі був виконаний break
Приклад циклу while з else (блок else виконується після завершення циклу while):
In [4]: i = 0 In [5]: while i < 5: ....: print(i) ....: i += 1 ....: else: ....: print("Конец") ....: 0 1 2 3 4 Конец
Приклад циклу while з else та break у циклі (через break блок else не виконується):
In [6]: i = 0 In [7]: while i < 5: ....: if i == 3: ....: break ....: else: ....: print(i) ....: i += 1 ....: else: ....: print("Конец") ....: 0 1 2
Якщо ви повторювали приклади, які використовувалися раніше, то, напевно, були ситуації, коли вискакувала помилка. Швидше за все, це була помилка синтаксису, коли не вистачало, наприклад, двокрапки.
Як правило, Python досить зрозуміло реагує на такі помилки, і їх можна виправити.
Проте, навіть якщо код синтаксично написаний правильно, можуть бути помилки. У Python ці помилки називаються виняток (exceptions) .
Приклади винятків:
In [1]: 2/0 ----------------------------------------------------- ZeroDivisionError: division by zero In [2]: 'test' + 2 ----------------------------------------------------- TypeError: must be str, not int
У цьому випадку виникли два винятки: ZeroDivisionError та TypeError .
Найчастіше можна передбачити, які винятки виникнуть під час виконання програми.
Наприклад, якщо програма на вхід очікує два числа, а на виході видає їх суму, а користувач ввів замість одного з чисел рядок, з’явиться помилка TypeError, як у прикладі вище.
Python дозволяє працювати з винятками. Їх можна перехоплювати та виконувати певні дії у тому випадку, якщо виник виняток.
Коли у програмі виникає виняток, вона одразу завершує роботу.
Для роботи з винятками використовується конструкція try/except
:
In [3]: try: ...: 2/0 ...: except ZeroDivisionError: ...: print("You can't divide by zero") ...: You can't divide by zero
Конструкція try працює таким чином:
спочатку виконуються вирази, які записані в блоці try
якщо під час виконання блоку try не виникло жодних винятків, блок except пропускається, і виконується подальший код
якщо під час виконання блоку try в якомусь місці виник виняток, частина блоку try, що залишилася, пропускається якщо в блоці except зазначено виняток, який виник, виконується код у блоці except. Якщо виняток, який виник, не вказано в блоці except, виконання програми переривається та видається помилка.
Зауважте, що рядок Cool!
у блоці try не виводиться:
In [4]: try: ...: print("Let's divide some numbers") ...: 2/0 ...: print('Cool!') ...: except ZeroDivisionError: ...: print("You can't divide by zero") ...: Let's divide some numbers You can't divide by zero
У конструкції try/except може бути багато except, якщо потрібні різні дії, залежно від типу помилки.
Наприклад, скрипт divide.py ділить два числа введених користувачем:
# -*- coding: utf-8 -*- try: a = input("Введите первое число: ") b = input("Введите второе число: ") print("Результат: ", int(a)/int(b)) except ValueError: print("Пожалуйста, вводите только числа") except ZeroDivisionError: print("На ноль делить нельзя")
Приклади виконання скрипту:
$ python divide.py Введите первое число: 3 Введите второе число: 1 Результат: 3 $ python divide.py Введите первое число: 5 Введите второе число: 0 На ноль делить нельзя $ python divide.py Введите первое число: qewr Введите второе число: 3 Пожалуйста, вводите только числа
У цьому випадку виняток ValueError виникає, коли користувач ввів рядок замість числа під час переведення рядка в число. Виняток ZeroDivisionError виникає у разі, якщо друге число дорівнювало 0.
Якщо немає потреби виводити різні повідомлення на помилки ValueError та ZeroDivisionError, можна зробити так (файл divide_ver2.py):
# -*- coding: utf-8 -*- try: a = input("Введите первое число: ") b = input("Введите второе число: ") print("Результат: ", int(a)/int(b)) except (ValueError, ZeroDivisionError): print("Что-то пошло не так...")
Перевірте:
$ python divide_ver2.py Введите первое число: wer Введите второе число: 4 Что-то пошло не так... $ python divide_ver2.py Введите первое число: 5 Введите второе число: 0 Что-то пошло не так...
У блоці except можна не вказувати конкретний виняток або виняток. У такому разі перехоплюватимуться всі винятки.
Це робити не рекомендується!
Блок finally – це ще один опціональний блок у конструкції try. Він виконується завжди незалежно від того, чи був виняток чи ні. Сюди ставляться дії, які потрібно виконати у будь-якому випадку. Наприклад, це може бути закриття файлу.
Файл divide_ver4.py із блоком finally:
# -*- coding: utf-8 -*- try: a = input("Введите первое число: ") b = input("Введите второе число: ") result = int(a)/int(b) except (ValueError, ZeroDivisionError): print("Что-то пошло не так...") else: print("Результат в квадрате: ", result**2) finally: print("Вот и сказочке конец, а кто слушал - молодец.")
# -*- coding: utf-8 -*- try: a = input("Введите первое число: ") b = input("Введите второе число: ") result = int(a)/int(b) except (ValueError, ZeroDivisionError): print("Что-то пошло не так...") else: print("Результат в квадрате: ", result**2) finally: print("Вот и сказочке конец, а кто слушал - молодец.")
Перевірте:
$ python divide_ver4.py Введите первое число: 10 Введите второе число: 2 Результат в квадрате: 25 Вот и сказочке конец, а кто слушал - молодец. $ python divide_ver4.py Введите первое число: qwerewr Введите второе число: 3 Что-то пошло не так... Вот и сказочке конец, а кто слушал - молодец. $ python divide_ver4.py Введите первое число: 4 Введите второе число: 0 Что-то пошло не так... Вот и сказочке конец, а кто слушал - молодец.
Як правило, той самий код можна написати і з використанням винятків, і без них.
Наприклад, цей варіант коду:
while True: a = input("Введите число: ") b = input("Введите второе число: ") try: result = int(a)/int(b) except ValueError: print("Поддерживаются только числа") except ZeroDivisionError: print("На ноль делить нельзя") else: print(result) break
Можна переписати таким чином без try/except (файл try_except_divide.py):
while True: a = input("Введите число: ") b = input("Введите второе число: ") if a.isdigit() and b.isdigit(): if int(b) == 0: print("На ноль делить нельзя") else: print(int(a)/int(b)) break else: print("Поддерживаются только числа")
Не завжди аналогічний варіант без використання винятків буде простим і зрозумілим.
Важливо в кожній конкретній ситуації оцінювати, який варіант коду зрозуміліший, компактніший і універсальніший – з винятками або без.
Якщо ви раніше використовували якусь іншу мову програмування, є ймовірність, що використання винятків вважалося поганим тоном. У Python це не так. Щоб трохи розібратися з цим питанням, перегляньте посилання на додаткові матеріали в кінці цього розділу.
Іноді в коді треба згенерувати виняток, це можна зробити так:
raise ValueError("При выполнении команды возникла ошибка")
У Python є багато вбудованих винятків, кожне з яких генерується у певній ситуації.
Наприклад, TypeError зазвичай генерується, коли очікувався один тип даних, а передали інший:
In [1]: "a" + 3 --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-1-5aa8a24e3e06> in <module> ----> 1 "a" + 3 TypeError: can only concatenate str (not "int") to str
ValueError коли значення не відповідає очікуваному:
In [2]: int("a") --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-2-d9136db7b558> in <module> ----> 1 int("a") ValueError: invalid literal for int() with base 10: 'a'
У цій статті ми пройшли важливий етап — освоїли базові інструменти створення скриптів у Python і навчилися контролювати хід виконання програм. Ви дізналися, як запускати скрипти, передавати аргументи, взаємодіяти з користувачем, а також керувати логікою за допомогою умов, циклів, логічних операторів і обробки винятків.
Ці знання — фундамент будь-якої Python-програми. Від простого запиту пароля до складних конструкцій з вкладеними циклами та обробкою помилок — усе це дозволяє писати чистий, безпечний і керований код. Найголовніше — не боятися експериментувати. Пишіть, запускайте, помиляйтесь і вчіться. Python заохочує простоту і читаємість — скористайтесь цим на повну.