Главная страница

Проектирование АИС. С аратовский госуниверситет м еханико математический факультет проектирование информационных систем Составил


Скачать 3.17 Mb.
НазваниеС аратовский госуниверситет м еханико математический факультет проектирование информационных систем Составил
АнкорПроектирование АИС.pdf
Дата05.03.2018
Размер3.17 Mb.
Формат файлаpdf
Имя файлаПроектирование АИС.pdf
ТипКонтрольные вопросы
#16260
страница2 из 22
1   2   3   4   5   6   7   8   9   ...   22
code
— код сотрудника, это необходимо при одинаковых “ФИО” сотрудников или, например, при изменении фамилии сотрудника;
family
— фамилия;
name
— имя;
patronym
— отчество.
Операции класса это:
__init__
— конструктор класса, в данном случае он необходим поскольку его атрибуты нужно инициализировать;
__hash__
— определение этой функции позволяет использовать объект класса в качестве элемента словарей и множеств;
__eq__
— поскольку хэш представляет отображение элементов некоторого множества в конечное множество чисел, обычно это числа умещающиеся в машинное слово, то необходимо разрешать так называемые коллизии. В случае коллизии два разных объекта имеют одинаковое значение функции __hash__ и __eq__ позволяет различить эти объекты.
Подразделения представлены классом Subdivision, который имеет следующие атрибуты:
name
— название подразделения;
collaborators
множество его сотрудников;

subdivisions
— множество его собственных подразделений.
Операции класса это также состоят из конструктора, операций __hash__ и __eq__ поскольку под- разделение может быть в качестве элемента множества subdivisions, а также других операций:
__iter__
— итератор для просмотра всех сотрудников подразделения, включая и сотрудников его собственных подразделений;
add
— для добавления сотрудника к подразделению;
addSubdivision
— для добавления к подразделению другого подразделения в качестве его собствен- ного подразделения;
iterSubdivision
— итератор для просмотра его собственных подразделений.
Оставшиеся элементы диаграммы классов могут быть описаны кратко. TelephoneType определяется своим названием. TelephoneTypes представляет собой множество из объектов класса TelephoneType.
Класс Telephone состоит из номера и его типа. Телефоны содержаться в множестве задаваемым классом Telephones. Телефонный справочник содержит TelephoneRecord ссылающийся на телефоны и подразделения.
Рассмотрим реализацию телефонного справочника
. Для усвоения использованного ниже мате- риала необходимо усвоить 1-4 лекции курса “Учебный курс - Язык программирования Python” [
10
]
Сузи Романа Арвиевича.
1
# -*- coding: utf-8 -*-
2 3
"""

4
Телефонная книга организации
5
"""
6 7
import itertools
8 9
class Collaborator:
10
"""
11
Сотрудник
12
"""
13
def
__init__
(self, code, family, name, patronym):
14
self.code = code
15
self.family = family
16
self.name = name
17
self.patronym = patronym
18 19
def
__str__
(self):
20
return
"%s %.2s. %.2s."
% (self.family, self.name, self.patronym)
21 22
def
__hash__
(self):
23
return
hash
(self.code)
24 25
def
__eq__
(self, other):
26
return self.code == other.code
Строка 1 определяет используемую кодировку. Затем, нам строках 3-5, определяем документацию нашей программы. На 7 строке импортируем модуль itertools для организации итераторов для обхода подразделения по его сотрудникам и по его собственным подразделениям. Далее следует описание
класса Collaborator. При вычисление хэш используется стандартная hash функция языка Python.
28
class Subdivision:
29
"""
30
Подразделение
31
"""
32
def
__init__
(self, name):
33
self.name = name
34
self.collaborators =
set
()
35
self.subdivisions =
set
()
36 37
def
__hash__
(self):
38
return
hash
(self.name)
39 40
def
__eq__
(self, other):
41
return self.name == other.name
42 43
def
__iter__
(self):
44
i =
iter
(self.collaborators)
45
for s in self.subdivisions:
46
i = itertools.
chain
(i,
iter
(s))
47
return i
48 49
def
add
(self, collaborator):
50
assert collaborator not in self
51
self.collaborators.
add
(collaborator)
52

53
def
addSubdivision
(self, subdivision):
54
assert subdivision not in self.subdivisions
55
assert not
set
(self).
intersection
(
set
(subdivision))
56
self.subdivisions.
add
(subdivision)
57 58
def
iterSubdivision
(self):
59
i =
iter
(self.subdivisions)
60
for s in self.subdivisions:
61
i = itertools.
chain
(i, s.
iterSubdivision
())
62
return i
В Subdivision для организации итераторов __iter__ и iterSubdivision используется так называемое за- цепление итераторов. Операция add на строчке 50 запрещает добавлять сотрудника к подразделению если он есть в нем или в его собственном подразделении. Это достигается за счет переопределе- ния стандартного метода __iter__ для контейнера языка Python. Строчка 54 запрещает добавлять подразделение если там оно уже есть, а строчка 55 если в нем есть хотя бы один сотрудник уже имеющиеся в нашем подразделении.
64
class TelephoneType:
65
"""
66
Тип телефона
67
"""
68
def
__init__
(self, name):
69
self.name = name
70 71
def
__hash__
(self):
72
return
hash
(self.name)

73 74
def
__eq__
(self, other):
75
return self.name == other.name
Тип телефона определяется его именем.
77
class
TelephoneTypes
(
set
):
78
"""
79
Типы телефонов
80
"""
81
def
add
(self, telephoneType):
82
assert telephoneType not in self
83
set add
(self, telephoneType)
На строке 82 стоит запрет на добавление к множеству типов телефонов элемента если он там уже есть.
85
class Telephone:
86
"""
87
Телефон
88
"""
89
def
__init__
(self, telephone, telephoneType):
90
self.number = telephone
91
self.
type
= telephoneType
92 93
def
__hash__
(self):
94
return
hash
(self.number)
95

96
def
__eq__
(self, other):
97
return self.number == other.number
Телефон определяется его типом и номером.
99
class
Telephones
(
set
):
100
"""
101
Телефоны
102
"""
103
def
__init__
(self, telephoneTypes):
104
set
__init__
(self)
105
self.telephoneTypes = telephoneTypes
106 107
def
add
(self, telephone):
108
assert telephone not in self
109
assert telephone.
type
in self.telephoneTypes
110
set add
(self, telephone)
На строке 108 стоит запрет на добавление к множеству телефонов элемента с уже существующим номером или и на строке 109 если его типа нет в telephoneTypes.
112
class TelephoneRecord:
113
"""
114
Запись в телефонном справочнике
115
"""
116
def
__init__
(self, telephone, collaborator):
117
self.telephone = telephone
118
self.collaborator = collaborator

119 120
def
__hash__
(self):
121
return
hash
((self.telephone, self.collaborator))
122 123
def
__eq__
(self, other):
124
return self.telephone == other.telephone and \
125
self.collaborator == other.collaborator
Запись в телефонном справочнике должна ссылаться на телефон и сотрудника.
127
class
TelephoneDir
(
set
):
128
"""
129
Телефонный справочник
130
"""
131
def
__init__
(self, telephones, subdivision):
132
set
__init__
(self)
133
self.telephones = telephones
134
self.subdivision = subdivision
135 136
def
add
(self, telephoneRecord):
137
assert telephoneRecord.telephone in self.telephones
138
assert telephoneRecord.collaborator in self.subdivision
139
assert telephoneRecord not in self
140
set add
(self, telephoneRecord)
На строке 137 стоит запрет на добавление к множеству телефона, если его нет среди телефонов справочника. Аналогично, на строке 138, запрет для подразделений. Строка 139 запрещает добавлять записи в телефонный справочник, если они уже там есть.

142
if __name__ ==
’__main__’
:
143
import tdcsv
144 145
telephoneDir = tdcsv.
load
()
146 147
for s in telephoneDir.subdivision.
iterSubdivision
():
148
if s.name ==
’помощник проректора’
:
149
for r in telephoneDir:
150
if r.collaborator in s and r.collaborator.family.
find
(
’ск’
)
>=
0
:
151
print r.telephone.number,
"%s %s. %s."
%
\
152
(r.collaborator.family, r.collaborator.name[:
2
],
r.collaborator.patronym[:
2
])
153
break
154 155
for s in telephoneDir.subdivision.
iterSubdivision
():
156
if s.name ==
’зав. кафедрой’
:
157
for r in telephoneDir:
158
if r.collaborator in s and r.collaborator.family.
find
(
’сс’
)
>=
0
:
159
print r.telephone.number,
"%s %s. %s."
%
\
160
(r.collaborator.family, r.collaborator.name[:
2
],
r.collaborator.patronym[:
2
])
161
break
Каждый модуль языка Python может быть использован в качестве головного, в этом случае значение переменной __name__ будет иметь значение ’__main__’ (см. строку 142).
На 143 строке подключаем модуль импорта данных из формата CSV, а на 145 осуществляется сам импорт.

На строчках 147–153 осуществляется поиск в подразделении помощник проректора сотрудника,
фамилия которого содержит ск.
На строчках 155–161 осуществляется поиск, аналогичный предыдущему, в подразделении зав.
кафедрой сотрудника, фамилия которого содержит сс.
Результат работы программы представлен ниже.
51-57-39 Виноградский С. Г.
51-18-84 Лосатинская А. С.
В результате первый запрос вернул два телефона, а второй не одного.
CSV
Для усвоения материала необходимо ознакомится с 7 курса “Учебный курс - Язык программирования
Python” [
10
] Сузи Романа Арвиевича.
Для представления информации используется два файла subdivision.csv и ssu.csv со струк- турой колонок представленных на рисунке ниже.
subdivision подразделение головное подразделение ssu телефон код сотр.
фамилия имя отчество подразделение тип тел.

Для набора можно воспользоваться любым текстовым редактором поддерживающим кодировку
UTF8 или экспортом из электронных таблиц.
Сначала опишем функцию load из файла tdcsv.py для загрузки данных из формата CSV.
30
def
load
():
31
subdivision = {}
32
for rec in csv.
reader
(
open
(os.path.
join
(os.curdir,
’subdivision.csv’
),
’rb’
), delimiter=
’;’
):
33
subdivision[rec[
0
]] = telephonedir.
Subdivision
(rec[
0
])
34
if rec[
1
]:
35
subdivision[rec[
1
]].
addSubdivision
(subdivision[rec[
0
]])
36
else:
37
telephoneDir =
telephonedir.
TelephoneDir
(telephonedir.
Telephones
(telephonedir.
TelephoneTypes
()),
subdivision[rec[
0
]])
38 39
telephones, telephoneTypes, collaborators = {}, {}, {}
40
for rec in csv.
reader
(
open
(os.path.
join
(os.curdir,
’ssu.csv’
),
’rb’
),
delimiter=
’;’
):
41
if rec[
6
]
not in telephoneTypes:
42
telephoneTypes[rec[
6
]] = telephonedir.
TelephoneType
(rec[
6
])
43
telephoneDir.telephones.telephoneTypes.
add
(telephoneTypes[rec[
6
]])
44
if rec[
0
]
not in telephones:
45
telephones[rec[
0
]] = telephonedir.
Telephone
(rec[
0
],
telephoneTypes[rec[
6
]])
46
telephoneDir.telephones.
add
(telephones[rec[
0
]])
47
key =
int
(rec[
1
])

48
if key not in collaborators:
49
collaborators[key] = telephonedir.
Collaborator
(key, rec[
2
], rec[
3
],
rec[
4
])
50
subdivision[rec[
5
]].
add
(collaborators[key])
51
telephoneDir.
add
(telephonedir.
TelephoneRecord
(telephones[rec[
0
]],
collaborators[key]))
52 53
return telephoneDir
Словарь subdivision на строке 31 будем использовать для хранения объектов – подразделений, читае- мых из файла ’subdivision.csv’
. Аналогично на строке 39 организовано чтение из файла ’ssu.csv’
Окончательно функция возвращает заполненный телефонный справочник. Функция save сохраняет данные в эти же файлы.
База данных
Структура базы данных представлена ниже

Т елефоновТ ипы кодТелефонаТип название
Подразделения кодПодразделения название кодГоловногоПодраз
Т елефоны кодТелефона кодТелефонаТип номер
Т елефонныйСправочник кодЗаписи кодТелефона кодСотрудника
Сот рудники кодСотрудника кодПодразделения фамилия имя отчество
Для создания таблиц используется следующий SQL код для базы данных Postgresql из файла telephonedir.sql
1
CREATE TABLE Подразделения (
2
кодПодразделения
SERIAL
PRIMARY KEY,
3
название
TEXT,
4
кодГоловногоПодраз
INTEGER
REFERENCES Подразделения(кодПодразделения)
DEFAULT NULL,
5
UNIQUE(название, кодГоловногоПодраз)
6
);
7

