Views Comments Previous Next Search

Я учусь программировать на Python: классы и объекты

 В новом выпуске блога о программировании я начинаю писать текстовую игру LAM-40 на Python и рассматриваю ещё одно ключевое понятие в программировании — класс.

Я учусь программировать на Python: классы и объекты. Изображение № 1.

Предыдущий выпуск

Я учусь программировать
на Python: циклы, условия
и исключения

 

Я учусь программировать на Python: классы и объекты. Изображение № 2.

Как я и обещал, после недельного перерыва, вызванного WWDC, мы возвращаемся к Python. Мы закончили работать над программой, вычисляющей квадрат заданного целого числа, так что пора взяться за что-нибудь более масштабное — например, текстовую игру, которая поможет разобраться в ключевых понятиях объектно-ориентированного программирования. Если вы интересуетесь программированием, вы наверняка сталкивались с этим термином. Что он значит?

В языке, который следует объектно-ориентированной парадигме, все сущности рассматриваются как объекты, имеющие набор заданных свойств и методов — функций, которыми они обладают. С объектами тесно связано понятие класса — некоего нейтрального прототипа объекта, а точнее — структуры, на основе которой создаются объекты. Говоря образами, класс — это такая коробка, на которой есть несколько наклеек без надписей. Когда мы создаём объект на основе класса, мы делаем на этих наклейках уникальные подписи, наследуя форму, заданную классом. Пока это, наверное, звучит слишком абстрактно и непонятно, но, надеюсь, на примерах будет доходчивее.

Примечание: Весь код приводится для Python версии 3.0 и старше, а потому может не работать на более старых версиях.

   

Прежде чем что-то писать, надо разобраться, что именно мы будем делать — составить план. Начнём с простейшего гейм-дизайна. Игра, которую мы будем писать, рассказывает о борьбе простого человека с бюрократией. Задача игрока — получить до конца дня справку под названием LAM-40 на самом высоком, 40-м этаже огромного государственного учреждения. В честь этой справки я игру и назову.

Как устроена LAM-40? В начале каждого цикла игры (а любая игра — это, по сути, бесконечный цикл) случайным образом генерируется этаж здания со всеми его бюрократическими препятствиями — бесконечными, одинаковыми дверьми и окошками, недружелюбными служащими и длинными, назойливыми очередями. Игрок выполняет определённую последовательность действий, на которую тратит некое количество времени — и либо переходит на следующий этаж, генерируемый случайным образом, либо остаётся на том же этаже, либо откатывается на один из предыдущих этажей, либо вообще проигрывает, если сильно напортачил.

Нерв игры — в балансе между риском и ограничением по времени. Вы можете вести себя нагло и быстрее продвигаться по зданию, но это оценят не все государственные служащие — если вы переборщите, кто-нибудь, например, позовёт полицию, и справку вы в этот день не получите. С другой стороны, если вы будете вести себя слишком осторожно, то не успеете добраться до 40-го этажа — ведь учреждение работает всего девять часов. Поэтому, чтобы добиться цели, игроку нужно оценивать обстановку и принимать решения исходя из неё — где-то рисковать, а где-то осторожничать.

   

Теперь вкратце опишу структуру игры, а точнее — какие в ней встречаются повторяющиеся типы объектов. Крупнейший из них — этаж. У каждого этажа есть набор свойств, которые генерируются случайным образом. Соответственно, нам потребуется создать класс этажа, из которого будут создаваться этажи-объекты, где и будет происходить действие игры. Какие типовые объекты есть на каждом этаже? Это, например, государственные служащие, которых я уже упомянул в описании игры (очень важно! я называю государственных служащих объектами лишь с точки зрения программирования!). Давайте создадим класс государственного служащего, на основе которого будут создаваться все государственные служащие в игре. В основном они будут выступать противниками игрока, но иногда могут стать и союзниками.

import random

greetings = ["'How can I help you?'", "'...'", "'Next!'"]
MOODS = ('bad', 'average', 'good')
RANKS = ('low', 'medium', 'high')


class Bureaucrat:
    '''A government employee who works in the Institution.'''

    def __init__(self):
        self.rank = random.choice(RANKS)
        self.mood = random.choice(MOODS)

    def greet(self):
        '''A random greeting from the government employee.'''

        print(random.choice(greetings))
        print('The bureaucrat is of a {} rank.'.format(bureaucrat.rank))
        print("The bureaucrat's mood seems to be {}.".format(bureaucrat.mood))

