Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Программирование на языке Python. Учебное пособие.pdf
X
- •ПРЕДИСЛОВИЕ
- •I. ВВЕДЕНИЕ В ПРОГРАММИРОВАНИЕ
- •1. Начало работы
- •2. Основные понятия
- •Ввод и вывод данных
- •Логические операторы
- •Условные инструкции
- •Инструкции
- •Типы данных
- •Константы и переменные
- •Арифметические операторы
- •Операторы сравнения
- •3. Функции
- •Определение функций
- •Встроенные функции
- •Многократное использование функций
- •Типы параметров функции
- •Область видимости
- •Обработка исключений
- •Строки документации
- •4. Контейнеры
- •Методы
- •Списки
- •Кортежи
- •Словари
- •Контейнеры внутри контейнеров
- •5. Операции со строками
- •6. Циклы
- •Цикл for
- •Цикл while
- •Операторы break и continue
- •Функция Enumerate
- •Вложенные циклы
- •Настройка функции print()
- •7. Модули
- •8. Файлы
- •Запись в файлы
- •Использование конструкции with
- •Чтение из файлов
- •CSV-файлы
- •II. ВВЕДЕНИЕ В ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ (ООП)
- •9. Парадигмы программирования
- •Состояние
- •Процедурное программирование
- •Функциональное программирование
- •Объектно-ориентированное программирование
- •10. Базовые понятия ООП
- •Наследование
- •Полиморфизм
- •Абстракция
- •Инкапсуляция
- •Композиция
- •11. Дополнительные понятия ООП
- •Как работают переменные
- •Ключевое слово is
- •Константа None
- •Классы – это объекты
- •Переменные класса и переменные экземпляра класса
- •Приватные переменные
- •Методы переопределения
- •Функция super
- •Переопределение встроенных методов
- •12. Создание игр
- •Карты
- •Колода
- •Игрок
- •Игра
- •Игра «War»
- •13. Bash
- •Запуск Bash
- •Использование Bash
- •Относительные и абсолютные пути
- •Навигация
- •Флаги
- •Редактор vim
- •Команда touch
- •Просмотр файлов командой less
- •Пользователи
- •Разрешения
- •Программы Bash
- •Скрытые файлы
- •Переменные окружения
- •Переменная окружения $PATH
- •Вертикальная черта (пайп)
- •Команда cat
- •Последние команды
- •Быстрые перемещения
- •Экранирование (escaping)
- •Регулярные выражения в Python
- •15. Менеджеры пакетов
- •Вкладка «Завершение»
- •Функция wildcard (подстановочный знак)
- •Другие инструменты
- •14. Регулярные выражения
- •Настройка
- •Простое совпадение
- •Игнорирование регистра
- •Вывод только конкретных совпадений слов
- •Совпадение в начале и в конце
- •Поиск совпадений с несколькими символами
- •Повторение
- •Диапазон
- •16. Управление версиями
- •Репозитории
- •Помещение и извлечение данных
- •Пример помещения данных
- •Пример извлечения данных
- •Откат версий
- •Команда git diff
- •Другой запрос на включение
- •IV. ВВЕДЕНИЕ В ИНФОРМАТИКУ
- •17. Структуры данных и алгоритмы
- •Что такое алгоритмы и структуры данных?
- •Нотация Big-O
- •Оператор деления по модулю
- •Сортировка методом пузырька
- •Поисковый алгоритм
- •Рекурсия
- •Абстрактные типы данных
- •Узлы
- •Стеки
- •Связанные списки
- •Массивы
- •Бинарные деревья
- •Поиск в ширину и в глубину
- •Хэш-таблицы
- •ЗАКЛЮЧЕНИЕ
- •БИБЛИОГРАФИЧЕСКИЙ СПИСОК

Чтобы играть в игру War, нужно уметь сравнивать две карты, чтобы ви-
деть, какая карта больше. Добавили возможность сравнения двух карт в выражении с операторами сравнения больше (>) и меньше (<) в класс Card, определив два магических метода, используемых этими операторами сравнения:
__lt__ и __gt__. Определив эти методы, можно понять, что происходит
при сравнении объектов Card, точно так же, как делали с примером
AlwaysPositive в предыдущей главе, за исключением того, что вместо оператора сложения используются операторы сравнения. Код в этих методах проверяет, является ли карта больше или меньше другой карты, переданной в качестве параметра. Однако нужно принять во внимание еще одну вещь – что произойдет, если карты будут иметь одинаковое значение, например если обе карты десятки. При возникновении такой ситуации нужно сравнить значение мастей и возвратить результат. Это работает, потому что целые числа, которые
используются для представления мастей, упорядочены – самая сильная масть
получает наибольшее целое число, а наименее сильная масть – наименьшее целое число. Определив эти методы, можно сравнивать карты, используя операторы «больше» и «меньше»:
card1 = Card(10, 2)
card2 = Card(11, 3)
print(card1 < card2)
>> True
card1 = Card(10, 2)
card2 = Card(11, 3)
print(card1 > card2)
>> False
В последнюю очередь переопределяется магический метод __repr__, ко-
торый используется функцией печати для вывода объекта. Переопределение
метода __repr__ позволяет распечатать карту, которую представляет объект
Card:
card = Card(3, 2)
print(card)
>> 3 of diamonds
111

Колода
Далее нужно определить класс Deck для представления колоды карт. Ко-
лода создаст список из пятидесяти двух карт – по четыре каждой масти – при
инициализации, и у нее будет метод для удаления карты из списка карт:
from random import shuffle
class Deck:
def __init__ (self):
self.cards = []
for i in range(2, 15):
for j in range(4):
self.cards.append(Card(i, j))
shuffle(self.cards)
def remove_card(self):
if len(self.cards) == 0:
return
return self.cards.pop()
Когда объект Deck инициализируется, два цикла for в __init__ созда-
ют все карты в колоде из пятидесяти двух карт и добавляют их в список карт.
Первый цикл – от 2 до 15, потому что карты начинаются со значения 2 и заканчиваются значением 14 (туз). Каждый раз во внутреннем цикле будет создаваться новая карта, используя целое число из внешнего цикла в качестве значения (например, 14 для туза) и целое число из внутреннего цикла в качестве масти (например, 2 для червей). В результате получается пятьдесят две карты – по
одной каждой масти.
Наконец, используется метод перетасовки shuffle из модуля random,
чтобы случайным образом переставить элементы в списке карт, имитируя перетасовку колоды карт. Колода имеет только один метод – remove_card, кото-
рый возвращает None, если список карт пуст, а в противном случае удаляет
и возвращает карту из списка карт. Используя класс Deck, можно создать новую колоду карт и распечатать все карты в колоде:
deck = Deck()
for card in deck.cards:
print (card)
112

>> 4 of spades
>> 8 of hearts
…
Игрок
Необходим класс, представляющий каждого игрока в игре, чтобы можно было отслеживать их карты и количество выигранных раундов. Вот класс игрока:
class Player:
def __init__ (self, name):
self.wins = 0
self.card = None
self.name = name
В классе Player есть три переменные экземпляра: wins, чтобы отслеживать, сколько раундов они выиграли, card, чтобы представлять текущую карту, которую держит игрок, и name, чтобы отслеживать имя игрока.
Игра
Наконец, можем создать класс Game, представляющий саму игру:
class Game:
def __init__ (self):
name1 = input("player1 name")
name2 = input ("player2 name")
self.deck = Deck()
self.player1 = Player(name1)
self.player2 = Player(name2)
def play_game(self):
cards = self.deck.cards
print("beginning War!")
response = None
while len(cards) >= 2 and response != 'q':
response = input('q to quit. Any other key to
play.')
player1_card = self.deck.remove_card()
113

player2_card = self.deck.remove_card()
print("{} drew {} {} drew
{}".format(self.player1.name,
player1_card, self.player2.name,
player2_card))
if player1_card > player2_card:
self.player1.wins += 1
print("{} wins this
round".format(self.player1.name))
else:
self.player2.wins += 1
print("{} wins this
round".format(self.player2.name))
print("The War is over.{}
wins".format(self.winner(self.player1,
self.player2)))
def winner(self, player1, player2):
if player1.wins > player2.wins:
return player1.name
if player1.wins < player2.wins:
return player2.name
return "It was a tie!"
Когда игровой объект инициализируется, вызывается метод __init__
и используется функция ввода input для сбора имен двух игроков в игре, которые сохраняются в переменных name1 и name2. Создаем новый объект
Deck и сохраняем его в переменной экземпляра deck, а также создаем два
объекта Player, используя имена, которые получили от пользователя, и сохраняем их в переменных экземпляра player1 и player2.
В классе Game есть метод play_game, используемый для запуска игры.
Сердцем метода является цикл, который поддерживает игру до тех пор, пока
в колоде осталось две или более карт и пока переменная response не равна
«q». Перед циклом определяем response как None, а позже устанавливаем
его на ввод пользователя, и это единственная ситуация, когда он может стать
«q» и завершить игру. В противном случае игра заканчивается, когда в колоде
остается менее двух карт.
114