8
CREATE TABLE Сотрудники (
9
кодСотрудника
INTEGER
PRIMARY KEY,
10
кодПодразделения
INTEGER
REFERENCES Подразделения(кодПодразделения)
DEFAULT NULL,
11
фамилия
TEXT,
12
имя
TEXT,
13
отчество
TEXT
14
);
15 16
CREATE TABLE ТелефоновТипы (
17
кодТелефонаТип SERIAL
PRIMARY KEY,
18
название
TEXT,
19
UNIQUE(название)
20
);
21 22
CREATE TABLE Телефоны (
23
кодТелефона
SERIAL
PRIMARY KEY ,
24
кодТелефонаТип
INTEGER
REFERENCES ТелефоновТипы(кодТелефонаТип),
25
номер
TEXT
26
);
27 28
CREATE TABLE ТелефонныйСправочник (
29
кодЗаписи
SERIAL
PRIMARY KEY,
30
кодТелефона
INTEGER
REFERENCES Телефоны(кодТелефона),
31
кодСотрудника
INTEGER
REFERENCES Сотрудники(кодСотрудника),
32
UNIQUE(кодТелефона, кодСотрудника)
33
);

С помощью скрипта create-db написанного на языке BASH создается база данных telephonedir1
со структурой таблиц задаваемых представленным выше SQL кодом.
Набор данных можно осуществить с помощью knoda – графического интерфейса пользователя для доступа к базам данных.
С помощью скриптов dump можно сохранить базу данных в файле dump.tar
, а с помощью restore её восстановить.
Для усвоения материала необходимо ознакомится с 10 лекцией “Учебный курс - Язык программи- рования Python” [
10
] Сузи Романа Арвиевича.
Для работы с Postgresql на строке 3 файла tddb.py подключим модуль psycopg2. На строке 7
создается соединение с базой данных, а на строке 13 закрытие этого соединения.
1
# -*- coding: utf-8 -*-
2 3
import psycopg2 as db
4 5
import telephonedir
6 7
def
createConn
():
8
conn = db.
connect
(host=
’localhost’
, database=
"telephonedir1"
,
user=
"postgres"
)
9
db.threadsafety=
2 10
curs = conn.
cursor
()
11
return (db, conn, curs)
12

13
def
closeConn
(db, conn, curs):
14
conn.
close
()
На строке 87 выполняется запрос в базе данных. В цикле for на строке 88 выполняется его просмотр. Заметим, что модуль psycopg2 поддерживает спецификацию DBI-2.0 и поэтому кортеж rec содержит элементы преобразованные из базы данных согласно их типам. Так например целое из базы данных перейдет в целое языка Python, анологичное преобразование будет выполнено и для чисел с плавающей точкой, строк. Значение NULL будет представленно в Python значением None.
75
def
load
():
76
db, conn, curs =
createConn
()
77 78
sql =
"""
79
SELECT
80
кодПодразделения,
81
название,
82
кодГоловногоПодраз
83
FROM
84
Подразделения"""
85
subdivisions, subdivisionOwners = {}, {}
86
try:
87
curs.
execute
(sql)
88
for rec in curs.
fetchall
():
89
s = telephonedir.
Subdivision
(rec[
1
])
90
subdivisions[rec[
0
]] = s
91
subdivisionOwners[s] = rec[
2
]
92
except db.DatabaseError, x:

93
print x
94
conn.
rollback
()
95
else:
96
conn.
commit
()
97
for s, i in subdivisionOwners.
iteritems
():
98
if i:
99
subdivisions[i].subdivisions.
add
(s)
100
else:
101
subdivision = s
102 103
sql =
"""
104
SELECT
105
кодСотрудника,
106
кодПодразделения,
107
фамилия,
108
имя,
109
отчество
110
FROM
111
Сотрудники"""
112
collaborators = {}
113
try:
114
curs.
execute
(sql)
115
for rec in curs.
fetchall
():
116
c = telephonedir.
Collaborator
(rec[
0
], rec[
2
], rec[
3
], rec[
4
])
117
collaborators[rec[
0
]] = c
118
subdivisions[rec[
1
]].
add
(c)
119
1   2   3   4   5   6   7   8   9   ...   22


написать администратору сайта