- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Язык программирования Python - Роман Сузи
Шрифт:
Интервал:
Закладка:
>>> c.x = 1
>>> print c.x
1
>>> del c.x
А на самом деле будут вызываться соответствующие методы: setx(), getx(), delx().
Следует отметить, что в экземпляре класса в Python можно организовать доступ к любым (даже несуществующим) атрибутам, обрабатывая запрос на доступ к атрибуту группой специальных методов:
__getattr__(self, name) Этот метод объекта вызывается в том случае, если атрибут не найден другим способом (его нет в данном экземпляре или в дереве классов). Здесь name — имя атрибута. Метод должен вычислить значение атрибута либо возбудить исключение AttributeError. Для получения полного контроля над атрибутами в «новых» классах (то есть потомках object) используйте метод __getattribute__(). __setattr__(self, name, value) Этот метод вызывается при присваивании значения некоторому атрибуту. В отличие от __getattr__(), метод всегда вызывается, а не только тогда, когда атрибут может быть найден в экземпляре класса, поэтому нужно с осторожностью присваивать значения атрибутам внутри этого метода: это может вызвать рекурсию. Для присваивания значений атрибутов предпочтительнее присваивать словарю __dict__: self.__dict__[name] = value или (для «новых» классов) — обращение к __setattr__() базового класса: object.__setattr__(self, name, value). __delattr__(self, name) Как можно догадаться из названия, этот метод служит для удаления атрибута.Следующий небольшой пример демонстрирует все перечисленные моменты. В этом примере из словаря создается объект, именами атрибутов которого будут ключи словаря, а значениями — значения из словаря по заданным ключам:
class AttDict(object):
def __init__(self, dict=None):
object.__setattr__(self, '_selfdict', dict or {})
def __getattr__(self, name):
if self._selfdict.has_key(name):
return self._selfdict[name]
else:
raise AttributeError
def __setattr__(self, name, value):
if name[0] != '_':
self._selfdict[name] = value
else:
raise AttributeError
def __delattr__(self, name):
if name[0] != '_' and self._selfdict.has_key(name):
del self._selfdict[name]
ad = AttDict({'a': 1, 'b': 10, 'c': '123'})
print ad.a, ad.b, ad.c
ad.d = 512
print ad.d
Сокрытие данных
Подчеркивание ("_") в начале имени атрибута указывает на то, что он не входит в общедоступный интерфейс. Обычно применяется одиночное подчеркивание, которое в языке не играет особой роли, но как бы говорит программисту: «этот метод только для внутреннего использования». Двойное подчеркивание работает как указание на то, что атрибут — приватный. При этом атрибут все же доступен, но уже под другим именем, что и иллюстрируется ниже:
>>> class X:
... x = 0
... _x = 0
... __x = 0
...
>>> dir(X)
['_X__x', '__doc__', '__module__', '_x', 'x']
Полиморфизм
В переводе с греческого полиморфизм означает «многоформие». Так в информатике называют возможность использования одного имени для выполнения различных действий.
Можно встретить множество определений полиморфизма (также есть несколько видов полиморфизма) в зависимости от языка программирования. Как правило, в качестве примера проявления полиморфизма приводят переопределение методов в подклассах. При этом можно создать функцию, требующую формального аргумента — экземпляра базового класса, а в качестве фактического аргумента давать экземпляр подкласса. Функция будет вызывать метод объекта с именем, а за именем будут скрываться различные действия. В связи с этим полиморфизм обычно связывают с иерархией наследования.
В Python полиморфизм связан не с наследованием, а с набором и смыслом доступных методов в экземпляре класса. Ниже будет показано, что, имея определенные методы, можно воссоздать класс для строки или любого другого встроенного типа. Для этого необходимо определить свойственный типу набор методов. Конечно, нужный набор методов можно получить и с помощью наследования, но в Python это не только не обязательно, но иногда и противоречит здравому смыслу.
При написании функции в Python обычно не проверяется, к какому типу (классу) относится тот или иной аргумент: некоторые методы просто применяются к переданному объекту. Тем самым функции получаются максимально обобщенными: они не требуют от объектов–параметров большего, чем наличие методов с определенным именем, набором аргументов и семантикой.
Следующий пример показывает полиморфизм в том виде, в котором он свойственен Python:
def get_last(x):
return x[-1]
print get_last([1, 2, 3])
print get_last("abcd")
Описанной функции будет подходить в качестве аргумента все, от чего можно взять индекс–1 (последний элемент). Однако семантика «взятие последнего элемента» выполняется только для последовательностей. Функция будет работать и для словарей, но смысл при этом будет немного другой.
Имитация типов
Для иллюстрации понятия полиморфизма можно построить собственный тип, похожий на встроенный тип «функция». Построить класс, объекты которого вызываются подобно методам или функциям, можно так:
class CountArgs(object):
def __call__(self, *args, **kwargs):
return len(args) + len(kwargs)
cc = CountArgs()
print cc(1, 3, 4)
Как видно из этого примера, экземпляры класса CountArgs можно вызывать подобно функциям (в результате будет возвращено количество переданных параметров). При попытке вызова экземпляра на самом деле будет вызван метод __call__() со всеми аргументами.
Следующий пример показывает, что сравнением экземпляров класса тоже можно управлять:
class Point:
def __init__(self, x, y):
self.coord = (x, y)
def __nonzero__(self):
return self.coord[0] != 0 or self.coord[1] != 0
def __cmp__(self, p):
return cmp(self.coord, p.coord)
for x in range(-3, 4):
for y in range(-3, 4):
if Point(x, y) < Point(y, x):
print "*",
elif Point(x, y):
print ".",
else:
print "o",
Программа выведет:
. * * * * * *
. . * * * * *
. . . * * * *
. . . o * * *
. . . . . * *
. . . . . . *
. . . . . . .
В данной программе класс Point (Точка) имеет метод __nonzero__(), который определяет истинностное значение объекта класса. Истину будут давать только точки, отличные от (0, 0). Другой метод — __cmp__() — вызывается при необходимости сравнить точку и другой объект (имеющий, как и точка, атрибут coord, который содержит кортеж как минимум из двух элементов). Нужно заметить, что вместо __cmp__ можно определить отдельные методы для операций сравнения: __lt__, __le__, __ne__, __eq__, __ge__, __gt__ (для <, <=, !=, ==, >=, > соответственно).
Достаточно легко имитировать и числовые типы. Класс, который пользуется удобством синтаксиса инфиксного +, можно определить так:
class Plussable:
def __add__(self, x):
...
def __radd__(self, x):
...
def __iadd__(self, x):
...
Здесь метод __add__() вызывается, когда экземпляр класса Plussable стоит слева от сложения, __radd__() — если справа от сложения и метод слева от него не имеет метода __add__(). Метод __iadd__() нужен для реализации +=.
Отношения между классами
Наследование
На практике часто возникает ситуация, когда в предметной области выделены очень близкие, но вместе с тем неодинаковые классы. Одним из способов сокращения описания классов за счет использования их сходства является выстраивание классов в иерархию. В корне этой иерархии стоит базовый класс, от которого нижележащие классы иерархии наследуют свои атрибуты, уточняя и расширяя поведение вышележащего класса. Обычно принципом построения классификации является отношение «IS–A» («ЕСТЬ»). Например, класс Окружность в программе — графическом редакторе может быть унаследован от класса Геометрическая Фигура. При этом Окружность будет являться подклассом (или субклассом) для класса Геометрическая Фигура, а Геометрическая Фигура — надклассом (или суперклассом) для класса Окружность.
В языке Python во главе иерархии («новых») классов стоит класс object. Для ориентации в иерархии существуют некоторые встроенные функции, которые будут рассмотрены ниже. Функция issubclass(x, y) может сказать, является ли класс x подклассом класса y: