- •ВВЕДЕНИЕ
- •1.1. Почему Python
- •1.2. Практические задания
- •Вопросы для самопроверки
- •2. ТИПЫ ДАННЫХ
- •2.1. Базовые типы данных в языке Python
- •2.1.3. Кортежи
- •2.1.4. Словари
- •2.1.5. Множества
- •2.1.6. Frozenset
- •2.1.7. Файлы
- •2.1.8. Генераторы
- •2.2. Практические задания
- •Вопросы для самопроверки
- •3. ФУНКЦИИ
- •3.1. Создание функции
- •3.2. Значения аргументов по умолчанию
- •3.3. Рекурсия
- •3.4. Лямбда-функции
- •3.5. Локальные и глобальные переменные
- •3.6. Практические задания
- •4.1. Декораторы
- •4.2. Итераторы и генераторы
- •5.2. Поле объекта класса
- •5.3. Добавление и удаление полей и методов
- •Вопросы для самопроверки
- •ЗАКЛЮЧЕНИЕ
Значение поля : Красный
Принадлежность : Класс MyClass Спрашивает Красный : Класс MyClass Спрашивает Зеленый : Здесь был Зеленый
Спрашивает Красный : Здесь могла быть Ваша реклама! Спрашивает Зеленый : здесь был Зеленый
Спрашивает Зеленый : Здесь могла быть Ваша реклама!
Ранее мы с помощью инструкции green.name считывали значение поля name, поэтому имеем некоторые основания рассчитывать на успех. Однако при выполнении команды print("Спрашивает Красный:", red.name) получаем в окне вывода сообщение Спрашивает Красный : Класс MyClass. То есть значение поля name, полученное по ссылке через экземпляр red не изменилось. Хотя при выполнении команды print ("Спрашивает Зеленый:" , green.name ) в окне вывода получаем вполне ожидаемое сообщение Спрашивает Зеленый: Здесь был Зеленый. Поворот событий достаточно неожиданный: пока мы через инструкцию green.name значение полю name не присваивали, значения выражений green.name и red.name совпадали, но после присваивания значения полю эти инструкции возвращают разные значения. Объяснение такое. При выполнении команды green.nаmе= "Здесь был Зеленый" на самом деле значение полю name класса MyClass не присваивается. Вместо этого создается поле с названием nare у экземпляра green, и этому полю присваивается значение "Здесь был Зеленый". И после этого каждый раз, когда мы будем использовать инструкцию green.name, она будет означать не поле name класса MyClass, а поле nare экземпляра green. Другими словами, поле name экземпляра green "перекрывает" поле nare класса MyClass. Но это только для экземпляра green. У экземпляра red поля name нет, поэтому инструкция red.name при считывании значения означает поле name класса MyClass.
При выполнении команды MyClass.nаmе= " Здесь могла быть Ваша реклама!" изменяется значение поля name класса MyClass. Поэтому когда в команде print ("Спрашивает Красный: ", red.name) используется ссылка red.name, то результатом этой инструкции будет новое значение поля name класса MyClass. А значение инструкции green.name в команде print ("Спрашивает Зеленый: " , green . name ) - это значение " Здесь был Зеленый " поля name экземпляра green.
На следующем этапе командой del(green.name) у экземпляра green удаляется поле name. После этого у экземпляра green поля name уже нет, и значением инструкции green.name в команде print("Спрашивает Зеленый : " , green.name ) является значение поля name класса MyClass.
5.3. Добавление и удаление полей и методов
После наших смелых экспериментов с полями объекта класса и экземпляров класса не сложно догадать, что поля можно добавлять и удалять,
52
причем это справедливо как для объекта класса, так и для экземпляров класса. Здесь мы обсудим и проанализируем две позиции:
Поля экземпляра класса можно добавлять и удалять после создания экземпляра класса.
Поля объекта класса можно добавлять и удалять после создания объекта класса.
С прикладной точки зрения ситуация в общем и целом несложная: для добавления поля экземпляра класса этому полю присваивается значение (разумеется, через ссылку на экземпляр класса). Примерно то же самое происходит при добавлении поля объекту класса: такому полю присваивается значение, и этого достаточно, чтобы у объекта класса появилось новое поле. Чтобы удалить поле у объекта класса, после оператора del указываем ссылку на поле объекта класса (в "точечном" формате: класс и, через точку, имя поля). Аналогичным образом удаляется и Поле экземпляра класса, только теперь после оператора del указывается ссылка на поле экземпляра класса (экземпляр класса, точки и имя поля).
Небольшой пример манипулирования с полями объекта класса и полями экземпляров класса приведен в листинге:
#Создаем класс class MyClass:
pass
#Создаем экземпляр А
A=MyClass()
#Создаем экземпляр В
B=MyClass()
#Экземпляру А добавляем
#поле first
А.first =" Экземпляр А "
#Экземпляру В добавляем
#поле seccond
В.second = " Экземпляр В "
#Классу MyClass добавляем
#поле total
MyClass.total= "Kлacc MyClass"
#Проверяем доступ к полям total и
#first через ссылку на экземпляр А print(А.total , " " , A.first )
#Проверяем доступ к полю second
#через ссылку на экземпляр А
try :
# Если Поле second есть print ( А.second )
# Ecли такого поля нет except AttributeError:
print ( "Taкoгo поля у экземпляра А нет ! " )
# Проверяем доступ к полям total и
53
# second через ссылку на экземпляр В print ( B.total, " " , B.second)
#Проверяем доступ к полю first
#через ссылку н а экземпляр В try:
#Если поле first есть
print(В.first )
#Если такого поля нет except AttributeError:
print ( " Taкoгo поля у экземпляра В нет ! " )
#Удаляем поле total класса MyClass del(MyClass.total)
#Проверяем доступ к полю total
#через ссылку на экземпляр А
try :
#Если поле есть print(A.total )
# Если поля нет except AttributeError:
print ( " Taкoгo поля нет ! " )
#Проверяем доступ к полю total
#через ссылку на экземпляр В try :
#Если поле есть
print (B.total)
#Если поля нет except AttributeError :
print ("Taкoгo поля нет!")
#Удаляем поле first экземпляра А del(A.first)
#Проверяем доступ к полю first
#через ссылку на экземпляр А try:
#Если поле есть
print (A.first)
# Если поля нет except AttributeError:
print ("Taкoгo поля у экземпляра А нет !")
Добавление и удаление полей
Результат выполнения программного кода такой:
Класс MyClass Экземпляр A
Такого поля у экземпляра А нет Класс MyClass Экземпляр B Такого поля у экземпляра в B нет
Такого поля нет! Такого поля нет!
54
Такого поля у экземпляра А нет!
В этом примере создается класс MyClass, не содержащий, собственно, ничего. На основе этого класса создаются два экземпляра с названиями А и B. Затем командам и А.first = "Экземпляр А", В.sесоnd= "Экземпляр В" и MyClass.total= "Kлacc MyClass" добавляются (с присваиванием значений) поля first для экземпляра А, поле second для экземпляра B и поле total для класса MyClass. В команде print (А.total , " " , А.first ) есть ссылки на поле first экземпляра класса и поле total объекта класса, причем обе ссылки выполняются через экземпляр А.
По результату выполнения команды видим, что проблем с доступом к полям не возникает. В принципе, нечто подобное мы наблюдали в предыдущих примерах, но здесь есть одна особенн6ость. Связана она с тем, что поле total появилось у класса MyClass уже после того, как были созданы экземпляры А и в. Но, тем не менее, доступ к добавленному полю total через экземпляры класса имеется. А вот добавление поля одному экземпляру класса для другого экземпляра "остается незамеченным" (что, в принципе, вполне логично).
При попытке выполнить команду print(А.second) возникает ошибка класса AttributeError: поля second у экземпляра А нет. Эту ситуацию мы обрабатываем с помощью блока try-except. Результатом является сообщение Такого поля у экземпляра А нет!, которое отображается командой print ("Такого поля у экземпляра А нет !") в ехсерt-блоке.
Аналогично обстоят дела с экземпляром B: доступ к полю total класса MyClass и полю second экземпляра через переменную В получаем без проблем, а к полю first экземпляра доступа нет, поскольку это поле добавлялось в экземпляр А, и экземпляр B к данному полю никакого отношения не имеет.
На следующем этапе командой del(MyClass.total) удаляем поле total объекта класса MyClass, после чего командой print(А.total) (в trу-блоке) пытаемся прочитать значение этого поля. Судя по тому, что в этом случае возникает ошибка класса At tributeError (неверный атрибут) и в ехсерt-блоке выполняется команда print ("Такого поля нет!"), поле total действительно удалено из объекта класса MyClass. Нет доступа к удаленному полю total и через переменную B.
Наконец, командой del(A.first) поле first экземпляра А. Как следствие, при попытке выполнить команду print (A . fir s t ) в t rу-блоке возникает ошибка. Поэтому в ехсерt-блоке выполняется команда print ("Такого поля у экземпляра А нет!").
5.4.Практические задания
1.Класс Дробное число со знаком (Fractions). Число должно быть представлено двумя полями: целая часть – длинное целое со знаком, дробная часть –беззнаковое короткое целое. Реализовать арифметические операции
55