Кращий і найбільш швидкий спосіб навчитися програмувати - це почати, змінюючи деякі існуючі прості програми і поступово зрозуміти, як все це працює. Розглянемо код з використанням умовних операторів та циклів.
Вкладки і відступи
Програмісти мають певний стиль викладання свого коду, щоб зробити його простішим для розуміння. В C для Arduino, блоки коду всередині функції або оголошення if роблять з відступом, щоб ви могли побачити, які рядки коду належать даній команді або функції. В Python це не є питанням особистих забаганок, бо Python наполягає на цьому.
В Python, немає { або }, щоб показати початок і кінець блоку коду, ви повинні використовувати відступи, щоб показати, які рядки повинні бути разом. Так, наприклад, виглядає фрагмент коду для керування сигналами на виводах Raspberry Pi (RPi):
while True :
GPIO.output(control_pin, False)
time.sleep(5)
GPIO.output(control_pin, True)
time.sleep(2)
print("Finished")
Це цикл while (подібно до while в C для Arduino). У даному випадку умова True. Значення True завжди True, тому цикл триватиме вічно. В кінці першого рядка є двокрапка (:). Відступ вказує, що далі буде йти блок коду. Таким чином, відступ в Python є тим самим, що в C для Arduino, але немає маркера закриття.
Рядки всередині блоку повинні мати однаковий відступ з наведеним вище рядком. Поки ви послідовні, не має значення, скільки пробілів (чи символів табуляції) використали для відступу в коді. Більшість програмістів, як правило, використовують чотири пробіли для кожного рівня відступу, або один символ табуляції, але рекомендується користуватися чимось одним.
Оскільки код з відступом перетворюється в блок, то, відповідно, блоком називають один або кілька поруч розміщених рядків з однаковим відступом. Відступ організує код не лише візуально, але і логічно: блок - єдина конструктивна одиниця.
Замість маркера в кінці блоку ви просто перестаєте робити відступи коду. Таким чином, в попередньому прикладі остання команда print вже поза циклом. Оскільки цикл while триває вічно, то цей останній рядок насправді ніколи не отримає можливості для запуску.
Ще раз про змінні
Змінні в Python такі, як і в C для Arduino, але відрізняються тим, що коли ви вперше використовуєте змінну, вам не треба вказувати є це int чи float, або ще щось. Ви просто привласнюєте їй значення і немає нічого незвичного в тому , що ця змінна спочатку буде цілим числом, а потім, після переприсвоєння - рядком. Наприклад, наведений нижче код є абсолютно законним, але не дуже розумним:
a = 123.45
a = "message"
До речі, при призначенні рядкових змінних, ви можете використовувати як подвійні лапки (як в попередньому прикладі), так і одинарні.
Умовні конструкції з if
Python має структури if і else такі самі, як і в C для Arduino, але використовує двокрапку і відступи для позначення блоків коду всередині оголошення if:
if x > 10 :
print("x is big!")
else:
print("x is small")
Приклад програми:
# Пароль
# Демонструє використання конструкції if
print ('Ласкаво просимо до нас в "System Security Inc.". ')
print ('-- Security (Безпека) - наше друге ім’я\n')
password = input ("Введіть пароль: ")
if password == "secret":
print ("Дocтyп відкритий")
input ("\n\nHaтисни Enter, щоб вийти.")
Таблиця 3.1. Оператори порівняння
Можна порівнювати рядки: реэульта порівняння буде базуватися на алфавітному порядку. Так, наприклад, «апельсин» < «блоха» поверне True, тому що за алфавітом «апельсин» стоїть раніше «блоха» (ближче до початку словника).
Не можна порівнювати ціле число і рядок. Спробуйте перевірити умову 10 > «п’ять».
Умовні конструкції if та else
# Пароль
# Демонструє використання конструкції if
print ('Ласкаво просимо до нас в "System Security Inc.". ')
print ('-- Security (Безпека) - наше друге ім’я\n')
password = input ("Введіть пароль: ")
if password == "secret":
print ("Дocтyп відкритий")
else:
print ("Дocтyп закритий")
input ("\n\nHaтисни Enter, щоб вийти.")
Умова еlse повинна бути всередині того ж блоку, що і попередня конструкція з умовою if, тобто відступи для if і для еlse повинні бути однаковими. Візуально вони повинні бути на одному вертикальному рівні.
Як тільки в конструкції if з умовою elif чергова умова буде істинною, програма виконає відповідний блок коду і перейде до наступного виразу. Таким чином, якщо навіть істинні кілька умов, то виконується все рівно максимум один блок коду.
Не варто забувати про описані особливості в конструкціях, де одночасно може виконуватися кілька умов. Тоді підлягає виконанню перший в черзі блок з істинною умовою.
Таблиця 3.2. Оператори розгалуження – коротке резюме
Створення циклів з використанням while
# Симулятор здачі заліку
#Демонструє роботу циклу while
print ("\tЛаскаво просимо в програму 'Здача заліку в КПІ'\n")
print ("Імітується розмова викладача і студента.")
print ("Спробуйте зупинити цей кошмар здачі заліку.\n")
response = ""
while response != "Добре, прийду на перескладання":
response = input ("Поясніть, чому так?\n")
print ("ОК, добре підготуйся.")
input ("\n\nHaтисни Enter, щоб вийти.")
Контроль над циклом whilе здійснює змінна керування. Це змінна, яка фігурує в умові: її співставляють з деяким значенням або значеннями. Змінну керування треба ініціалізувати. Як правило, ініціалізація виконується безпосередньо перед початком циклу:
response = ""
В нашому випадку, змінну керування response прирівняли до пустого рядка "". Можна було б зробити початковим значенням response будь-яке слово і програма працювала б так само.
Переконайтеся, що умова циклу whilе спочатку хибна. В іншому випадку, тіло циклу ніколи не буде виконане.
Ще один приклад безкінечного циклу:
counter = 0
while counter <= 10
print (counter)
Запам’ятайте: виконання циклічного коду повинно змінювати (хоча б в деяких випадках) значення змінної керування. В іншому випадку ви отримаєте цикл без кінця.
Знову безкінечний цикл:
# Приклад логічної помилки в циклі
# Демонструє цикл без кінця, який так ненавидять програмісти
print ("Студент зайшов в магазин, щоб зробити покупки на всі свої гроші \n")
cash = 10
purchases = 0
purchase_price = 3
while cash != 0:
purchases += 1
cash -= purchase_price
print ("От він вже поклав в корзину один товар, " \
"але, витратив ", purchase_price, "гривень. \n")
print ("Наш студент зробив ", purchases, "покупок.")
print ("Нарешті! Всі гроші «викинуті».")
input ("\n\nHaтисни Enter, щоб вийти.")
Безкінечний цикл зупиняємо через натискання Ctr + C, а потім виконуємо ручне трасування та виправляємо помилку.
Значення як умова
# Метрдотель
# Демонструє умовну інтерпретацію значень
print ("Ласкаво просимо в Шато-де-Перекусити!")
print ("Здається, сьогодні ввечері у нас немає вільного столика.\n")
money = int(input("Cкільки гривень ви можете дати метрдотелю на чай? "))
if money:
print ("Вибачаюсь, мені зараз повідомили, що є один вільний столик. \
Сюди, будь ласка.")
else:
print ("Присядьте, будьте такі ласкаві. Доведеться почекати.")
input ("\n\nHaтисни Enter, щоб вийти.")
Використання команд break і continue
# Привередливий цикл
# Демонструє роботу команд break і continue
count = 0
while True:
count += 1
# завершити цикл, якщо count приймає значення більше 10
if count > 10 :
break
# пропустити 5
if count == 5:
continue
print (count)
input ("\n\nHaтисни Enter, щоб вийти.")
В прикладі цикл організований умовою:
while True:
Це значить, що цикл буде продовжуватися доти, поки команда в самому тілі циклу не завершить його при якій-небуть умові.
Цикл for
В циклах з оператором for також циклічне виконання коду, але не на базі умови. В фундаменті циклу for лежить послідовність - впорядкована множина об’єктів.
На відміну від традиційної моделі, в мові Python цикл for має більшу гнучкість, тому що дозволяє організувати перебирання будь-якої послідовності.
Цикл for перебирає всі елементи послідовності один за одним і для кожного з них виконує фрагмент коду, який знаходиться в тілі циклу. Після досягнення кінця послідовності цикл завершується.
# Літери із слова
# Демонструє застосування циклу for до рядка
word = input ("Введіть слово: ")
print("\nОт всі літери вашого слова одну за одною: ")
for letter in word :
print (letter)
input("\n\nHaтисни Enter, щоб вийти.")
Підрахунок за допомогою циклу for
# Підрахунок
# Демонструє використання функції range()
print("Порахуємо: ")
for i in range(10):
print (i, end=" ")
print("\n\nПерерахуємо кратні п’яти: ")
for i in range(0, 50, 5):
print (i, end=" ")
print("\n\nПoрахуємо в зворотному порядку: ")
for i in range(10, 0, -1):
print (i, end=" ")
input("\n\nHaтисни Enter, щоб вийти.\n")
Узагальнені змінні-лічильники для перебору чисел в циклах прийнято позначати i, j, k. Зазвичай імена змінних вибираються так, щоб із них була зрозуміла суть позначених даних. Тому будь-який досвідчений програміст, переглянувши ваш код, відразу зрозуміє, що змінна i, j або k - лічильник циклу.
Приклад. Щоб десять раз вивести на екран слово «Привіт!», досить написати два рядки коду:
for _ in range(10):
print ("Привіт! ")
Програма «Аналізатор тексту»
# Аналізатор тексту
# Демонструє роботу функції len() і оператора in
message = input("Введіть текст: ")
print("\nДовжина введеного вами тексту складає: ", len(message))
print("\nНайчастіша приголосна, ‘т’, ")
if "т" in message:
print ("зустрічається у вашому тексті.")
else :
print("нe зустрічається у вашому тексті.")
input("\n\nHaтисни Enter, щоб вийти.")
Оператор in можете застосовуватися всюди, де необхідно дізнатися, чи є членом послідовності який-небудь елемент. Достатньо написати ім’я змінної, яке має цей елемент, потім in та ім’я послідовності і отримаєте умову. Якщо елемент – член послідовності, то умова буде істинною, а якщо ні, то хибною.
За допомогою циклу for можна перебирати один за одним символи рядка. Це так званий послідовний доступ до елементів.
Програма «Випадкові букви»
# Випадкові букви
# Демонструє індексацію рядків
import random
word = "індекс"
print("У змінній word зберігається слово: ", word, "\n")
high = len(word)
low = -len(word)
for i in range(10):
position = random.randrange(low, high)
print ("word[", position, "]\t", word[position])
input("\n\nHaтисни Enter, щоб вийти.")
Отримати доступ до окремого символу рядка дуже легко. Букву, яка знаходиться в змінній word в позиції 0, позначають просто word[0]. Це правильно і для будь-якої іншої позиції: досить замінити 0 відповідним числом.
Програма «Лише приголосні»
# Лише приголосні
# Демонструє, як створювати нові рядки з первинних за допомогою циклу for
message = input("Введіть текст: ")
new_message = ''
VOWELS = "аеiouаеєиоуіюя"
print()
for letter in message:
if letter.lower() not in VOWELS:
new_message += letter
print("Створений новий рядок: ", new_message)
print("\nОт ваш текст без голосних букв: ", new_message)
input("\n\nHaтисни Enter, щоб вийти.")
Створення констант
Змінні з повністю прописних літер в іменах мають особливе значення. Вони називаються константам і посилаються на значення, які не планується змінювати (тобто на постійні величини).
Константи корисні для програміста з двох причин.
По-перше, вони роблять код зрозумілішим. Так, в наведеній програмі всюди, де треба звернутися до послідовності голосних букв, автор пише не "аеiоuаеєиоуіюя", а VOWELS. Якщо замість рядка користуватися ім’ям змінної, то зрозумілість програми виросте, адже, побачивши змінну, ви згадуєте, що вона значить, а який-небудь дивний рядок самим своїм виглядом може збентежити.
По-друге, константи економлять час набору і певним чином оберігають від описок, властивих повторному набору. Константи особливо корисні в тих випадках, коли вам доводиться мати справу з •довгими• значеннями, наприклад, з дуже великими числами і об’ємними рядками. Якщо одне і те ж незмінне значення зустрічається в коді в кількох місцях, то це привід створити константу.
Python дуже скрупульозний при роботі з рядками та символами. Інтерпретатор вважає, що "А" - не те ж саме, що "а". Оскільки константі VOWELS присвоєне рядкове значення, яке складається лише з букв в нижньому регістрі, варто переконатися, що оператор in співставляє зі зразком лише символи в нижньому регістрі. Для цього і потрібний запис letter.lower().
Наприклад, треба порівняти два рядкових значення: nаmе і winner, щоб побачити, чи співпадають вони; регістр неважливий. Тоді треба створити таку умову:
name.lower() == winner.lower()
Ця умова істинна в усіх випадках, коли name і winner мають одну і ту ж послідовність букв, навіть і набраних в різних регістрах. Так, рядки "Вася" і "вася" з цієї точки зору співпадають. Те ж відноситься до рядків "ВАСЯ" і "вася", навіть для "ВаСя" і "вАсЯ".
Розглянемо використання наведених операторів для керування сигналами на виводах RPi.
Керування цифровими виводами
Цифрові виходи
Приклад нижче показує, що для призначення цифрового виходу спочатку необхідно встановити, наприклад, вивід 18 GPIO (як показано на рис. вище), як цифровий вихід, а потім встановити на ньому необхідний рівень сигналу, наприклад, високий:
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)
GPIO.output(18, True)
Під час налаштування виводу за допомогою GPIO.output, ви можете встановити на ньому високий рівень, використовуючи значення True чи 1, або низький - використовуючи False чи 0.
Цифрові входи
Роботу цифрових входів RPi організовують подібно до цифрові виходів:
GPIO.setup(18, GPIO.IN)
value = GPIO.input(18)
print(value)
Можна також вказати, що вхід має на собі навантажувальний резистор, наступним чином:
GPIO.setup(switch_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
Аналогові виходи
Використання аналогових виходів на RPi є двоетапним процесом. Спочатку потрібно налаштувати вивід, щоб це був вихід, а потім ви повинні визначити ШІМ-канал, який використовує цей вивід. В наступному занятті ми розглянемо це детальніше на прикладі змішування кольорів.
Керування світлодіодом з Raspberry Pi
На відміну від Arduino, RPi не має міток поруч з виводами GPIO, щоб показати, що є що. Це залишає нам два варіанти: ми можете використовувати схему позначення GPIO, наведену вище, і за допомогою відліку знайти потрібний вивід, або можемо використати шаблон ідентифікації контактів, який надягається на виводи GPIO. На рис. нижче показане підключення до виводу 12 RPi, який на схемі позначається числом 18, світлодіоду через опір 200-470 Ом.
Напишемо і запустимо програму на RPi. Для цього введіть в редакторі наступне та збережіть з іменем on_off_control.py:
import RPi.GPIO as GPIO # 1
import time # 2
GPIO.setmode(GPIO.BCM) # 3
control_pin = 18 # 4
GPIO.setup(control_pin, GPIO.OUT)
try: # 5
while True: # 6
GPIO.output(control_pin, True)# 7
time.sleep(5)
GPIO.output(control_pin, False)
time.sleep(2)
finally:
print("Cleaning up")
GPIO.cleanup()
1. Щоб отримати доступ до контактів GPIO в RPi використовується бібліотека Python, яка називається RPi.GPIO і створена ентузіастом Raspberry Pi Ben Croston. Перший рядок коду імпортує цю бібліотеку, так що вона може бути використана в програмі. Бібліотека RPi.GPIO поставляється попередньо встановленою у всіх останніх версіях стандартного образу Raspbian, тому ви не повинні встановлювати її, якщо тільки не використовуєте стару версію Raspbian. У цьому випадку, найпростіший спосіб встановити її - просто оновити систему, що, ймовірно, слід зробити в будь-якому випадку, виконавши наступну команду в термінальній сесії:
$ sudo apt-get upgrade
2. Також повинна бути імпортована бібліотека часу, бо вона використовується, щоб викликати затримки між включенням світлодіоду і його вимкненням.
3. Рядок GPIO.setmode(GPIO.BCM)повинен бути включений в кожну програму Python, яку пишете для контролю виводів GPIO, перш ніж встановлювати режим виводів чи використовувати їх в якомусь іншому випадку. Команда повідомляє бібліотеці GPIO, що контакти повинні бути визначені їх іменами Broadcom (BCM), а не розміщенням виводів. Бібліотека RPi.GPIO підтримує дві різні схеми іменування, але іменування Broadcom є більш популярним і ми будемо використовувати його.
4. Змінна control_pin ідентифікує вивід 18 GPIO, як вивід, що використовується для управління світлодіодом, а потім цей вивід визначається, як вихід за допомогою GPIO.setup.
5. Тепер ми прийшли до еквіваленту функції циклу в Arduino. Це міститься в конструкції try/finally. Сенс цього в тому, що якщо в програмі виникає яка-небудь помилка, або ви просто зупинили програму, натиснувши Ctrl-C у вікні терміналу, в якому запустили програму, то код очищення в фінальному блоці буде працювати.
Можна опустити цей код і залишити лише цикл while, але код очищення встановлює автоматично всі виводи GPIO знову в безпечний стан, що робить набагато менш ймовірним те, що випадкова закоротка чи помилка з’єднання у вашому макеті може привести до пошкодження RPi.
6. Цикл продовжується, поки залишається True. Це може здатися дивним, але ми дійсно зробили деякий код, який триває нескінченно довго в Python. Насправді, програма просто продовжує виконання команд всередині циклу доти, поки ви не зупините програму з Ctrl-C або не вимкнете RPi.
7. Вивід GPIO встановлюється в TRUE (високий рівень), потім затримка в 5 секунд, потім вивід GPIO встановлюється в False (низький рівень) і ще 2-секундна затримка, а потім цикл починається знову.
Щоб отримати доступ до виводу GPIO, потрібні привілеї суперкористувача Linux (для Jessie таких привілеїв не треба). Щоб запустити програму, перейдіть в каталог, що містить on_off_control.py, а потім запустіть програму, використовуючи команду:
$ sudo python on_off_control.py
sudo на початку команди дозволяє запустити від імені суперкористувача.
Коли вже достатньо награєтесь, натисніть Ctrl-C для виходу з програми.
Порівняння коду
Загальна структура обох кодів: C для Arduino і Python дуже схожа, але сам код відрізняється за стилем. Крім того, при іменуванні змінних або функцій C використовує угоду, згідно якої кожне наступне слово після першого капіталізується – пишеться з великої літери, в той час як Python використовує snake_case (тобто, слова розділені підкресленням).
В таблиці нижче порівнюються деякі з ключових відмінностей між програмами на різних мовах: