Чтение онлайн

на главную - закладки

Жанры

Язык программирования Python
Шрифт:

Еще один способ получить объект некоторого типа — использование функций–фабрик. По синтаксису вызов функции–фабрики не отличается от вызова конструктора класса.

Определение класса

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

Листинг

from sets import Set as set # тип для множества

class G:

def __init__(self, V, E):

self.vertices = set(V)

self.edges = set(E)

def add_vertex(self, v):

self.vertices.add(v)

def add_edge(self, (v1, v2)):

self.vertices.add(v1)

self.vertices.add(v2)

self.edges.add((v1, v2))

def has_edge(self, (v1, v2)):

return (v1, v2) in self.edges

def __str__(self):

return "%s; %s» % (self.vertices, self.edges)

Использовать класс можно следующим образом:

Листинг

g = G([1, 2, 3, 4], [(1, 2), (2, 3), (2, 4)])

print g

g.add_vertex(5)

g.add_edge((5,6))

print g.has_edge((1,6))

print g

что даст в результате

Листинг

Set([1, 2, 3, 4]); Set([(2, 4), (1, 2), (2, 3)])

False

Set([1, 2, 3, 4, 5, 6]); Set([(2, 4), (1, 2), (5, 6), (2, 3)])

Как видно из предыдущего примера, определить класс не так уж сложно. Конструктор класса имеет специальное имя __init__. (Деструктор здесь не нужен, но он бы имел имя __del__.) Методы класса определяются в пространстве имен класса. В качестве первого формального аргумента метода принято использовать self. Кроме методов в объекте класса имеются два атрибута: vertices (вершины) и edges (ребра). Для представления объекта G в виде строки используется специальный метод __str__.

Принадлежность классу можно выяснить с помощью встроенной функции isinstance:

Листинг

print isinstance(g, G)

Инкапсуляция

Обычно считается, что без инкапсуляции невозможно представить себе ООП, что это ключевое понятие. История развития методологий программирования движима борьбой со сложностью разработки программного обеспечения. Сложность больших программных систем, в создании которых участвует сразу большое количество разработчиков, уменьшается, если на верхнем уровне не видно деталей реализации нижних уровней. Собственно, процедурный подход был первым шагом на этом пути. Под инкапсуляцией (incapsulation, что можно перевести по–разному, но на нужные ассоциации хорошо наводит слово «обволакивание») понимается сокрытие информации о внутреннем устройстве объекта, при котором работа с объектом может вестись только через его общедоступный (public) интерфейс. Таким образом, другие объекты не должны вмешиваться в «дела» объекта, кроме как используя вызовы методов.

В языке Python инкапсуляции не придается принципиального значения: ее соблюдение зависит от дисциплинированности программиста. В других языках программирования имеются определенные градации доступности методов объекта.

Доступ к свойствам

В языке Python не считается зазорным получить доступ к некоторому атрибуту (не методу) напрямую, если, конечно, этот атрибут описан в документации как часть интерфейса класса. Такие атрибуты называются свойствами (properties). В других языках программирования принято для доступа к свойствам создавать специальные методы (вместо того чтобы напрямую обращаться к общедоступным членам–данным). В Python достаточно использовать ссылку на атрибут, если свойство ни на что в объекте не влияет (то есть другие объекты могут его произвольно менять). Если же свойство менее тривиально и требует каких–то действий в самом объекте, его можно описать как свойство (пример взят из документации к Python):

Листинг

class C(object):

def getx(self): return self.__x

def setx(self, value): self.__x = value

def delx(self): del self.__x

x = property(getx, setx, delx, «I'm the 'x' property.»)

Синтаксически доступ к свойству x будет обычной ссылкой на атрибут:

Листинг

>>> c = C

>>> 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

Поделиться:
Популярные книги

Исправленному верить (сборник)

Перумов Ник
Фантастика:
научная фантастика
6.40
рейтинг книги
Исправленному верить (сборник)

Борис Березовский. Человек, проигравший войну

Бушков Александр Александрович
Документальная литература:
биографии и мемуары
прочая документальная литература
публицистика
4.00
рейтинг книги
Борис Березовский. Человек, проигравший войну

Второгодка. Книга 3. Ученье свет

Ромов Дмитрий
3. Второгодка
Фантастика:
городское фэнтези
сказочная фантастика
альтернативная история
5.00
рейтинг книги
Второгодка. Книга 3. Ученье свет

Социология

Гидденс Энтони
Научно-образовательная:
обществознание
5.00
рейтинг книги
Социология

Тайная доктрина. Том II

Блаватская Елена Петровна
4. Теософия
Религия и эзотерика:
эзотерика
6.60
рейтинг книги
Тайная доктрина. Том II

Призрак

Шатнер Уильям
Звездный путь
Фантастика:
эпическая фантастика
космическая фантастика
5.00
рейтинг книги
Призрак

Газлайтер. Том 38

Володин Григорий Григорьевич
38. История Телепата
Фантастика:
городское фэнтези
аниме
попаданцы
6.20
рейтинг книги
Газлайтер. Том 38

Том 6. Зарубежная литература и театр

Луначарский Анатолий Васильевич
6. Собрание сочинений в восьми томах
Документальная литература:
критика
5.00
рейтинг книги
Том 6. Зарубежная литература и театр

Том 5. Рудин. Повести и рассказы 1853-1857

Тургенев Иван Сергеевич
5. Собрание сочинений в двенадцати томах
Проза:
русская классическая проза
5.00
рейтинг книги
Том 5. Рудин. Повести и рассказы 1853-1857

Сердце Дракона. Том 10

Клеванский Кирилл Сергеевич
10. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.14
рейтинг книги
Сердце Дракона. Том 10

Сын Архидемона (Тетралогия)

Рудазов Александр
135. В одном томе
Фантастика:
фэнтези
8.07
рейтинг книги
Сын Архидемона (Тетралогия)

Ученик

Первухин Андрей Евгеньевич
1. Ученик
Фантастика:
фэнтези
6.27
рейтинг книги
Ученик

Фарамунд

Никитин Юрий Александрович
10. Трое из леса
Фантастика:
героическая фантастика
8.81
рейтинг книги
Фарамунд

Пламенев. Книга IX

Карелин Сергей Витальевич
9. Пламенев
Фантастика:
аниме
уся
сказочная фантастика
фэнтези
фантастика: прочее
5.00
рейтинг книги
Пламенев. Книга IX