Классы в Python

From Викижурнал
Jump to: navigation, search
Классы в Python
Классы в Python
Портал ПрограммистовПортал Python

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

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

Понимание объектно-ориентированного программирования помогает глубже понять процесс создания программ, игр, приложений. Знание логики поможет писать программы, которые эффективно решают практически любые проблемы, с которыми вы сталкиваетесь. Классы также облегчают жизнь вам и другим программистам, с которыми вам придется работать, когда вы решаете все более сложные задачи. Когда вы и другие программисты пишете код, основанный на одной и той же логике, вы сможете понять работу друг друга.

Создание и использование классов

При помощи классов можно моделировать почти все. Давайте начнем с написания простого класса "Dog", который представит объект или шаблон собаки. Используя этот класс, шаблон можно организовать создание других объектов "собаки" на основе такого шаблона. Прежде чем создать класс, нужно понять, какими параметрами или свойствами обладают собаки? Так, у них всех есть имя и возраст. Мы также знаем, что большинство собак могут исполнять команды "сидеть" или "переворачиваться". Эти части данных (имя и возраст) и эти два поведения ("сидеть" и "переворачиваться") войдут в наш класс "Dog", потому что они являются общими для большинства собак. После написания нашего класса мы будем использовать его для создания отдельных экземпляров, каждый из которых представляет одну конкретную собаку.

Пример создания простого класса

Каждый экземпляр, созданный из класса Dog, будет хранить имя и возраст, и мы дадим каждой собаке выполнять действия sit() и roll_over():

class Dog:
    """A simple attempt to model a dog."""
    def __init__(self, name, age):
        """Initialise name and age attributes."""
        self.name = name.title()
        self.age = age

    def sit(self):
        """Simulate a dog sitting in response to a command."""
        print(self.name + " is now sitting.")

    def roll_over(self):
        """Simulate rolling over in response to a command."""
        print(self.name + " rolled over!")

Код сначала может казаться непонятным, но мы сейчас всё поясним. Такая стандартная структура будет использоваться достаточно часто, поэтому нужно привыкнуть к ней. И так, в самом начале мы определяем класс с именем "Dog". Так принято в Python, что все классы начинаются с заглавной буквы. Затем в тройных кавычках можно комментировать, что означает последующий код, так как это информация будет включена в документацию к программе для тех, кто может работать с кодом в последующем.

Метод __init__()

Функция, которая является частью класса, называется методом. Все, что вы узнали о функциях, относится и к методам; единственное практическое отличие на данный момент - это то, как мы будем вызывать методы. __init __() в коде - это специальный метод, который Python запускает автоматически всякий раз, когда мы создаем новый экземпляр на основе класса "Dog". Этот метод выделяется двойными подчёркиваниями.

Мы определяем метод __init __() для трех параметров: "self", "name" и "age". Параметр "self" является обязательным в определении метода и должен предшествовать другим параметрам. Он должен быть включен в определение, потому что когда Python позже вызывает этот метод __init __() (для создания экземпляра "Dog"), вызов метода автоматически передаст аргумент "self". Каждый вызов метода, связанный с классом, автоматически передает себя, что является ссылкой на сам экземпляр; он дает экземпляру доступ к атрибутам и методам в классе. Когда мы создаем экземпляр "Dog", Python вызывает метод __init __() из класса Dog. Мы передадим классу Dog() имя и возраст в качестве аргументов; "self" передается автоматически, поэтому нам не нужно его передавать. Всякий раз, когда мы хотим создать экземпляр из класса "Dog", мы предоставим значения для двух параметров - имени и возраста.

Две переменные, написанные в коде, имеют префикс "self". Любая переменная с префиксом "self" доступна каждому методу в классе, и мы также сможем получить доступ к этим переменным через любой экземпляр, созданный из класса. "self.name = name.title()" принимает значение, сохраненное в имени параметра, и сохраняет его в имени переменной, которая затем присоединяется к создаваемому экземпляру. При этом мы используем функцию title(), которая выводит все значения в переменной с заглавной буквы. Тот же процесс происходит с "self.age = age". Переменные, доступные через такие экземпляры, называются атрибутами.

Класс "Dog" имеет два других метода в нашем примере: sit() и roll_over(). Так как эти методы не нуждаются в дополнительной информации, такие как имя или возраст, мы просто определяем их как один параметр - self. Экземпляры, которые мы создадим позже, будут иметь доступ к этим методам. Другими словами, мы присваиваем объекту действия для собаки: садиться и переворачиваться. В данном примере методы sit() и roll_over() просто выводят сообщение о том, что собака села или переворачивается. Имейте в виду, что концепция может быть расширена до реалистичных ситуаций: если бы этот класс был частью реальной компьютерной игры, эти методы содержали бы код, заставляющий анимированную собаку садиться и переворачиваться.