bureaucrat = Bureaucrat()
bureaucrat.greet()

  Первым делом мы импортируем библиотеку random (возможно, вам потребуется её установить), из которой нам нужна функция choice(), позволяющая выбирать случайный объект из списка. Импортирование с помощью ключевого слова import и названия библиотеки обычно всегда проводится в начале файла.

  Создаём список с приветствиями. Список — это один из основных способов хранения данных в Python, аналог массива в других языках. Как они работают и что с ними можно делать, мы разберём чуть позже, а пока лишь замечу: списки позволяют хранить набор разных элементов в виде чётко заданной последовательности.

  Создаём кортежи с возможными настроениями и рангами служащих. Основное отличие кортежа от списка в том, что его содержимое нельзя изменить. Так как мы подразумеваем, что набор настроений и рангов меняться не будет, мы записываем переменные, хранящие их, большими буквами.

  Создаём класс государственных служащих с помощью ключевого слова class. Обратите внимание на синтаксис: название класса записывается с большой буквы, а скобки используются опционально, в том случае если вы наследуете свойства и методы другого класса — но об этом позднее.

  Содержимое класса — это блок кода, и потому вслед за двоеточием идёт отступ на четыре пробела. В тройных кавычках помечается описание класса или функции. Это стандартизированный комментарий в Python, позволяющий понять человеку, читающему код, зачем нужны этот класс или эта функция.

  Содержимое специального метода __init__() выполняется каждый раз, когда мы создаём объект на основе класса. Каждому образцу класса присваиваются указанные в __init__() характеристики, в нашем случае — ранг и настроение, которые у каждого государственного служащего будут случайные. Для того чтобы извлечь из кортежей ранг и настроение, мы используем функцию choice() из библиотеки random. Доступ к любой функции из сторонней библиотеки можно получить, написав название библиотеки и название функции, разделённые точкой.

  Возможно, ваше внимание привлекло ключевое слово self, которое неоднократно используется внутри класса. Это одна из наиболее неинтуитивных вещей на начальных этапах изучения программирования. Суть в том, что в Python запись вроде rank = random.choice(RANKS) будет некорректной внутри класса. Слово self помогает интерпретатору понять, что мы присваиваем некое значение одному из бесконечного числа возможных образцов класса. Я сейчас не буду вдаваться в подробности, а просто обращаю ваше внимание — когда вы планируете, каким будет образец класса, вам обязательно нужно использовать слово self — это касается в том числе специального метода __init__(), где его надо поместить в скобки.

  Функция greet() класса Bureaucrat выдаёт случайно выбранное приветствие, а также даёт понять, какими свойствами обладает созданный служащий. Закончив описание класса, мы прописываем всего две команды: присваиваем переменной bureaucrat образец класса Bureaucrat и используем метод greet(), чтобы понять, какой служащий был создан и присвоен переменной bureaucrat. Так как мы используем функцию random.choice() внутри класса, каждый образец класса Bureaucrat будет с высокой вероятностью отличаться от предыдущего. 

   

На этом пока всё. Сегодня мы познакомились с основами объектно-ориентированного программирования, создав простейший класс государственного служащего, и заложили одну из частей фундамента игры. В следующий раз мы продолжим изучать возможности классов, тщательнее их продумаем, да и структура игры начнёт вырисовываться более ясно.

Я понимаю, что, возможно, не все объяснения были корректными, потому что мы заходим на довольно сложную территорию. Если вам что-то непонятно, пишите комментарии под постом и в социальных сетях — буду рад и любым другим отзывам. Если вы более опытный в программировании человек, чем я, то с удовольствием выслушаю содержательную критику. Спасибо, и до следующего раза!

Читайте также:

  Полные курсы Python на Codeacademy и Treehouse*

* — платные курсы, но есть пробный период

  Развитие программистского мышления на Udacity

  Классы в Python на LearnPython.org и Python Course

исправление 11.08.2015: спасибо нашему читателю Никите Королькову, который обратил внимание, что в четвёртой снизу строке кода вместо двойных внешних кавычек стояли одинарные, из-за чего апостроф внутри фразы воспринимался как конец string.

Рассказать друзьям
6 комментариевпожаловаться

Комментарии

Подписаться
Комментарии загружаются
чтобы можно было оставлять комментарии.