Каждый раз через цикл вытягиваются две карты. Первая карта назначена
игроку 1 (player1), а вторая – игроку 2 (player2). Далее печатаем имя каждого игрока и карту, которую он вытащил. Сравниваем две карты, чтобы увидеть, какая карта больше, увеличиваем переменную экземпляра wins для выигравшего игрока и печатаем сообщение о том, какой игрок выиграл.
В классе Game также есть метод с именем winner, который принимает
два объекта игроков, отслеживает количество выигранных ими раундов и возвращает игрока, выигравшего наибольшее количество раундов. Когда в колоде
заканчиваются карты, печатаем сообщение о том, что война окончена, вызываем метод winner (передавая в него player1 и player2) и печатаем сообщение с итогом игры – именем игрока победителя.
Игра «War»
При объединении всех фрагментов получится карточная игра «War»:
from random import shuffle
class Card:
suits = ["spades", "hearts", "diamonds", "clubs"]
values = [None, None, "2", "3", "4", "5", "6", "7",
"8", "9", "10", "Jack", "Queen", "King",
"Ace"]
def __init__ (self, value, suit):
"""suit and value should be integers"""
self.value = value
self.suit = suit
def __lt__ (self, other):
if self.value < other.value:
return True
if self.value == other.value:
if self.suit < other.suit:
return True
else:
return False
return False
115

def __gt__ (self, other):
if self.value > other.value:
return True
if self.value == other.value:
if self.suit > other.suit:
return True
else:
return False
return False
def __repr__ (self):
return self.values[self.value] + " of " +
self.suits[self.suit]
class Deck:
def __init__ (self):
self.cards = []
for i in range(2, 15):
for j in range(4):
self.cards.append(Card(i, j))
shuffle(self.cards)
def remove_card(self):
if len(self.cards) == 0:
return
return self.cards.pop()
class Player:
def __init__ (self, name):
self.wins = 0
self.card = None
self.name = name
class Game:
def __init__ (self):
name1 = input("player1 name ")
name2 = input("player2 name ")
self.deck = Deck()
self.player1 = Player(name1)
self.player2 = Player(name2)
116

def play_game(self):
cards = self.deck.cards
print("beginning War!")
response = None
while len(cards) >= 2 and response != 'q':
response = input('q to quit. Any other key to
play.')
player1_card = self.deck.remove_card()
player2_card = self.deck.remove_card()
print("{} drew {} {} drew
{}".format(self.player1.name,
player1_card, self.player2.name,
player2_card))
if player1_card > player2_card:
self.player1.wins += 1
print("{} wins this
round".format(self.player1.name))
else:
self.player2.wins += 1
print("{} wins this
round".format(self.player2.name))
print("The War is over.{}
wins".format(self.winner(self.player1,
self.player2)))
def winner(self, player1, player2):
if player1.wins > player2.wins:
return player1.name
if player1.wins < player2.wins:
return player2.name
return "It was a tie!"
game = Game()
game.play_game()
>> "player1 name "
…
117

