Файл: Объектноориентированное программирование на Python.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 10.04.2024

Просмотров: 34

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

В случае классов используется особая терминология. Пусть имена, определенные в классе, называются атрибутами этого класса. В примере имена n и adder – это атрибуты класса B. Атрибуты-переменные часто называют полями или свойствами (в других языках понятия "поле" и "свойство" не совсем одно и то же). Полем является n. Атрибуты-функции называются методами. Методом в классе B является adder. Количество свойств и методов в классе может быть любым.

Переменные класса и объекта


Данные, т.е. поля, являются не чем иным, как обычными переменными, заключёнными в пространствах имён классов и объектов. Это означает, что их имена действительны только в контексте этих классов или объектов. Отсюда и название “пространство имён”.

Существует два типа полей: переменные класса (рассмотрели выше) и переменные объекта, которые различаются в зависимости от того, принадлежит ли переменная классу или объекту соответственно.
Переменные класса разделяемы – доступ к ним могут получать все экземпляры этого класса. Переменная класса существует только одна, поэтому когда любой из объектов изменяет переменную класса, это изменение отразится и во всех остальных экземплярах того же класса.
Переменные объекта принадлежат каждому отдельному экземпляру класса. В этом случае у каждого объекта есть своя собственная копия поля, т.е. не разделяемая и никоим образом не связанная с другими такими же полями в других экземплярах. Это легко понять на примере (сохраните как objvar.py):


class Robot:
'''Представляет робота с именем.'''
# Переменная класса, содержащая количество роботов
population = 0

def __init__(self, name):
'''Инициализация данных.'''
self.name = name
print('(Инициализация {0})'.format(self.name))

# При создании этой личности, робот добавляется
# к переменной 'population'
Robot.population += 1

def __del__(self):
'''Я умираю.'''
print('{0} уничтожается!'.format(self.name))

Robot.population -= 1

if Robot.population == 0:
print('{0} был последним.'.format(self.name))
else:
print('Осталось {0:d} работающих роботов.'.format(Robot.population))

def sayHi(self):
'''Приветствие робота.

Да, они это могут.'''
print('Приветствую! Мои хозяева называют меня {0}.'.format(self.name))

def howMany():
'''Выводит численность роботов.'''
print('У нас {0:d} роботов.'.format(Robot.population))

howMany = staticmethod(howMany)

droid1 = Robot('R2-D2')
droid1.sayHi()
Robot.howMany()

droid2 = Robot('C-3PO')
droid2.sayHi()
Robot.howMany()

print("\nЗдесь роботы могут проделать какую-то работу.\n")

print("Роботы закончили свою работу. Давайте уничтожим их.")
del droid1
del droid2

Robot.howMany()



Вывод:

$ python3 objvar.py

(Инициализация R2-D2)

Приветствую! Мои хозяева называют меня R2-D2.

У нас 1 роботов.

(Инициализация C-3PO)

Приветствую! Мои хозяева называют меня C-3PO.

У нас 2 роботов.
Здесь роботы могут проделать какую-то работу.
Роботы закончили свою работу. Давайте уничтожим их.

R2-D2 уничтожается!

Осталось 1 работающих роботов.

C-3PO уничтожается!

C-3PO был последним.

У нас 0 роботов.
Как это работает:

Это длинный пример, но он помогает продемонстрировать природу переменных класса и объекта. Здесь population принадлежит классу Robot, и поэтому является переменной класса. Переменная name принадлежит объекту (ей присваивается значение при помощи self), и поэтому является переменной объекта.

Таким образом, мы обращаемся к переменной класса population как Robot.population, а не self.population. К переменной же объекта name во всех методах этого объекта мы обращаемся при помощи обозначения self.name. Помните об этой простой разнице между переменными класса и объекта. Также имейте в виду, что переменная объекта с тем же именем, что и переменная класса, сделает недоступной (“спрячет”) переменную класса!

Метод howMany принадлежит классу, а не объекту.
Примечание:

В этом примере мы также наблюдали применение строк документации для классов, равно как и для методов. Во время выполнения мы можем обращаться к строке документации класса при помощи Robot.__doc__, а к строке документации метода – при помощи Robot.sayHi.__doc__.

Динамическое изменение (не рекомендуется использовать)



Классы в Python могут динамически изменяться после определения:

class SomeClass(object):
# пустой класс
pass

a = SomeClass()
b = SomeClass()
a.arg = 1 # у экземпляра a появился атрибут arg, равный 1
b.arg = 2 # а у экземпляра b - атрибут arg, равный 2
print(a.arg)
print(b.arg)
c = A()
print(c.arg) # а у этого экземпляра нет arg


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

При вызове метода экземпляра класса, ссылка на экземпляр передается первым аргументом. При этом, экземпляр передается неявно, но параметр надо указывать явно.

Практическая работа “Игра воин”:


Напишите программу по следующему описанию. Есть класс "Воин". От него создаются два экземпляра-юнита. Каждому устанавливается здоровье в 100 очков. В случайном порядке они бьют друг друга. Тот, кто бьет, здоровья не теряет. У того, кого бьют, оно уменьшается на 20 очков от одного удара. После каждого удара надо выводить сообщение, какой юнит атаковал, и сколько у противника осталось здоровья. Как только у кого-то заканчивается ресурс здоровья, программа завершается сообщением о том, кто одержал победу.