Создание экземпляра из класса

Думайте о классе как о наборе инструкций о том, как создать экземпляр. Класс Dog - это набор инструкций, который сообщает Python, как создавать отдельные экземпляры, представляющие конкретных собак Давайте сделаем пример, представляющий конкретную собаку. После кода определяющий класс "Dog" вносим следующий код:

my_dog = Dog('willie', 6)
print("My dog's name is " + my_dog.name + ".")
print("My dog is " + str(my_dog.age) + " years old.")

Класс "Dog", который мы здесь используем, - это тот, который мы только что написали в предыдущем примере. Сначала мы сообщаем Python создать собаку с именем "willie" и возрастом 6 лет. Когда Python читает эту строку, он вызывает метод __init __() в "Dog" с аргументами "willie" и "6". Метод __init __() создает экземпляр, представляющий эту конкретную собаку и устанавливающий атрибуты имени и возраста с использованием предоставленных нами значений. Метод __init __ () не имеет явного оператора return, но Python автоматически возвращает экземпляр, представляющий эту собаку. Мы храним этот экземпляр в переменной "my_dog". В нашем примере название заглавное "Dog", относится к классу, а строчное имя, например, "my_dog", относится к одному экземпляру, созданному из класса.

Доступ к атрибутам

Для доступа к атрибутам экземпляра используется точечная запись. Так в коде мы получаем доступ к значению имени атрибута "my_dog", написав:

my_dog.name

Точечная нотация часто используется в Python. Этот синтаксис демонстрирует, как Python находит значение атрибута. Здесь Python использует экземпляр "my_dog" и затем находит атрибут "name", связанное с "my_dog". Это тот же атрибут, который называется "self.name" в классе "Dog". Затем в коде мы используем такой же подход для работы с атрибутом "age" (возраст). Во втором выводе значение атрибута "my_dog.age" преобразует значение в строку. Вывод представляет собой сводку того, что мы знаем о "my_dog":

My dog's name is Willie.
My dog is 6 years old.

Вызов методов

После того, как мы создаем экземпляр из класса "Dog", мы можем использовать точечную запись для вызова любого метода, созданного в этом классе. Давайте заставим условно нашу собаку сесть и перевернуться:

my_dog = Dog('willie', 6)
my_dog.sit()
my_dog.roll_over()

Чтобы вызвать метод, нужно задать названия экземпляра (в данном случае "my_dog") и метод, который вы хотите вызвать, через точку. Когда Python читает "my_dog.sit()", он ищет метод sit() в классе "Dog" и запускает этот код. Python интерпретирует строку "my_dog.roll_over()" таким же образом. Теперь наша виртуальная собака делает то, что мы сообщаем ей:

Willie is now sitting.
Willie rolled over!

Такой синтаксис довольно полезен. Когда атрибутам и методам присвоены соответствующие описательные имена, такие как "name", "age", "sit()" и "roll_over()", мы можем легко определить, что должен делать блок кода.

Создание нескольких экземпляров

Вы можете создать столько экземпляров из класса, сколько нужно. Давайте создадим вторую собаку с именем "your_dog":

my_dog = Dog('willie', 6)
your_dog = Dog('lucy', 3)

print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old.")
print("\nYour dog's name is " + your_dog.name.title() + ".")
print("Your dog is " + str(your_dog.age) + " years old.")
your_dog.sit()
my_dog.sit()

В этом примере мы создаем собаку по имени "Willie" и собаку по имени "Lucy". Каждая собака - это отдельный экземпляр со своим набором атрибутов, способный выполнять один и тот же набор действий:

My dog's name is Willie.
My dog is 6 years old.
Willie is now sitting.

Your dog's name is Lucy.
Your dog is 3 years old.
Lucy is now sitting.

Даже если бы мы использовали то же имя и возраст для второй собаки, Python все равно создал бы отдельный экземпляр из класса "Dog". Можно создать столько экземпляров из одного класса, сколько нужно, при условии, что даете каждому экземпляру уникальное имя переменной или оно занимает уникальное место в списке или словаре.

Работа с классами и экземплярами