III. ВВЕДЕНИЕ В ИНСТРУМЕНТЫ
ый Bash. В нем есть команды, которые похожи на фун
ПРОГРАММИРОВАНИЯ
13. Bash
Оболочка командной строки Bash поставляется со многими версиями
Linux и OS X (которые являются Unix-подобными операционными системами).
Оболочка командной строки Bash – это программа, позволяющая вводить в нее
инструкции, которые компьютер выполняет, когда нажимается клавиша ввода.
Освоение оболочки Bash позволит более эффективно использовать Unixподобные операционные системы. Это важно, потому что Unix-подобные операционные системы очень широко используются в мире программирования:
Linux работает на большинстве мировых веб-серверов и многие задания по
программированию потребуют знаний с Unix-подобными операционными системами.
В примерах этой главы предполагается, что будет использоваться Ubuntu
или OSX.
Запуск Bash
Запуск Bash осуществляется с поиска с помощью значка «Поиск на вашем
компьютере и онлайн-ресурсах», если используется Ubuntu, или с помощью поиска Spotlight, если используется Mac.
Использование Bash
Интерфейс Bash похож на оболочку Python. Оболочка командной строки
Bash принимает в качестве входных данных свой собственный язык программирования, называем
ции в Python. Начинаем с ключевого слова; вводим пробел; вводим параметры,
которые хотим задать команде (если таковые имеются); нажимаем клавишу
Enter и Bash возвращает результат. Одной из команд Bash является
рая похожа на функцию печати в Python.
echo, кото-
118
к-

Пример:
$ echo Hello, World!
>> Hello, World!
В Bash после команды echo ставится пробел и Hello, World! как параметр.
При нажатии Enter Hello, World! печатается в оболочке командной строки Bash.
Также можно использовать установленные программы, например Python,
из оболочки командной строки Bash. Чтобы использовать Python из оболочки,
введите команду python3.
$ python3
>>
Теперь выполните код Python:
print(“Hello, World!”)
>> Hello, World!
Чтобы выйти из Python, надо ввести команду exit().
Относительные и абсолютные пути
Операционная система состоит из каталогов (папок) и файлов. Все каталоги и файлы имеют путь. Путь – это адрес, по которому в операционной системе
существует каталог или файл. Когда вы используете оболочку командной строки Bash, то всегда находитесь в каталоге, расположенном по определенному
пути. Увидеть путь, по которому вы находитесь, можно введя команду pwd
(сокращенно от print working directory – вывод рабочего каталога) в оболочке
командной строки Bash:
$ pwd
>> /Users/bernie
Команда pwd (сокращенно от print working directory) – печать рабочего каталога, рабочий каталог – это каталог, в котором вы сейчас находитесь, а путь,
который печатается на вашем компьютере, будет именем любого каталога,
в котором вы находитесь.
119

Папки в операционной системе представляют собой дерево. Дерево – важ-
ная концепция в информатике, называемая структурой данных (будет рассматриваться позже). В дереве есть корень наверху. Корень может иметь ветви,
каждая из ветвей может иметь больше ветвей, которые тоже могут иметь ветви.
Это продолжается бесконечно.
Каждая ветвь дерева представляет собой каталог, включая корень. Дерево
показывает, как они связаны друг с другом. Когда используется Bash, в любой
момент времени можно находиться в одном из мест дерева, а путь – это способ
выразить это местоположение. В Unix-подобных операционных системах есть
два способа указать местоположение: абсолютный путь и относительный путь.
Абсолютный путь – это способ указать расположение, начиная с корневого каталога. Абсолютный путь состоит из имен папок в дереве по порядку, разделенных обратной косой чертой (слэш). Абсолютный путь к каталогу bernie (для
показанной выше операционной системы) – /home/bernie. Первый слэш обозначает корневой каталог, затем домашний каталог, за которым следует еще один
слэш, и каталог bernie.
Относительный путь – это способ указать местоположение на компьютере.
Вместо того чтобы начинать с корневого каталога, относительный путь относится к каталогу, в котором вы находитесь. Ваша операционная система знает,
что путь является относительным, если он не начинается с обратной косой черты. Если находиться в домашнем каталоге в приведенном выше примере, относительный путь к каталогу проектов был бы bernie/projects. Если находиться в домашнем каталоге, относительный путь к bernie был бы просто bernie.
Если находиться в каталоге root, относительный путь к projects был бы
home/bernie/projects.
120
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
