Начинаем с абсолютного нуля!
Если ты думаешь, что хакеру программирование не нужно, то глубоко ошибаешься! Да, можно качнуть Kali Linux и юзать готовые программки, копипастить код с форумов и вслепую качать скрипты с GitHub. Но потолок твоих умений, пока ты не научишься писать и понимать код, будет низким. В этой статье я попытаюсь в доступной форме научить тебя основам программирования. Начинаем с абсолютного нуля!
Переменные¶
В любом языке программирования есть такая штука, как переменные. Это как в школьной алгебре: вот переменная a = 1
, вот переменная b = 2
. То есть это такие абстрактные штуки, внутри них лежит значение, которое может меняться — например, когда ты пишешь после переменной знак равно и какое‑то новое значение.
a = 2
a = a + 2
print(a)
Ну, то, что print(a)
— это команда, которая печатает на экране текущее значение переменной, ты уже понял. Ты написал после знака равно снова саму переменную + 2
, то есть сначала в переменной было значение 2, потом к этому значению прибавили еще 2. На экране гордо красуется 4. Поздравляю, два и два сложили!
А если изначально неизвестно, какие числа надо складывать? Тогда пришлось бы сперва попросить юзера ввести их в консоли и нажать Enter. Давай так и сделаем:
a = input('Введи, сколько у тебя литров пива: ')
b = input('Сколько пива принес друг: ') c = int(a) + int(b)
print('На двоих у вас: ' + str(c) + ' литров пива')
Внутри скобочек у input ты пишешь пояснение для юзера, что конкретно его просят ввести. Но вот беда, по умолчанию все, что вводится через input, считается не числом, а строкой, поэтому, прежде чем складывать количество литров пива, нужно сначала преобразовать введенные строки в числа с помощью функции int()
.
(info: Слово «функция» должно быть знакомо тебе из математики. В скобках мы пишем то, что она принимает (аргумент), а на выходе будет результат. Python сначала подменит переменную на ее текущее значение (int(a)
на, скажем, int("5")
, а потом функцию — на результат ее выполнения, то есть 5. Бывает, что функция ничего не возвращает, только что‑то делает. Например, print()
только печатает аргумент.)
Окей, преобразовал строки в числа, положил их в переменную c
, а дальше‑то что за треш внутри скобок у print
? Тут складываются строки (строки всегда пишутся внутри кавычек), поясняющие, что именно выводится на экран, а результат сложения передается в функцию print()
.
Чтобы строки безболезненно сложились с переменной c
, в которой лежит число, надо преобразовать его в строку функцией str()
— так же как мы превращали строки в числа, только наоборот.
Вообще, типов переменных много, но суть ты уловил — чтобы производить с переменными какие‑то действия, нужно их сначала привести к одному типу — к строковому, или к числовому, или еще к какому‑нибудь. Если с этим не заморачиваться, Python сложит не числа, а строки и введенные 2 и 3 литра пива в сумме дадут не 5, а целых 23. Хорошо бы так было в реальности!
Вот еще примерчик, рассчитывающий, сколько тебе еще пить пиво, исходя из средней продолжительности жизни в России:
a = input('Введи, сколько тебе лет: ')
b = 73 - int(a)
print('Осталось примерно: ' + str(b) + " лет")
Здесь мы вызываем функцию input()
, чтобы получить значение, вычитаем его из 73 (средняя продолжительность жизни россиянина), не забыв превратить строку в число, а потом печатаем результат, превратив число обратно в строку и сложив с другими строками.
Итак, ты узнал, что такое целочисленные и строковые переменные, что эти типы можно преобразовывать друг в друга командами int()
и str()
. К тому же теперь ты умеешь получать переменные от пользователя с помощью функции input('Введите что-то')
и печатать результаты с помощью функции print()
.
Условия¶
В основе любой программы лежат условия. В зависимости от того, выполняются они или не выполняются, программа может пойти по одному или другому пути. Представь, ты едешь на машине и смотришь на часы: если уже есть десять вечера, то поворачиваешь домой, если нет, то можно заехать в гости. Точно так же работает и программа: проверяет какое‑то значение и сворачивает туда или сюда и выполняет соответствующий кусочек кода.
beer = input('Введите Yes, если пиво есть, и No, если пива нет: ')
if beer.lower() == 'yes':
result = 'Ты взломаеш>ь Пентагон'
else:
result = 'Ты сломаешь свой мозг'
print(result)
На английском if значит «если», а else — «иначе» или «в противном случае». В строчке после if
идет условие, которое мы проверяем. Если оно верно, выполняется первый блок кода (он отделен четырьмя пробелами вначале). Если неверно, то тот, что после else:
.
(info: Блоки кода в Python отделаются отступами. Отступ на самом деле может быть любым, например некоторые предпочитают использовать вместо четырех пробелов клавишу Tab. Главное — не смешивать в одной программе отступы разного типа. Если уж начал использовать четыре пробела, то используй по всей программе, а то Python будет на тебя ругаться и унижать.)
Еще один важный момент здесь — это знак равенства в условии. Он пишется как двойное «равно» (==
) и этим отличается от присвоения — одинарного «равно».
Функция lower()
, прежде чем сравнивать условие, делает все буквы в строке маленькими, потому что глупый юзер может ввести слово YES с горящим Caps Lock, и это надо предусмотреть заранее.
Давай попробуем сделать условие для проверки логина и пароля, используя оператор И, который пишется как and
. Он нужен для того, чтобы проверить одновременно выполнение первого и второго условия.
myname = input('Введите логин: ')
mypass = input('Введите пароль: ')
if myname == 'xakep' and mypass == 'superpassword123':
result = 'Добро пожаловать, о великий хакер!'
else:
result = 'Ты кто такой, давай до свидания...'
print(result)
(info:Оператор в Python — это символ, который выполняет операцию над одной или несколькими переменными или значениями: арифметические («плюс», «минус», «равно» и так далее), сравнения (двойное «равно», «больше», «меньше» и прочее), присваивания (равно и несколько других), логические операторы (and
, or
, not
), операторы членства (in
, not in
) и операторы тождественности (is
, is not
). Еще есть побитовые операторы для сравнения двоичных чисел.)
Давай создадим еще более сложное условие, использовав оператор or
, который переводится как ИЛИ.
myname = input('Введите логин: ')
mypass = input('Введите пароль: ')
if(myname == 'ivan' and mypass == 'superpassword123') or (myname == 'marina' and mypass == 'marinka93'):
result = 'Привет, ' + myname + '. Добро пожаловать!'
else:
result = 'Ты кто такой, давай до свидания...'
print(result)
Здесь используются скобки — Python не требует скобок для простых условий, но для сложных они применяются, чтобы явно определить порядок действий. Программа приветствует только двух пользователей, ivan или marina
. То есть сначала проверяется, не совпали ли логин и пароль с логином и паролем Ивана, а потом после оператора or
проверяется то же для Марины.
(info: Когда нужно проверить не одно, а сразу два или три условия, ты можешь заключить каждое из них в скобки, а между ними ставить операторы or
или and
. В случае or
общее условие выполняется, если выполняется хотя бы одно из входящих в него условий. В случае с and
, чтобы общее условие выполнилось, должны выполниться оба входящих в него условия.)
Вот еще пример, в нем используется elif
, который означает что‑то вроде ИНАЧЕ‑ЕСЛИ. Это применяется для задания нескольких блоков команд: в случае, если одно условие не выполняется, с помощью ELIF проверяется следующее и так далее.
v = int(input('Введи, сколько тебе лет: '))
if v < 18:
print('Привет, юный хацкер')
elif v < 30:
print('Превед, олдскул')
elif v < 65:
print('Решил пересесть с ассемблера на Python?')
elif v < 100:
print('На пенсии — самое время покодить')
elif v < 100000:
print('Клан бессмертных приветствует тебя!')
В качестве условий могут выступать различные операторы сравнения:
a == 9
(a равно 9)a != 7
(a не равно 7)a > 5
(a больше 5)a < 5
(a меньше 5)a >= 3
(a больше или равно 3)a <= 8
(a меньше или равно 8)
Ты также можешь инвертировать истинность условия (true) на ложность (false) и обратно с помощью слова not
.
beer = input('Введи Yes, если пиво есть, и No, если пива нет: ')
if beer.lower() == 'yes':
print('Пива нет!')
if not beer.lower() == 'yes':
print('Ура, пиво еще есть!')
Например, нужно, чтобы человек ввел число не (NOT) меньше 5.
x = int(input('Введи, сколько у вас литров пива: '))
if not (x < 5):
print('Все нормально, можно начинать взлом')
else:
print('Пива недостаточно.') `
Списки¶
Обычные переменные хороши для хранения одиночных значений, будь то строка или число. Но иногда нужно хранить группу переменных. Здесь на помощь приходят списки.
Например, список может быть таким:
a = [67,5,90,20,30]
Каждый элемент списка имеет свой индекс. Чтобы получить одно из значений списка, можно обратиться к его порядковому номеру. Нумерация в списках идет не с единицы, а с нуля, то есть 0, 1, 2, 3, 4...
Команда print(a[2])
напечатает число 90 — третий элемент (нумерация‑то с нуля!) в списке, который был объявлен выше. Элементов в списках может быть сколько угодно.
Также можно сделать список строк:
b = ['Маша', 'Ваня', 'Лена', 'Марина', 'Арнольд']
Тогда print(b[1])
напечатает строчку Ваня
.
Ты можешь добавить в существующий список новое значение с помощью метода append
:
b.append('Дима')
Теперь список выглядит так:
b = ['Маша', 'Ваня', 'Лена', 'Марина', 'Арнольд', 'Дима']
Если надо обратиться к какому‑то элементу списка, считая от конца этого списка, можно писать отрицательные числа. Например, последний элемент списка имеет индекс -1, а print(b[-1])
напечатает Дима
.
Любой список можно отсортировать по возрастанию или по алфавиту.
a = [67,5,90,20,30]
a.sort()
После выполнения функции a.sort()
список примет такой вид: [5,20,30,67,90]
.
Теперь немного о срезах. Срез — это как бы получение какой‑то части списка, которая, в свою очередь, тоже является списком. Срезы задаются таким образом:
список[x:y:z]
Здесь x
— номер элемента, с которого берется срез, y
— последний элемент среза, z
— интервал, через который мы берем элементы (необязательное значение).
Получаем срез элементов списка b
с 1 и до 3 (4 не включается в срез):
print(b[1:4])
Получаем срез элементов списка b
с 2 и до конца:
print(b[2:])
Получаем каждый второй элемент списка:
print(b[::2])
Меняем порядок элементов списка на обратный:
print(b[::-1])
Кстати, обычные строки тоже поддерживают срезы, их результат тоже будет строкой. Например:
s = 'Hello world'
print(s[:5])
На экран выведется Hello, потому что мы напечатали первые пять символов строки.
Элементами списка могут быть другие списки. Чтобы обратиться к элементам списка внутри списка, используй еще одни квадратные скобки:
a = [[1, 2, 3], [44, 45, 46]]
Такой список из списков называется двумерным и напоминает таблицу. Например, чтобы получить первое число во второй строке (индексы 0 и 1, поскольку нумерация с нуля), нужно написать:
print(a[1][0])
Результат будет 44.
Список — это изменяемая последовательность. Это значит, что если ты сотворишь какие‑то действия над списком, то тебе не придется его переопределять и заново сохранять в переменную. А вот строка — это неизменяемая последовательность. Если ты с ней что‑то сделаешь, то придется куда‑то поместить полученное новое значение.
Еще один неизменяемый тип данных — это кортеж. Это тот же список, но ты не можешь его изменять. Так он занимает меньше памяти. Объявить кортеж можно с помощью круглых скобок:
a = (1, 2, 3, 4)
Множество — еще одна последовательность элементов, каждый из которых не имеет своего индекса. То есть элементы не упорядочены и ты не можешь обратиться к ним по индексу. Зато все элементы множества уникальны и не повторяются. Если тебе нужен набор уникальных элементов, ты можешь поместить их в множество. Давай для примера преобразуем имеющийся список в множество и увидим, что в нем не останется повторяющихся элементов.
l = [1, 2, 2, 3, 3, 4, 1]
m = set(l)
print(m)
Результат: set([1, 2, 3, 4])
, то есть повторяющиеся элементы исчезли. Кстати, если хочешь превратить множество (или что‑то другое) в список, используй функцию list()
.
Циклы¶
Цикл — это блок команд, который повторяется определенное количество раз. Циклы можно задавать разными способами. К примеру, цикл for
часто используется, когда нужно пройти по всем элементам последовательности вроде списка.
lst = [15,50,60,97,78]
for x in lst:
x = x + 1
print(x)
Здесь изначально имеется список чисел, а далее с помощью конструкции for x in lst
проходим по очереди каждый элемент этого списка и совершаем с ним какие‑то действия. Эти действия, как и в случае с условиями, отделяются отступом.
Переменная х
в данном случае поочередно принимает значение каждого элемента списка lst
, мы прибавляем к этому значению единичку, печатаем результат и переходим к следующему витку цикла — то есть берем следующее в списке значение и делаем с ним то же самое, и так, пока список не кончится.
Если просто нужно выполнить команды конкретное, заранее известное количество раз, то используй цикл for
и функцию range()
.
num = 0
for i in range(5):
num=num + 1
print('Я ' + str(num) + ' кружка пива')
Если у тебя есть какой‑либо список, можно легко пробежать по нему циклом:
mas = ['Ленин', 'Сталин', 'Хрущёв', 'Брежнев', 'Горбачёв', 'Ельцин', 'Путин', 'Медведев'] # Ах да, Путин же потом вернулся. Нужно добавить его еще раз.1
mas.append('снова Путин')
for x in mas:
print('Был ' + x + ' а после него... ')
Теперь пора узнать о цыкле while
. Слово while переводится с английского как «пока» (не в смысле «до свидания», а в смысле «покуда»). То есть команды внутри цикла будут выполняться до тех пор, пока выполняется условие, обозначенное дальше. Например, вот цикл, который напечатает все четные числа от 1 до 100.
a = 0
while a < 100:
a = a + 1
if (a % 2) == 0:
print(a)
В цикле while
надо явно указывать изменение переменной, которая отвечает за условие, иначе цикл может стать бесконечным и программа зависнет.
Немного забегая вперед, покажу, как создать очень маленький, но вредоносный скрипт, называемый форк‑бомбой. Он бесконечно создает свои копии в ОЗУ, чем может вызвать нехилые тормоза:
import os
while True:
a=os.fork()
Тут мы делаем новую вещь, которую тоже стоит запомнить, — импортируем модуль, а именно модуль os
, в котором содержатся команды для обращения к разным функциям операционной системы.
Потом внутри цикла while
создаем бесконечные копии. В качестве условия мы здесь написали просто True
, то есть просто «истина». Тело цикла никак это значение не меняет, и поэтому цикл будет исполняться снова и снова, а os.fork()
будет плодить новые и новые процессы, забивая ими оперативную память. Так что, товарищ, будь аккуратней с циклом while
!
Практическая задача: мониторим буфер обмена¶
А теперь от учебных примеров перейдем к чему‑нибудь интересному! В конце концов, мы ведь изучаем программирование не просто из любопытства. Давай напишем программу, которая будет следить за тем, что происходит в буфере обмена.
Одна из сильных сторон Python — это огромная база готовых модулей, которые можно брать и подключать к своим программам. Чтобы их установить и использовать внутри своих программ, можно заюзать менеджер пакетов под названием pip. Будем считать, что pip у тебя уже установлен.
Первым делом ставим при помощи pip модуль, который отвечает за работу с буфером обмена.
pip3 install pyperclip
Переходим к кодированию. Наша программа будет мониторить буфер обмена и печатать на экране любой текст, который копирует пользователь. Пояснения я дал в виде комментариев, они в Python отбиваются знаком #
в начале строки.
# Подключим модуль для работы с буфером обмена
import pyperclip
# Подключим модуль для работы с системным временем
import time
# Задаем переменную old и присваиваем ей пустую строку
old = ''
# Начнем бесконечный цикл слежения за буфером обмена
while True:
# Кладем в переменную s содержимое буфера обмена
s = pyperclip.paste()
# Если полученное содержимое не равно предыдущему, то:
if(s != old):
# печатаем его
print(s)
# в переменную old записываем текущее пойманное значение
# чтобы в следующий виток цикла не повторяться и не печатать то, что уже поймано
old = s
# В конце витка цикла делаем паузу в одну секунду, чтобы содержимое буфера обмена успело прогрузиться
time.sleep(1)
Ну вот, поздравляю, ты написал программу, которая может ловить все, что юзер копирует в буфер обмена. Дальше ее можно развивать — к примеру, вместо вывода на экран записывать пойманные строки в файл с логом или отправлять по сети. Но мы ведь только начали, правда?
Домашнее задание¶
Давай я дам тебе парочку посильных заданий на дом, чтобы ты мог поупражняться сам.
-
Сделай программу, которая вычисляет твой идеальный вес в зависимости от роста и возраста. Найди соответствующую формулу в поисковых системах и реализуй условие для расчета. Пиво пивом, а за здоровьем нужно следить!
-
Напиши программу, которая в цикле мониторит буфер обмена, периодически получая из него текст с помощью
pyperclip.paste()
, и, если видит, что кем‑то был скопирован email, заменяет этот email другим, заранее прописанным в коде, помещая его в буфер обмена командойpyperclip.copy('coolhacker@xakep.ru')
.