Можно использовать классы для моделирования многих реальных ситуаций. После написания класса вы будете проводить большую часть времени, работая с экземплярами, созданными из этого класса. Одна из первых задач, которую нужно будет выполнить, - изменить атрибуты, связанные с конкретным экземпляром. Можно изменить атрибуты экземпляра напрямую или написать методы, которые обновляют атрибуты определенным образом.

Класс автомобиля

Давайте напишем новый класс, представляющий автомобиль. Наш класс будет хранить информацию о типе автомобиля, с которым мы работаем, и у него будет метод, который сообщает эту информацию:

сlass Car():
    """A simple attempt to represent a car."""
    def __init__(self, make, model, year):
    """Initialize attributes to describe a car."""
    self.make = make
    self.model = model
    self.year = year

    def get_descriptive_name(self):
    """Return a neatly formatted descriptive name."""
    long_name = str(self.year) + ' ' + self.make + ' ' + self.model
    return long_name.title()

my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())

В начале класса "Car" мы сначала определяем метод __init __() с параметром self, как мы делали это раньше с нашим классом "Dog". Затем этому классу задаём три других параметра: марка, модель и год автомобиля. Метод __init __() принимает эти параметры и сохраняет их в атрибутах, которые будут связаны с экземплярами, созданными из этого класса. Когда мы создаем новый экземпляр "Car", нам нужно указать марку, модель и год для нашего автомобиля.

Затем мы определяем метод get_descriptive_name(), который помещает год, марку и модель автомобиля в одну строку, описывающий автомобиль. Это избавит нас от необходимости печатать значение каждого атрибута отдельно. Для работы со значениями атрибутов в этом методе мы используем self.make, self.model и self.year. Потом создаём экземпляр из класса "Car" и сохраняем его в переменной "my_new_car". Затем мы вызываем get_descriptive_name(), чтобы показать, какая у нас машина:

2016 Audi A4

Чтобы сделать класс более интересным, давайте добавим атрибут, который меняется со временем. Мы добавим атрибут, который хранит общий пробег автомобиля.

Установка значения по умолчанию для атрибута

Каждому атрибуту в классе необходимо задать начальное значение, даже если это значение равно 0 или пустой строке. В некоторых случаях, например при установке значения по умолчанию, имеет смысл указать начальное значение в теле метода "__init __()"; если вы делаете это для атрибута, вам не нужно включать параметр для этого атрибута.

Давайте добавим атрибут с именем "odometer_reading", который всегда имеет значение "0". Мы также добавим метод "read_odometer()", который поможет считывать значения счётчика каждого автомобиля:

class Car():
    def __init__(self, make, model, year):
        """Initialize attributes to describe a car."""
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0

    def get_descriptive_name(self):
        --snip--

    def read_odometer(self):
        """Print a statement showing the car's mileage."""
        print("This car has " + str(self.odometer_reading) + " miles on it.")

my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()

На этот раз, когда Python вызывает метод __init __() для создания нового экземпляра, он сохраняет значения "make", "model" и "year" в виде таких атрибутов, как это было в предыдущем примере. Затем Python создает новый атрибут с именем "odometer_reading" и устанавливает его начальное значение равным "0". У нас также есть новый метод "read_odometer()", который облегчает считывание пробега автомобиля. Так пробег нашего виртуального автомобиля равняется нулю:

2016 Audi A4
This car has 0 miles on it.

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

Изменение значений атрибутов

Можно изменить значение атрибута тремя способами: вы можете изменить значение непосредственно через экземпляр, установить значение с помощью метода или увеличить значение (добавить к нему определенное число) с помощью метода. Давайте посмотрим на каждый из этих подходов.

Прямое изменение значения атрибута

Самый простой способ изменить значение атрибута - получить доступ к атрибуту напрямую через экземпляр. Здесь мы устанавливаем показания счётчика на 23:

class Car():
    --snip--

my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())

my_new_car.odometer_reading = 23
my_new_car.read_odometer()

Сначала используем используем запись через точку, чтобы получить доступ к атрибуту "odometer_reading" нашего виртуального автомобиля и установить его значение напрямую. Эта строка сообщает Python взять экземпляр "my_new_car", найти связанный с ним атрибут "odometer_reading" и установить значение этого атрибута равным "23":

2016 Audi A4
This car has 23 miles on it.

Иногда необходимо получить доступ к атрибутам напрямую, но иногда нужно написать метод, который обновит это значение.

Изменение значения атрибута с помощью метода
Editarticle.png

Данная статья находится в стадии доработки.

  • Автор статьи работает над завершением этой статьи.
  • {{{описание3}}}

Другие статьи о Python