tag:blogger.com,1999:blog-47729410937535595312024-03-05T07:22:14.530-08:00My Spacehttp://iwajlo.blogspot.com/Unknownnoreply@blogger.comBlogger42125tag:blogger.com,1999:blog-4772941093753559531.post-43223173140479668662011-12-06T04:19:00.002-08:002011-12-06T04:43:21.383-08:00Файлови Системи Файлова система или управление на данните това е тази компонента на операционната<br />
система, която е предназначена да управлява постоянните обекти данни, т.е. обектите, които<br />
съществуват по-дълго отколкото процесите, които ги създават и използват. Постоянните обекти<br />
данни се съхраняват на външна памет (диск или друг носител) в единици, наричани файлове.<br />
Файловата система трябва да:<br />
• осигурява операции за манипулиране на отделни файлове, като например create, open,<br />
close, read, write, delete и др.<br />
• изгражда пространството от имена на файлове и да предоставя операции за<br />
манипулиране на имената в това пространство.<br />
<br />
Какво съдържа пространството от имена? Каква е организацията на файловата система?<br />
Какви са операциите, наричани системни примитиви, системни функции, системни<br />
извиквания или system calls, осигурявани от файловата система? Това са въпроси, които<br />
вълнуват потребителите и се разглеждат в първия раздел. Вторият раздел е посветен на<br />
проблеми при физическата реализация на файлова система и подходи за тяхното решаване.<br />
Като примери са използвани файловите системи на операционните системи UNIX, MINIX,<br />
LINUX, MSDOS, OS/2 и Windows NT.<br />
<a name='more'></a><br />
1. ЛОГИЧЕСКА СТРУКТУРА НА ФАЙЛОВА СИСТЕМА<br />
1.1. ИМЕНА И ТИПОВЕ ФАЙЛОВЕ<br />
<br />
Най-важната характеристика на една абстракция за потребителите са правилата, по<br />
които се именуват обектите, в случая файловете. Най-често името на файл е низ от символи с<br />
определена максимална дължина, като в някои системи освен букви и цифри са разрешени и<br />
други символи. Много често името се състои от две части, разделени със специален символ,<br />
например ".". Втората част се нарича разширение на името и носи информация за типа или<br />
формата на данните, съхранявани във файла. Например, следните имена имат разширения,<br />
показващи типа на данните във файла...........<br />
<br />
<br />
1.2. КАТАЛОЗИ И ОРГАНИЗАЦИЯ НА ФАЙЛОВАТА СИСТЕМА<br />
<br />
Вторият основен въпрос, засягащ външния вид на файловата система е: Колко каталога<br />
има и ако са повече от един каква е организацията на системата от каталози? Каталогът<br />
съдържа по един запис (елемент) за всеки файл, който съдържа като минимум името на файла.<br />
Освен това може да съдържа атрибутите на файла и дисковите адреси на данните на файла или<br />
указател към друга структура, където се съхраняват дисковите адреси на данните и евентуално<br />
атрибутите на файла.<br />
<br />
<br />
<br />
1.3. ОПЕРАЦИИ С ФАЙЛОВЕ<br />
<br />
Системните примитиви реализират операциите, които файловата система предоставя на<br />
потребителите за:<br />
• работа с отделни файлове;<br />
• изграждане на структура на файловата система;<br />
• защита на файловата система.<br />
Ще разгледаме няколко основни системни примитиви за работа с файлове по стандарта POSIX,<br />
който е реализиран в повечето UNIX системи - System V, 4.3BSD, SunOS, AIX, HP-UX, OSF/1 и<br />
др, в LINUX и MINIX. Повечето съвременни операционни системи предоставят системни<br />
примитиви, изпълняващи същите функции, макар да има различия в имената, броя аргументи и<br />
при реализацията им.<br />
Основното проектно решение, което определя набора от операции над файл, е<br />
структурата на файла. За потребителя файлът представлява последователност от 0 или повече<br />
байта. Това е структурата на файла, реализирана от файловата система и съобразно тази<br />
структура са проектирани системните примитиви. Преди да разгледаме системните примитиви<br />
ще въведем някои необходими понятия, използвани при работа на файловата подсистема.<br />
Файлов дескриптор (file descriptor) е неотрицателно цяло число, от 0 до 19 в по-<br />
ранните версии на UNIX или до 63, 255 и повече в по-новите версии на UNIX и в LINUX, което<br />
се свързва с файл при отваряне и се използва за идентифициране на файла при последващата<br />
му обработката. Връзката между файловия дескриптор и файла се разрушава при затваряне на<br />
файла. Файловите дескриптори имат локално значение за всеки процес, което означава, че<br />
файлов дескриптор напр. 5 в два процеса най-вероятно е свързан с различни файлове. Прието е<br />
файловите дескриптори 0, 1 и 2 да се свързват със стандартно отворените файлове, които всеки<br />
процес получава, съответно стандартния вход, стандартния изход и стандартния изход за<br />
грешки. Стандартно тези три файлови дескриптора са свързани с един и същи специален файл,<br />
съответстващ на управляващия терминал на процеса. Но за ядрото на операционната система<br />
няма нищо специално в тези файлови дескриптори. Това е просто съглашение, което ако се<br />
приеме от всички потребителски програми, прави лесно пренасочването на стандартния им<br />
вход/изход/изход за грешки и свързването на програми в конвейер, с помощта на командния<br />
интерпретатор.<br />
С всяко отваряне на файл се свързва и указател на текуща позиция във файла (file<br />
offset, file pointer), който определя позицията във файла, от която ще бъде четено или<br />
записвано и на практика стойността му е отместването от началото на файла, измерено в<br />
байтове. Този указател се зарежда, изменя или използва от повечето примитиви за работа с<br />
файлове.<br />
С всяко отваряне на файл се свързва и режим на отваряне на файла, който определя<br />
начина на достъп до файла чрез съответния файлов дескриптор докато е отворен от процеса,<br />
напр. само четене, само писане, четене и писане. При всеки следващ опит за достъп до файла се<br />
проверява дали той не противоречи на режима на отваряне, и ако е така, достъпа се отказва<br />
независимо от правата на процеса.<br />
<br />
<br />
РЕАЛИЗАЦИЯ НА КАТАЛОГ<br />
<br />
ПРИМЕРИ НА ФАЙЛОВИ СИСТЕМИ (UNIX, LINUX, WINDOWS - NTFS)<br />
<br />
<a href="https://docs.google.com/open?id=18EMEZX_Ay7oz72uTP2l9WbRzrzDSeJa8TOleyW8rxtUPZFWgY6trPCbUY16i" target="_blank"><span class="Apple-style-span" style="font-size: x-large;">Всичко за Файлови системи в документа</span>.</a><script type="text/javascript">
<!--
google_ad_client = "ca-pub-5917881121950498";
/* text_only */
google_ad_slot = "1901247234";
google_ad_width = 728;
google_ad_height = 110;
//-->
</script><br />
<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
</script>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-59520969044066249932011-12-02T06:49:00.000-08:002011-12-02T06:49:25.426-08:00Протоколът HTTPHTTP представлява прост текстов протокол, който се използва от услугата WWW за осигуряване на достъп до практически всякакъв вид данни, наричани събирателно ресурси. В HTTP протокола има понятия като клиент (обикновено това са Web-браузърите) и сървър (това са Web-сървърите). Обикновено HTTP протоколът работи върху стандартен TCP сокет отворен от клиента към сървъра. Стандартният порт за HTTP протокола e 80, но може да се използва и всеки друг TCP порт. Комуникацията по HTTP се състои от заявка (request) – съобщение от клиента към сървъра и отговор (response) – отговор на сървъра на съобщението от клиента.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-64009095436087750162011-12-02T06:34:00.000-08:002011-12-02T06:35:41.289-08:00Представяне на задачата за търговския пътник<ol start="1" style="margin-top: 0in;" type="I"><li class="MsoNormal"><span lang="BG">Представяне на проблема</span></li>
</ol><div class="MsoNormal"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-list: l1 level1 lfo2; tab-stops: .5in; text-indent: -.25in;"><span lang="BG" style="font-family: Wingdings; font-size: 9pt;">l<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG">Формулиране:</span></div><div class="MsoNormal" style="margin-left: .5in;"><span lang="BG">Търговски пътник трябва да обходи N града, като тръгне от един град, приет за начален, и се върне в него, без да преминава два пъти през един и същ град и цената на транспортните разходи да е минимална. Да се определи маршрутът на търговския пътник, ако са известни пътните разходи между градовете, (когато такъв път съществува).</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><br />
</div><div class="MsoNormal" style="text-indent: 28.35pt;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-list: l1 level1 lfo2; tab-stops: .5in; text-indent: -.25in;"><span lang="BG" style="font-family: Wingdings; font-size: 9pt;">l<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG">Едно възможно рещение:</span></div><div class="MsoNormal" style="margin-left: .5in;"><span lang="BG">Алгоритъмът на пълното изброяване за решаване на тази задача образува всички възможни маршрута ,(N-1)! на брой, оценява стойността на всеки и избира маршрутът с минимална стойност. Схематично(чрез псевдокод), алгоритъмът на пълното изброяване е представен на следващите редове.</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><br />
</div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG">Алгоритъм </span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG">{</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"> - Въвеждане на входните данни</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"> Suma = max // max е някакво голямо число (може да е сума на всички // пътища)</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"> for (I = 1; I <= (N-1)!; I++)</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"> {</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"> - Образуване на поредната пермутация Pi от N -1 града.</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"> - Изчисляване сумата Si на маршрута Pi.</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"> If ( Si < Suma)</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"> {</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"> Path=Pi;</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"> Suma=Si;</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"> }</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"> }</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><br />
</div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG">}</span><br />
<span lang="BG"><br />
</span><br />
<a name='more'></a><br />
<span lang="BG"></span><br />
<div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><i><span lang="BG">Входните данни за алгоритъма са:<o:p></o:p></span></i></span></div><span lang="BG"> </span><br />
<div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG">Масив CENA :</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> 1 2 … N</span></span></div><table border="0" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; margin-left: 62.1pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-table-layout-alt: fixed;"><tbody>
<tr> <td style="padding: 0in 5.4pt 0in 5.4pt; width: 42.55pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><span lang="BG">1</span></div></td> <td style="border-right: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 42.5pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> <td style="border-right: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 42.55pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> <td style="border-right: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 42.5pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> <td style="border: solid black 1.0pt; mso-border-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 36.45pt;" valign="top" width="49"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> </tr>
<tr> <td style="padding: 0in 5.4pt 0in 5.4pt; width: 42.55pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><span lang="BG">2</span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 42.5pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 42.55pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 42.5pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> <td style="border-top: none; border: solid black 1.0pt; mso-border-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 36.45pt;" valign="top" width="49"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> </tr>
<tr> <td style="padding: 0in 5.4pt 0in 5.4pt; width: 42.55pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><span lang="BG">…</span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 42.5pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 42.55pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 42.5pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center;"><span lang="BG">Cij</span></div></td> <td style="border-top: none; border: solid black 1.0pt; mso-border-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 36.45pt;" valign="top" width="49"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> </tr>
<tr> <td style="padding: 0in 5.4pt 0in 5.4pt; width: 42.55pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><span lang="BG">N</span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 42.5pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 42.55pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 42.5pt;" valign="top" width="57"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> <td style="border-top: none; border: solid black 1.0pt; mso-border-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 36.45pt;" valign="top" width="49"><div align="center" class="MsoNormal" style="layout-grid-mode: char; text-align: center; text-indent: 28.35pt;"><br />
</div></td> </tr>
</tbody></table><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG">Cij - цена на маршрута между I-я и J-я градове (Ако има такъв).</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG">StartPoint - номер на началния град</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><i><span lang="BG">Резултатите са:<o:p></o:p></span></i></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG">Suma – сумарна цена на маршрута</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG">Масив Path:</span></span></div><table border="0" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; margin-left: 42.0pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-table-layout-alt: fixed;"><tbody>
<tr style="height: 20.65pt; mso-yfti-lastrow: yes;"> <td style="border-right: none; border: solid black 1.0pt; height: 20.65pt; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 62.35pt;" valign="top" width="83"><div class="MsoNormal" style="layout-grid-mode: char; text-align: justify;"><span lang="BG">StartPoint</span></div></td> <td style="border-right: none; border: solid black 1.0pt; height: 20.65pt; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 42.2pt;" valign="top" width="56"><div class="MsoNormal" style="layout-grid-mode: char; text-align: justify; text-indent: 28.35pt;"><br />
</div></td> <td style="border-right: none; border: solid black 1.0pt; height: 20.65pt; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 42.65pt;" valign="top" width="57"><div class="MsoNormal" style="layout-grid-mode: char; text-align: justify; text-indent: 28.35pt;"><br />
</div></td> <td style="border-right: none; border: solid black 1.0pt; height: 20.65pt; mso-border-bottom-alt: solid black .5pt; mso-border-left-alt: solid black .5pt; mso-border-top-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 35.6pt;" valign="top" width="47"><div class="MsoNormal" style="layout-grid-mode: char; text-align: justify;"><span lang="BG">….....</span></div></td> <td style="border: solid black 1.0pt; height: 20.65pt; mso-border-alt: solid black .5pt; padding: 0in 5.4pt 0in 5.4pt; width: 63.3pt;" valign="top" width="84"><div class="MsoNormal" style="layout-grid-mode: char; text-align: justify;"><span lang="BG">StartPoint</span></div></td> </tr>
</tbody></table><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG">Асимптотичната оценка на този алгоритъм е O(N!), което даже за малки стойности на N е неприемливо.</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> <b>Все още за науката не е известен „хубав“ алгоритъм, който да намира така наречения хамилтонов път. Проблема се смята за NP – пълен.<o:p></o:p></b></span></span></div><div class="MsoNormal" style="margin-left: .5in; text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="margin-left: .5in; mso-list: l0 level1 lfo1; tab-stops: .5in; text-align: justify; text-indent: -.25in;"><span lang="BG"><span lang="BG" style="font-family: Wingdings; font-size: 9pt;">l<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG">Евристическо решение:</span></span></div><div class="MsoNormal" style="margin-left: .5in; text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="margin-left: .5in; text-align: justify;"><span lang="BG"><span lang="BG">Съществуват различни идеи за евристическо решение на тази задача. Едно от решенията използва “метод на частните цели”, който се състои в следното: Когато търговският пътник се намира в град I, се търси непосетен до този момент град J, с минимална цена на транспортните разходи до него спрямо другите, непосетени до този момент градове, имащи връзка с I. Чрез този подход се получава неоптимално решение, а близко до оптималното, което може да се види от следващата фигура.</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><br />
</span></div><div class="separator" style="clear: both; text-align: center;"><span lang="BG"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXItd-taYHEvmrbjCwphW3wThp3L2tMWoLGsTEaXVFvYA2d4aHZGMUjKDmAWYWkvddfz189GzNeRNY877DiDPGyBOpEpC-bGrgvawlYxohFTlLbRBEzIYrbfCYQ5S6K_ekTDMC3Yd-yw6l/s1600/p1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="136" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXItd-taYHEvmrbjCwphW3wThp3L2tMWoLGsTEaXVFvYA2d4aHZGMUjKDmAWYWkvddfz189GzNeRNY877DiDPGyBOpEpC-bGrgvawlYxohFTlLbRBEzIYrbfCYQ5S6K_ekTDMC3Yd-yw6l/s400/p1.jpg" width="400" /></a></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"><o:p><br />
</o:p></span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"><o:p><br />
</o:p></span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"><o:p></o:p></span></span></div><div align="center" class="MsoNormal" style="text-align: center;"><span lang="BG"><span lang="BG">Примерен граф на задачата за търговския пътник</span></span></div><div align="center" class="MsoNormal" style="text-align: center;"><span lang="BG"><span lang="BG"><br />
</span></span></div><div align="center" class="MsoNormal" style="text-align: center;"><span lang="BG"><br />
</span></div><span lang="BG"><br />
</span><br />
<div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG">Маршрутът 143251 е получен с евристически алгоритъм с начален град - 1. (Той се оказва и оптимален за този граф)</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG">Псевдокодът на евристическия алгоритъм е следния:</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> { </span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> - Въвеждане на входни данни.</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> Suma=0; </span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> Br=0;</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> Path[Br] = StartPoint;</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> While (Br < N-1)</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> {</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> I=Path[Br];</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> Избира се следващ град J, за който C[I,j] е минимално спрямо цената от I до останалите непосетени до момента градове.</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> Suma = Suma + Cena[I,j];</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> Br=Br+1;</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> Path[Br]=J;</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> }</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> Suma=Suma+Cena(Path[Br], StartPoint);</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> } /* край */</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG">Асимптотичната оценката на този алгоритъм е O(N*N), тъй като основният цикъл се повтаря N-1 пъти, а във всеки цикъл има около N на брой операции.</span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG" style="font-family: 'Arial Narrow', sans-serif;"><o:p><br />
</o:p></span></span></div><div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG" style="font-family: 'Arial Narrow', sans-serif;"><o:p></o:p></span></span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"><span lang="BG" style="font-size: 15pt;">II. Представяне на задачата за търговския пътник с Обобщени мрежи.<o:p></o:p></span></span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"><span lang="BG"> Обобщените мрежи се използват за моделиране на реални процеси и проблеми, с тях ще се опитаме да представим и проблема на търговския пътник.</span></span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"><i><span lang="BG">Нека първо въведем някой означения който ще използваме:<o:p></o:p></span></i></span></div><div class="MsoNormal" style="text-indent: 28.35pt;"><span lang="BG"><br />
</span></div><ol start="1" style="margin-top: 0in;" type="1"><li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: .5in; text-align: justify;"><span lang="BG"><span lang="BG">Нека t<sub>i</sub> и t<sub>f</sub> са началния и крайния момент на процеса който моделираме, като е възможно t<sub>f </sub>= безкрайност. Time = { t<sub>i</sub>, t<sub>f</sub>}</span></span></li>
<span lang="BG">
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: .5in; text-align: justify;"><span lang="BG">Нека T = {T1, T2, ... Tn} – е множество от пътуващи търговци</span></li>
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: .5in; text-align: justify;"><span lang="BG">Нека C = {C1, C2, ... Cc} – множеството от всички продукти който търговците T продават, тук може да кажем, че всеки търговец не е задължително да предлага всички продукти. </span></li>
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: .5in; text-align: justify;"><span lang="BG">Нека V = {V1, V2, ... Vv} – е множество от градове, който се посещават от търговците T.</span></li>
</span></ol><div class="MsoNormal"><span lang="BG"><br />
</span></div><div class="MsoNormal"><span lang="BG"><span lang="BG" style="font-size: 11pt;"> </span><i><span lang="BG" style="font-size: 14pt;">Сега ще дефинираме, някой функции, който ще използваме, в мрежата и на базата на който търговеца прави избор за своя маршрут между градовете.</span></i><span lang="BG" style="font-size: 14pt;"> <o:p></o:p></span></span></div><div class="MsoNormal"><span lang="BG"><br />
</span></div><ol start="1" style="margin-top: 0in;" type="1"><li class="MsoNormal" style="mso-list: l1 level1 lfo2; tab-stops: .5in; text-align: justify;"><span lang="BG"><span lang="BG">Fi(t<sub>i, </sub>Time<sub> </sub>) = {Ci1, Ci2, ... Cim} – продуктите, който i-я търговец доставя в момента Time.</span></span></li>
<span lang="BG">
<li class="MsoNormal" style="mso-list: l1 level1 lfo2; tab-stops: .5in; text-align: justify;"><span lang="BG">Q(t<sub>i, </sub>C<sub>j ,</sub>Time) – количеството на j-я продукт, който има i-я търговец в момента Time.</span></li>
<li class="MsoNormal" style="mso-list: l1 level1 lfo2; tab-stops: .5in; text-align: justify;"><span lang="BG">P(t<sub>i, </sub>C<sub>j ,</sub>Time) - цената на j-я продукт, който i – я търговец от T има в момента Time.</span></li>
<li class="MsoNormal" style="mso-list: l1 level1 lfo2; tab-stops: .5in; text-align: justify;"><span lang="BG">L(t<sub>i, </sub>C<sub>j ,</sub>Time) – срок на годност на j-я продукт, който i-я търговец от множеството T има в момента Time</span></li>
<li class="MsoNormal" style="mso-list: l1 level1 lfo2; tab-stops: .5in; text-align: justify;"><span lang="BG">M(Vk<sub> ,</sub>Time) = <kk1, ... ="" kk2,="" kks=""> където Kkj > 0 е количеството продукти, който в града Vk, са необходими в момента Time.</kk1,></span></li>
<li class="MsoNormal" style="mso-list: l1 level1 lfo2; tab-stops: .5in; text-align: justify;"><span lang="BG">D(Vk, Vk') – времето, което е необходимо за преминаване от върха Vk до съседния му връх Vk', като не е необходимо да имаме равенство в двете посоки на маршрута (Vk, Vk').</span></li>
<li class="MsoNormal" style="mso-list: l1 level1 lfo2; tab-stops: .5in; text-align: justify;"><span lang="BG">E(Vk, Vk', Time) – цената за пренос от връх Vk до неговия съседен Vk' в момента Time.</span></li>
<li class="MsoNormal" style="mso-list: l1 level1 lfo2; tab-stops: .5in; text-align: justify;"><span lang="BG">G(Vk, Vk' Time) – {0, 1} възможността за пренос от Vk до неговия съсед Vk' в момента Time.</span></li>
</span></ol><div class="MsoNormal" style="margin-left: 0.5in;"><span lang="BG"><span lang="BG">Така в рамките на даден интервал от време може пътищата да бъдат затворени и преминаването по директния път между двата града да не е възможно, затова ще въведем една друга функция, която да казва предполагаемо време когато затворения път(ако е затворен) ще бъде на разположение.</span></span></div><ol start="9" style="margin-top: 0in;" type="1"><li class="MsoNormal" style="mso-list: l1 level1 lfo2; tab-stops: .5in; text-align: justify;"><span lang="BG"><span lang="BG">O(Vk, Vk', Time) – времето, което се чака до отварянето на пътя между градовете Vk и Vk' от момента Time, ако пътя в момента е отворен то времето за чакане е 0 иначе ако не е сигурно кога ще бъде отворен пътя, то времето е = безкрайност.</span></span></li>
<span lang="BG">
<li class="MsoNormal" style="mso-list: l1 level1 lfo2; tab-stops: .5in; text-align: justify;"><span lang="BG"> R(Ti, Vk, Time) – стойноста на печалба на Ti в града Vk, това определяме по следния начин:</span></li>
</span></ol><div class="MsoNormal" style="margin-left: 0.5in;"><span lang="BG"><span lang="BG">R(Ti, Vk, Time) = Сумата на печалбата от всеки продукт който предлага търговеца, като за всеки продукт печалбата е равна на количеството на стоката по нейната цена, т.е</span></span></div><div class="MsoNormal" style="margin-left: 0.5in;"><span lang="BG"><span lang="BG">R(Ti, Vk, Time) = Сума по всички стоки(Q(t<sub>i, </sub>C<sub>j ,</sub>Time) * P(t<sub>i, </sub>C<sub>j ,</sub>Time)). Всичко това правим с уговорка, че нуждите на даден град надвишават количеството, което дадения търговец носи.</span></span></div><ol start="11" style="margin-top: 0in;" type="1"><li class="MsoNormal" style="mso-list: l1 level1 lfo2; tab-stops: .5in; text-align: justify;"><span lang="BG"><span lang="BG">N(Ti, Vk, Time) – времето, което търговеца Ti прекарва в града Vk след момента Time.</span></span></li>
<span lang="BG">
<li class="MsoNormal" style="mso-list: l1 level1 lfo2; tab-stops: .5in; text-align: justify;"><span lang="BG">S (Ti, Cj, Vk, Time) – {0, 1} – дали цената на j-я продукт , предлагана от i-я търговец в града Vk е конкурентно способна(приемлива).</span></li>
</span></ol><span lang="BG"><br />
</span><br />
<div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG" style="font-family: 'Arial Narrow', sans-serif;"><o:p><br />
</o:p></span></span></div><div class="separator" style="clear: both; text-align: center;"><span lang="BG"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFiHEMdpCMIOAcrS5wGOcYaP8aj0WkmnEu7o2usEvjFpSY32uQkPxG7RJccV7xOMMPoYwjukXapzAj0LTW_-vBKvBAEt6FWA96laKwir3YDEHjnKbKWODd5alO6at535EGU-9M5NREMbCh/s1600/p2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="333" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFiHEMdpCMIOAcrS5wGOcYaP8aj0WkmnEu7o2usEvjFpSY32uQkPxG7RJccV7xOMMPoYwjukXapzAj0LTW_-vBKvBAEt6FWA96laKwir3YDEHjnKbKWODd5alO6at535EGU-9M5NREMbCh/s400/p2.jpg" width="400" /></a></span></div><div class="separator" style="clear: both; text-align: center;"><span lang="BG"><br />
</span></div><div class="separator" style="clear: both; text-align: center;"></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Сега трябва представим така посочената мрежа.</span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Имаме две входни позиции - това са състоянията </span><span lang="BG">l<sub>1 </sub> и</span><span lang="BG" style="position: relative; top: 4.5pt;"> </span><span lang="BG"> </span><span lang="BG">l</span><span lang="BG" style="position: relative; top: 4.5pt;">2 </span><span lang="BG">ядрата, който се движат по мрежата започват именно от тези две начални състояния. Всяко ядро описва поведението на един търговец, който се стреми да изкара най-голяма печалба продавайки стоката си.</span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><i><span lang="BG">Сега да дадем описание на някой от основните преходи r<sub>i </sub>,<o:p></o:p></span></i></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><b><span lang="BG" style="font-family: 'Arial Narrow', sans-serif; font-size: 11pt;">Прехода r1:<o:p></o:p></span></b></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><table border="0" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; margin-left: 2.75pt; mso-padding-alt: 2.75pt 2.75pt 2.75pt 2.75pt; mso-table-layout-alt: fixed;"><tbody>
<tr style="height: 25.5pt;"> <td style="border-right: none; border: solid black 1.0pt; height: 25.5pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-top-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 31.5pt;" valign="top" width="42"><div class="TableContents" style="text-align: justify;"><br />
</div></td> <td style="border-right: none; border: solid black 1.0pt; height: 25.5pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-top-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 32.0pt;" valign="top" width="43"><div class="MsoNormal" style="text-align: justify;"><span lang="BG" style="font-size: 9pt;">l<span style="position: relative; top: 3pt;">3<o:p></o:p></span></span></div></td> <td style="border-right: none; border: solid black 1.0pt; height: 25.5pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-top-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 32.0pt;" valign="top" width="43"><div class="MsoNormal" style="text-align: justify;"><span lang="BG" style="font-size: 9pt;">l<span style="position: relative; top: 3pt;">4<o:p></o:p></span></span></div></td> <td style="border-right: none; border: solid black 1.0pt; height: 25.5pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-top-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 30.5pt;" valign="top" width="41"><div class="MsoNormal" style="text-align: justify;"><span lang="BG" style="font-size: 9pt;">l<span style="position: relative; top: 3pt;">6<o:p></o:p></span></span></div></td> <td style="border: solid black 1.0pt; height: 25.5pt; mso-border-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 37.0pt;" valign="top" width="49"><div class="MsoNormal" style="text-align: justify;"><span lang="BG" style="font-size: 9pt;">l<span style="position: relative; top: 3pt;">14<o:p></o:p></span></span></div></td> </tr>
<tr style="height: 25.15pt;"> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; height: 25.15pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 31.5pt;" valign="top" width="42"><div class="MsoNormal" style="text-align: justify;"><span lang="BG" style="font-size: 9pt;">l</span><span lang="BG" style="font-size: 9pt; position: relative; top: 4.5pt;">1<o:p></o:p></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; height: 25.15pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 32.0pt;" valign="top" width="43"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">True<o:p></o:p></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; height: 25.15pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 32.0pt;" valign="top" width="43"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">False<o:p></o:p></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; height: 25.15pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 30.5pt;" valign="top" width="41"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">False<o:p></o:p></span></div></td> <td style="border-top: none; border: solid black 1.0pt; height: 25.15pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-right-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 37.0pt;" valign="top" width="49"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">False<o:p></o:p></span></div></td> </tr>
<tr> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 31.5pt;" valign="top" width="42"><div class="MsoNormal" style="text-align: justify;"><span lang="BG" style="font-size: 9pt;">l<span style="position: relative; top: 3pt;">2<o:p></o:p></span></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 32.0pt;" valign="top" width="43"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">False<o:p></o:p></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 32.0pt;" valign="top" width="43"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">False<o:p></o:p></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 30.5pt;" valign="top" width="41"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">True<o:p></o:p></span></div></td> <td style="border-top: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-right-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 37.0pt;" valign="top" width="49"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">False<o:p></o:p></span></div></td> </tr>
<tr> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 31.5pt;" valign="top" width="42"><div class="MsoNormal" style="text-align: justify;"><span lang="BG" style="font-size: 9pt;">l<span style="position: relative; top: 3pt;">3<o:p></o:p></span></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 32.0pt;" valign="top" width="43"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">W1<o:p></o:p></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 32.0pt;" valign="top" width="43"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">W2<o:p></o:p></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 30.5pt;" valign="top" width="41"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">False<o:p></o:p></span></div></td> <td style="border-top: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-right-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 37.0pt;" valign="top" width="49"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">W3<o:p></o:p></span></div></td> </tr>
<tr> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 31.5pt;" valign="top" width="42"><div class="MsoNormal" style="text-align: justify;"><span lang="BG" style="font-size: 9pt;">l<span style="position: relative; top: 3pt;">9<o:p></o:p></span></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 32.0pt;" valign="top" width="43"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">W1<o:p></o:p></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 32.0pt;" valign="top" width="43"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">W2<o:p></o:p></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 30.5pt;" valign="top" width="41"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">False<o:p></o:p></span></div></td> <td style="border-top: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-right-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 37.0pt;" valign="top" width="49"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">W3<o:p></o:p></span></div></td> </tr>
<tr> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 31.5pt;" valign="top" width="42"><div class="MsoNormal" style="text-align: justify;"><span lang="BG" style="font-size: 11pt;">l</span><span lang="BG" style="font-size: 11pt; position: relative; top: 4pt;">11<o:p></o:p></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 32.0pt;" valign="top" width="43"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">False<o:p></o:p></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 32.0pt;" valign="top" width="43"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">False<o:p></o:p></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 30.5pt;" valign="top" width="41"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">True<o:p></o:p></span></div></td> <td style="border-top: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-right-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 37.0pt;" valign="top" width="49"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">False<o:p></o:p></span></div></td> </tr>
</tbody></table><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Където имаме следната стойност на предикатите Wi.</span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">W1 – има поне един допълнителен път (повече от един), през който ядрото може да премине</span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">W2 – има път по който ядрото може да премине</span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">W3 – противоположно на W2 т.е няма път по който ядрото може да премине.</span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">r<sub>1</sub> e началния преход за мрежата, като той проверява дали има път по който даден търговец може да продължи движението си, в зависимост от условита го пренасочва в различни състояния.</span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><b><span lang="BG">Прехода r2:<o:p></o:p></span></b></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><table border="0" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; margin-left: 2.75pt; mso-padding-alt: 2.75pt 2.75pt 2.75pt 2.75pt; mso-table-layout-alt: fixed;"><tbody>
<tr> <td style="border-right: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-top-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 46.5pt;" valign="top" width="62"><div class="TableContents" style="text-align: justify;"><br />
</div></td> <td style="border: solid black 1.0pt; mso-border-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 58.5pt;" valign="top" width="78"><div class="MsoNormal" style="text-align: justify;"><span lang="BG">l<span style="position: relative; top: 4.5pt;">5<o:p></o:p></span></span></div></td> </tr>
<tr> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 46.5pt;" valign="top" width="62"><div class="MsoNormal" style="text-align: justify;"><span lang="BG">l<span style="position: relative; top: 4.5pt;">4<o:p></o:p></span></span></div></td> <td style="border-top: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-right-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 58.5pt;" valign="top" width="78"><div class="TableContents" style="text-align: justify;"><span lang="BG">W4</span></div></td> </tr>
</tbody></table><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Където W4 = „Time > pr<sub>2 </sub>X<sub>cu</sub><sup>α</sup>“</span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><b><span lang="BG">Прехода r3:<o:p></o:p></span></b></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><table border="0" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; margin-left: 2.75pt; mso-padding-alt: 2.75pt 2.75pt 2.75pt 2.75pt; mso-table-layout-alt: fixed;"><tbody>
<tr> <td style="border-right: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-top-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 49.5pt;" valign="top" width="66"><div class="TableContents" style="text-align: justify;"><br />
</div></td> <td style="border: solid black 1.0pt; mso-border-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 46.0pt;" valign="top" width="61"><div class="MsoNormal" style="text-align: justify;"><span lang="BG">l<span style="position: relative; top: 4.5pt;">7<o:p></o:p></span></span></div></td> </tr>
<tr> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 49.5pt;" valign="top" width="66"><div class="MsoNormal" style="text-align: justify;"><span lang="BG">l<span style="position: relative; top: 4.5pt;">5<o:p></o:p></span></span></div></td> <td style="border-top: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-right-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 46.0pt;" valign="top" width="61"><div class="TableContents" style="text-align: justify;"><span lang="BG">W5</span></div></td> </tr>
</tbody></table><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Като W5 = „Time > X<sub>cu</sub><sup>α</sup>“</span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><b><span lang="BG">Прехода r4:<o:p></o:p></span></b></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><table border="0" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; margin-left: 2.75pt; mso-padding-alt: 2.75pt 2.75pt 2.75pt 2.75pt; mso-table-layout-alt: fixed;"><tbody>
<tr> <td style="border-right: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-top-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 40.5pt;" valign="top" width="54"><div class="TableContents" style="text-align: justify;"><br />
</div></td> <td style="border-right: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-top-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 50.0pt;" valign="top" width="67"><div class="MsoNormal" style="text-align: justify;"><span lang="BG">l<span style="position: relative; top: 4.5pt;">8<o:p></o:p></span></span></div></td> <td style="border-right: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-top-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 49.0pt;" valign="top" width="65"><div class="MsoNormal" style="text-align: justify;"><span lang="BG">l<span style="position: relative; top: 4.5pt;">9<o:p></o:p></span></span></div></td> <td style="border-right: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-top-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 40.5pt;" valign="top" width="54"><div class="MsoNormal" style="text-align: justify;"><span lang="BG">l<span style="position: relative; top: 4.5pt;">10<o:p></o:p></span></span></div></td> <td style="border: solid black 1.0pt; mso-border-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 41.0pt;" valign="top" width="55"><div class="MsoNormal" style="text-align: justify;"><span lang="BG">l<span style="position: relative; top: 4.5pt;">11<o:p></o:p></span></span></div></td> </tr>
<tr> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 40.5pt;" valign="top" width="54"><div class="MsoNormal" style="text-align: justify;"><span lang="BG">l<span style="position: relative; top: 4.5pt;">7<o:p></o:p></span></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 50.0pt;" valign="top" width="67"><div class="TableContents" style="text-align: justify;"><span lang="BG">W6</span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 49.0pt;" valign="top" width="65"><div class="TableContents" style="text-align: justify;"><span lang="BG">W7</span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 40.5pt;" valign="top" width="54"><div class="TableContents" style="text-align: justify;"><span lang="BG">False</span></div></td> <td style="border-top: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-right-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 41.0pt;" valign="top" width="55"><div class="TableContents" style="text-align: justify;"><span lang="BG">False</span></div></td> </tr>
<tr> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 40.5pt;" valign="top" width="54"><div class="MsoNormal" style="text-align: justify;"><span lang="BG">l<span style="position: relative; top: 4.5pt;">6<o:p></o:p></span></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 50.0pt;" valign="top" width="67"><div class="TableContents" style="text-align: justify;"><span lang="BG">False</span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 49.0pt;" valign="top" width="65"><div class="TableContents" style="text-align: justify;"><span lang="BG">False</span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 40.5pt;" valign="top" width="54"><div class="TableContents" style="text-align: justify;"><span lang="BG">W6</span></div></td> <td style="border-top: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-right-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 41.0pt;" valign="top" width="55"><div class="TableContents" style="text-align: justify;"><span lang="BG">W7</span></div></td> </tr>
</tbody></table><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Като:</span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">W6 = „Time > T + t<sub>x</sub>“ като t<sub>x</sub> е Ti - T </span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">W7 = отрицанието на предиката W6.<o:p></o:p></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><b><span lang="BG">Прехода r5:<o:p></o:p></span></b></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><table border="0" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; margin-left: 2.75pt; mso-padding-alt: 2.75pt 2.75pt 2.75pt 2.75pt; mso-table-layout-alt: fixed;"><tbody>
<tr> <td style="border-right: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-top-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 48.0pt;" valign="top" width="64"><div class="TableContents" style="text-align: justify;"><br />
</div></td> <td style="border-right: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-top-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 62.0pt;" valign="top" width="83"><div class="MsoNormal" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">l<span style="position: relative; top: 3.5pt;">12<o:p></o:p></span></span></div></td> <td style="border: solid black 1.0pt; mso-border-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 53.0pt;" valign="top" width="71"><div class="MsoNormal" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">l<span style="position: relative; top: 3.5pt;">13<o:p></o:p></span></span></div></td> </tr>
<tr> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 48.0pt;" valign="top" width="64"><div class="MsoNormal" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">l<span style="position: relative; top: 3.5pt;">8<o:p></o:p></span></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 62.0pt;" valign="top" width="83"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">W8<o:p></o:p></span></div></td> <td style="border-top: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-right-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 53.0pt;" valign="top" width="71"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">W9<o:p></o:p></span></div></td> </tr>
<tr> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 48.0pt;" valign="top" width="64"><div class="MsoNormal" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">l<span style="position: relative; top: 3.5pt;">12<o:p></o:p></span></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 62.0pt;" valign="top" width="83"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">W9<o:p></o:p></span></div></td> <td style="border-top: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-right-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 53.0pt;" valign="top" width="71"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">W8<o:p></o:p></span></div></td> </tr>
<tr> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 48.0pt;" valign="top" width="64"><div class="MsoNormal" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">l<span style="position: relative; top: 3.5pt;">14<o:p></o:p></span></span></div></td> <td style="border-bottom: solid black 1.0pt; border-left: solid black 1.0pt; border-right: none; border-top: none; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 62.0pt;" valign="top" width="83"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">W8<o:p></o:p></span></div></td> <td style="border-top: none; border: solid black 1.0pt; mso-border-bottom-alt: solid black .25pt; mso-border-left-alt: solid black .25pt; mso-border-right-alt: solid black .25pt; padding: 2.75pt 2.75pt 2.75pt 2.75pt; width: 53.0pt;" valign="top" width="71"><div class="TableContents" style="text-align: justify;"><span lang="BG" style="font-size: 10pt;">W9<o:p></o:p></span></div></td> </tr>
</tbody></table><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Като:</span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">W8 = c(</span><span lang="BG">l<span style="position: relative; top: 4.5pt;">12, </span>Time</span><span lang="BG">) = 0 v X<sub>cu</sub><sup>αi > </sup>X<sub>cu</sub><sup>i<o:p></o:p></sup></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">където </span></span></div><div class="MsoNormal" style="margin-left: .25in; mso-list: l0 level1 lfo1; tab-stops: .25in; text-align: justify; text-indent: -.25in;"><span lang="BG"><span lang="BG" style="font-family: Symbol; font-size: 9pt;">-<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG">c(l, t) е броя на преходите в състояние l, в момента t.</span></span></div><div class="MsoNormal" style="margin-left: .25in; mso-list: l0 level1 lfo1; tab-stops: .25in; text-align: justify; text-indent: -.25in;"><span lang="BG"><span lang="BG" style="font-family: Symbol; font-size: 9pt; position: relative; top: 4.5pt;">-<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG">X<sub>cu</sub><sup>αi </sup>е текущата характеристика на i-тото ядро „алфа“ което се намира в състояние </span><span lang="BG">l<span style="position: relative; top: 4.5pt;">12.<o:p></o:p></span></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">W9 = отрицанието на предиката W8.<o:p></o:p></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Ядрата α1, α2, ... αt с начални характеристики „Ti“ влизат в състояние l<span style="position: relative; top: 4.5pt;">1 </span>в момента Time = t и след това веднага преминават в състояние l<span style="position: relative; top: 4.5pt;">3 </span>. Там те приемат нови характеристики μ(Ti, Time) {<c<sub>j , Q(Ti, Cj, Time), P(Ti, Cj, Time), L(Ti, Cj, Time), S(Ti, Cj, Vk, Time) > като Cj е от Fi(Ti, Time)}<o:p></o:p></sub></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Където μ(Ti, Time) е за върха Vk където търговеца Ti се намира.<o:p></o:p></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Едновременно с този преход ядрото β влиза в състояние l<span style="position: relative; top: 4.5pt;">2.</span></span><span lang="BG">с начална характеристика:</span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG"> β = {Vk, M(Vk, Time), {<d(vk, ,="" e(vk,="" g(vk,="" o(vk,="" time),="" time)="" vk'),="" vk',="" vk'=""> като Vk' е от множеството от съседите на върха Vk}}<o:p></o:p></d(vk,></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Ядрата </span><span lang="BG">α се разделята на в състояние l<span style="position: relative; top: 4.5pt;">3 </span></span><span lang="BG"> (ако Ti има възможност за движение) и в състояние </span><span lang="BG">l<span style="position: relative; top: 4.5pt;">4 </span>(Ако пътя за движение на търговеца Ti е уникален).<o:p></o:p></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">В състояние </span><span lang="BG">l<span style="position: relative; top: 4.5pt;">4 </span>някой от ядрата трябва да бъдат генерирани който имат по един линеен предчественик. Всички ядра, който имат еднакви(равни) начални характеристики „Ti“ са различни представяния на ядрото α<sub>i</sub> и няма конкурентна ситуация между тях. <o:p></o:p></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">В този модел съществува конкуренция спрямо цената на даден предлаган продукт, ако цената на даден търговец е неконкурентно способна спрямо на друг то този град не му носи никаква печалба и той не трябва да ходи там. Така когато в началото ядрата получат характеристика за даден град те преценяват дали да преминат в този град(т.е дали тяхната цена е добра или не).<o:p></o:p></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Ядрата α<sub>i</sub> не приемат нови характеристики в l<span style="position: relative; top: 4.5pt;">3</span> но в l<span style="position: relative; top: 4.5pt;">4 </span>те приемат характеристика:<o:p></o:p></span></span></div><div class="MsoNormal" style="margin-left: .25in; mso-list: l1 level1 lfo2; tab-stops: .25in; text-align: justify; text-indent: -.25in;"><span lang="BG"><span lang="BG" style="font-family: Symbol; font-size: 9pt;">-<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG">„Vk, Time + D(Vk, Vk') “ където Vk' е връх който Ti (търговеца) ще посети. <o:p></o:p></span></span></div><div class="MsoNormal" style="margin-left: .25in; text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="margin-left: .25in; text-align: justify;"><span lang="BG"><span lang="BG">След преминаването им от l<span style="position: relative; top: 4.5pt;">4 </span>в<span style="position: relative; top: 4.5pt;"> </span>l<span style="position: relative; top: 4.5pt;">5 </span>ядрото α приема характеристика:<o:p></o:p></span></span></div><div class="MsoNormal" style="margin-left: .25in; mso-list: l1 level1 lfo2; tab-stops: .25in; text-align: justify; text-indent: -.25in;"><span lang="BG"><span lang="BG" style="font-family: Symbol; font-size: 9pt;">-<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG">„Time + N( pr<sub>1 </sub>X<sub>0</sub><sup>α </sup>, pr<sub>1 </sub>X<sub>cu</sub><sup>α </sup>, Time) “ <o:p></o:p></span></span></div><div class="MsoNormal" style="margin-left: .25in; text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="margin-left: .25in; text-align: justify;"><span lang="BG"><span lang="BG">А в състояние l<span style="position: relative; top: 4.5pt;">7 </span>характеристика:<o:p></o:p></span></span></div><div class="MsoNormal" style="margin-left: .25in; mso-list: l1 level1 lfo2; tab-stops: .25in; text-align: justify; text-indent: -.25in;"><span lang="BG"><span lang="BG" style="font-family: Symbol; font-size: 9pt;">-<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG">R(pr<sub>1 </sub>X<sub>0</sub><sup>α</sup> , pr<sub>1 </sub>X<sub>cu</sub><sup>α </sup>, Time) - E(pr<sub>1 </sub>X<sub>cu-2</sub><sup>α</sup> , pr<sub>1 </sub>X<sub>cu-1</sub><sup>α </sup>, Time)<o:p></o:p></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Което е и неговата печалба.<o:p></o:p></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Когато ядро α<sub>i</sub> влезе в състояние l<sub>9 </sub>то приема като текуща характеристика името на върха където се намира в текущия момент т.е μ(Ti, Time).<o:p></o:p></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">В състояние l<span style="position: relative; top: 4.5pt;">8 </span>тези ядра приемат характеристика стойността на изминатия път от ядрото в мрежата сподер критерия „максимална печалба“. <o:p></o:p></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG">Накрая ядрото α<sub>i</sub> с максимална печалба e търсеното в задачата. Така определихме възможната максимална печалба.<o:p></o:p></span></span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><br />
</span></div><div class="MsoNormal" style="text-align: justify;"><span lang="BG"><span lang="BG" style="font-size: 11pt;">Трябва да отбележим че:<o:p></o:p></span></span></div><div class="MsoNormal" style="margin-left: .25in; mso-list: l2 level1 lfo3; tab-stops: .25in; text-align: justify; text-indent: -.25in;"><span lang="BG"><span lang="BG" style="font-family: Symbol; font-size: 9pt;">-<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG" style="font-size: 11pt;">В рамките на един такт всички ядра, който могат да преминат по някой преход го прават<o:p></o:p></span></span></div><div class="MsoNormal" style="margin-left: .25in; mso-list: l2 level1 lfo3; tab-stops: .25in; text-align: justify; text-indent: -.25in;"><span lang="BG"><span lang="BG" style="font-family: Symbol; font-size: 9pt;">-<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG" style="font-size: 11pt;">t<sup>0 </sup> (елементарно време) е времето свързано с престоя или прехода на търговеца (и може да е например 1 минута)<o:p></o:p></span></span></div><div class="MsoNormal" style="margin-left: .25in; mso-list: l2 level1 lfo3; tab-stops: .25in; text-align: justify; text-indent: -.25in;"><span lang="BG"><span lang="BG" style="font-family: Symbol; font-size: 9pt;">-<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG" style="font-size: 11pt;">Преходите се активират всеки момент относно някакво фиксирано време.<o:p></o:p></span></span></div><div class="MsoNormal" style="margin-left: .25in; mso-list: l2 level1 lfo3; tab-stops: .25in; text-align: justify; text-indent: -.25in;"><span lang="BG"><span lang="BG" style="font-family: Symbol; font-size: 9pt;">-<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG" style="font-size: 11pt;">Продължителността на прехода е t<sup>0</sup> <o:p></o:p></span></span></div><div class="MsoNormal" style="margin-left: .25in; mso-list: l2 level1 lfo3; tab-stops: .25in; text-align: justify; text-indent: -.25in;"><span lang="BG"><span lang="BG" style="font-family: Symbol; font-size: 9pt;">-<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG" style="font-size: 11pt;">Капацитета на всички дъги и състояния е „безкрайност“ с изключение на <o:p></o:p></span></span></div><div class="MsoNormal" style="margin-left: .25in; text-align: justify;"><span lang="BG"><span lang="BG" style="font-size: 11pt;">c(</span><span lang="BG">l<span style="position: relative; top: 4pt;">2</span></span><span lang="BG" style="font-size: 11pt;">) = c(</span><span lang="BG">l<span style="position: relative; top: 4pt;">6</span></span><span lang="BG" style="font-size: 11pt;">) = c(</span><span lang="BG">l<span style="position: relative; top: 4pt;">10</span></span><span lang="BG" style="font-size: 11pt;">) = c(</span><span lang="BG">l<span style="position: relative; top: 4pt;">11</span></span><span lang="BG" style="font-size: 11pt;">) = 1<o:p></o:p></span></span></div><div class="MsoNormal" style="margin-left: .25in; mso-list: l2 level1 lfo3; tab-stops: .25in; text-align: justify; text-indent: -.25in;"><span lang="BG"><span lang="BG" style="font-family: Symbol; font-size: 9pt;">-<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG" style="font-size: 11pt;">приоритетите на всички състояния и преходи са равни с изключение на </span><span lang="BG" style="position: relative; top: 4pt;"> </span><span lang="BG">l<span style="position: relative; top: 4pt;">8 </span>l<span style="position: relative; top: 4pt;">14 </span>и<span style="position: relative; top: 4pt;"> </span>l<span style="position: relative; top: 4pt;">12 </span>.<o:p></o:p></span></span></div><div class="MsoNormal" style="margin-left: .25in; mso-list: l2 level1 lfo3; tab-stops: .25in; text-align: justify; text-indent: -.25in;"><span lang="BG"><span lang="BG" style="font-family: Symbol; font-size: 9pt;">-<span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span></span><span lang="BG">Трябва да поставим все пак някакво ограничение на броя на ядрата за да може мрежата да функционира нормално.<o:p></o:p></span></span></div><span lang="BG"><br />
</span><br />
<div class="MsoNormal" style="text-align: justify; text-indent: 28.35pt;"><span lang="BG"><span lang="BG" style="font-family: 'Arial Narrow', sans-serif;"><o:p><br />
</o:p></span></span></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-48320061639839689042011-11-25T05:59:00.000-08:002011-11-25T05:59:37.909-08:00Sockets<div align="center" class="MsoNormal" style="text-align: center;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif; font-size: x-large;"><br />
</span></div><div class="VsTitle" style="margin-bottom: 6.0pt; mso-outline-level: 1;"><span lang="BG" style="font-family: "Verdana","sans-serif"; font-size: 12.0pt;">Sockets<o:p></o:p></span></div><div class="MsoNormal" style="mso-layout-grid-align: none; text-align: justify; text-autospace: none;"><span lang="RU">При модела клиент-сървер </span><span lang="RU">сърверът предлага дадена услуга. При инициализация на услугата сърверът създава </span><b>socket</b><span lang="RU">. </span>Socket e<span lang="RU"> софтуерен мрежови интерфейс, </span><span lang="BG">който </span><span lang="RU">се използва за междумашинна</span><span lang="RU"> </span><span lang="RU">комуникация в мрежовата среда и се определя от </span>IP<span lang="RU"> адреса и от номера</span><span lang="RU"> </span><span lang="RU">на порта, който е число между 0 и 65535 (0-1024 –системни портове).</span><span lang="RU"><o:p></o:p></span></div><div class="MsoNormal" style="mso-layout-grid-align: none; text-align: justify; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG" style="font-family: "Courier New CYR";">#</span><span lang="BG">include <netinet in.h=""></netinet></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><a name='more'></a><br />
<div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">struct <b>sockaddr</b> {</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> unsigned short sa_family; // socket address family</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> char sa_data[14]; // 14 байта е максималният размер за всичките </span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> // различни sockaddr структури</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">}</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">struct <b>sockaddr_in</b> {</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> short sin_family; // адресна фамилия – AF_INET</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> unsigned short sin_port; // номер на порт</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> struct in_addr sin_addr; // Интернет адрес</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> char sin_zero[8]; // padding, за да се изравни размера на структурата // sockaddr_int с този на sockaddr</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">}</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">struct <b>in_addr</b> {</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> unsigned long s_addr;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">}</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><b><span lang="BG">sockaddr</span></b><span lang="BG"> е структура, описваща един сокет. <b>sockaddr_in</b> е вид sockaddr, специфична за Интернет сокетите, и може да бъде cast-вана към sockaddr.</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <arpa inet.h=""></arpa></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">in_addr_t <b>inet_addr</b>(const char *cp);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Функцията <b>inet_addr</b> преобразува даден интернет адрес от dot notation в integer. Преобразуваният адрес е в network byte order (байтовете са подредени отляво надясно).</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><span lang="BG" style="font-family: "Times New Roman","serif"; font-size: 12.0pt; mso-ansi-language: BG; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: BG;"><br clear="all" style="page-break-before: always;" /> </span> <div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <sys types.h=""></sys></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <sys socket.h=""></sys></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">int <b>socket</b>(int domain, int type, int protocol);</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Функцията <b>socket</b> инициализира сокет и връща дескриптор на този новосъздаден сокет. Параметърът <u>domain</u> определя адресната фамилия и може да бъде AF_INET (нас това ни интересува, за Интернет адреси), AF_INET6, AF_UNIX, AF_LOCAL, AF_ISO и т.н. Параметърът <u>type</u> определя семантиката на предаваните данни и може да бъде SOCK_STREAM (за TCP/IP), SOCK_DGRAM (за UDP/IP), SOCK_SEQ_PACKET и др. Параметърът <u>protocol</u> определя протокола, който да се използва; за TCP/IP трябва да е 0.</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">int <b>bind</b>(int sockfd, struct sockaddr *my_addr, int addrlen);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Функцията <b>bind</b> наименува сокета (с дескриптор <u>sockfd</u>), т.е. му задава локален адрес <u>my_addr</u> (указател към структура sockaddr). Параметърът <u>addrlen</u> показва размера на структурата my_addr. При успех връща 0, а при грешка връща -1.</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">int <b>listen</b>(int sockfd, int backlog);</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Чрез функцията <b>listen</b> се посочва, че даден сокет (с дескриптор <u>sockfd</u>) трябва да започне да слуша за конекции. Работи само със сокети от тип SOCK_STREAM и SOCK_SEQ_PACKET (connection-based socket types). Параметърът <u>backlog</u> указва максималната дължина на опашката от чакащи конекции. При успех функцията връща 0, а при грешка връща -1.</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">int <b>accept</b>(int sockfd, struct sockaddr *addr, int addrlen);</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Функцията <b>accept</b> също работи само със сокети, установяващи конекция, т.е. със SOCK_STREAM и SOCK_SEQ_PACKET. Чрез нея сървърът приема чакащи на опашката конекции. <u>sockfd</u> трябва да е сокет, създаден със socket, свързан с bind и слушащ за конекции с listen. Взима се първата заявка за конекция от опашката, създава се нов свързан сокет и се връща файлов дескриптор на този сокет. Новият сокет не е в слушащо състояние. sockfd не се повлиява и остава непроменен. Функцията връща файлов дескриптор на новия сокет при успех и -1 при грешка.</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal"><span lang="BG">int <b>connect</b>(int sockfd, struct sockaddr *serv_addr, int addrlen);</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">За да се свърже един клиент с даден сървър, трябва да изпълни функцията <b>connect</b> (свързва клиентския сокет с дескриптор sockfd с адреса serv_addr). Функцията връща 0 при успех и -1 при грешка.</span></div><div class="MsoNormal" style="text-align: justify;"><br />
</div><div class="MsoNormal" style="text-align: justify;"><br />
</div><span lang="RU" style="font-family: "Verdana","sans-serif"; font-size: 12.0pt; mso-ansi-language: RU; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: BG;"><br clear="all" style="page-break-before: always;" /> </span> <div class="MsoNormal" style="text-align: justify;"><span lang="RU" style="font-family: "Verdana","sans-serif"; mso-ansi-language: RU;">1. </span><span lang="BG" style="font-family: "Verdana","sans-serif";">Прост клиент/ сървър<o:p></o:p></span></div><div class="MsoNormal" style="margin-left: 53.4pt; mso-list: l0 level1 lfo1; tab-stops: list 53.4pt; text-align: justify; text-indent: -.25in;"><!--[if !supportLists]--><span lang="RU" style="font-family: Symbol; font-size: 11.0pt; mso-ansi-language: RU; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·<span style="font: 7.0pt "Times New Roman";"> </span></span><!--[endif]--><span lang="BG" style="font-family: "Verdana","sans-serif"; font-size: 11.0pt;">Протокол </span><b><span style="font-family: "Verdana","sans-serif"; font-size: 11.0pt; mso-ansi-language: EN-US;">lnc</span></b><span lang="BG" style="font-family: "Verdana","sans-serif"; font-size: 11.0pt;">: клиента изпраща цяло число. Сървърът връща на клиента това число, увеличено с едно. Клиента разпечатва увеличеното число.</span><b><span lang="RU" style="font-family: "Verdana","sans-serif"; font-size: 11.0pt; mso-ansi-language: RU;"><o:p></o:p></span></b></div><div class="MsoNormal" style="margin-left: 35.4pt; text-align: justify;"><br />
</div><div class="VsTitle"><span lang="BG" style="font-family: "Verdana","sans-serif"; font-size: 11.0pt;">Прост клиент/сървър<o:p></o:p></span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><u><span lang="BG">Пример</span></u><span lang="BG"> за комуникация между клиент и сървър – клиентът изпраща цяло число; сървърът връща на клиента това число, увеличено с едно; клиентът разпечатва увеличеното число:</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/*****************/</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Simple server */г</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/*****************/</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Make the necessary includes and set up the variables. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <sys types.h=""></sys></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <sys socket.h=""></sys></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <stdio.h></stdio.h></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <netinet in.h=""></netinet></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <arpa inet.h=""></arpa></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <unistd.h></unistd.h></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <string.h></string.h></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">int main()</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">{</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int server_sockfd, client_sockfd;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int server_len, client_len;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> struct sockaddr_in server_address;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> struct sockaddr_in client_address;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int n;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> char buff[1024];</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int chislo;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> char dest[2];</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Create an unnamed socket for the server. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> server_sockfd = socket(AF_INET, SOCK_STREAM, 0);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Name the socket. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> server_address.sin_family = AF_INET;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> server_address.sin_addr.s_addr = inet_addr("127.0.0.1");</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> server_address.sin_port = htons(9734);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> server_len = sizeof(server_address);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> bind(server_sockfd, (struct sockaddr *)&server_address, server_len);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Create a connection queue and wait for clients. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> listen(server_sockfd, 5);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> while(1) {</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> printf("server waiting\n");</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Accept a connection. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> client_len = sizeof(client_address);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* We can now read/write to client on client_sockfd. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> while (n = read(client_sockfd, buff, 1024) > 0) {</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> write(1, "server receives: ", 17);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> write(1, buff, n);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> write(1, "\n", 1);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> dest[2];</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> strncpy(dest, buff, n + 1);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> dest[n] = 0;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> chislo = atoi(dest) + 1;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> snprintf(dest, 2, "%d", chislo);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> </span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> write(client_sockfd, dest, 2);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> close(client_sockfd);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> }</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> }</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> printf("server closes\n");</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> return 0;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">}</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/*****************/</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Simple client */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/*****************/</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Make the necessary includes and set up the variables. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <sys types.h=""></sys></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <sys socket.h=""></sys></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <stdio.h></stdio.h></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <netinet in.h=""></netinet></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <arpa inet.h=""></arpa></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <unistd.h></unistd.h></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">int main()</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">{</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int sockfd;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int client_len;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int i;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> struct sockaddr_in client_address;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int result;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> char ch = '5';</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int n;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> char buff[1024];</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Create a socket for the client. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> sockfd = socket(AF_INET, SOCK_STREAM, 0);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Name the socket, as agreed with the server. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> client_address.sin_family = AF_INET;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> client_address.sin_addr.s_addr = inet_addr("127.0.0.1");</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> client_address.sin_port = htons(9734);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> client_len = sizeof(client_address);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Now connect our socket to the server's socket. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> result = connect(sockfd, (struct sockaddr *)&client_address, client_len);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> if(result == -1) {</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> perror("oops: client");</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> return 1;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> }</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* We can now read/write via sockfd. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> printf("client sends: %c\n", ch);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> write(sockfd, &ch, 1);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> </span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> while(n = read(sockfd, buff, 1024) > 0) {</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> write(1, "client receives: ", 17);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> write(1, buff, n);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> write(1, "\n", 1);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> }</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> close(sockfd);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> return 0;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">}</span><o:p></o:p></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Различните видове компютри използват различни конвенции за подредбата на байтовете в рамките на една дума. Някои слагат най-важния байт първо (т.нар. <u>big-endian</u> подредба), а други – последно (т.нар. <u>little-endian</u> подредба). За да могат да си комуникират машини с различна подредба на байтовете, Интернет протоколите определят конвенция за подредба на байтовете при предаване по мрежата – <u>network byte order</u>. При установяването на Интернет връзка чрез сокети, трябва полетата sin_port и sin_addr от структурата sockaddr_in да са в network byte order. Ако се задават целочислени стойности, трябва да се преобразуват в network byte order. Ако се използва някоя от функциите getservbyname, gethostbyname или inet_addr за получаване на номер на порт и адрес на хост, стойностите вече са в network byte order и няма нужда да се преобразуват допълнително. В противен случай обаче трябва да се използват функциите <u>htons</u> и <u>ntohs</u> за преобразуване на номера на порт, а <u>htonl</u> и <u>ntohl</u> – за преобразуване на IPv4 адреси. Тук <u>h</u> означава <u>host</u>, а <u>n</u> – <u>network</u>; <u>s</u> – <u>short</u> (16-битови числа, портове), <u>l</u> – <u>long</u> (32-битови числа, Интернет адреси).</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <arpa inet.h=""></arpa></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <netinet in.h=""></netinet></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">uint16_t <b>htons</b>(uint16_t hostshort)<a href="" name="index-htons-1752"></a>;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">uint16_t <b>ntohs</b>(uint16_t netshort)<a href="" name="index-ntohs-1753"></a>;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">uint32_t <b>htonl</b>(uint32_t hostlong)<a href="" name="index-htonl-1754"></a>;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">uint32_t <b>ntohl</b>(uint32_t netlong)<a href="" name="index-ntohl-1755"></a>;</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <sys unistd.h=""></sys></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">int <b>gethostname</b>(char *name, size_t namelen);</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Чрез функцията <b>gethostname</b> в аргумента <u>name</u> се получава стандартното име на текущата система. <u>namelen</u> указва размера в байтове на масива, към който сочи <u>name</u>. Функцията връща 0 при успех, -1 при грешка.</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Чрез структурата <b>hostent</b> се описва даден хост:</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <netdb.h></netdb.h></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">struct <b>hostent</b> {</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> char *h_name; // официалното име на хоста</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> char **h_aliases; // zero-terminated списък от псевдо-</span></div><div class="MsoNormal" style="margin-left: 2.5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> // ними/алтернативни имена на хоста</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none; text-indent: .5in;"><span lang="BG">int h_addrtype; // адресна фамилия – AF_INET</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none; text-indent: .5in;"><span lang="BG">int h_length; // дължина на адреса в байтове</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none; text-indent: .5in;"><span lang="BG">char **h_addr_list; // zero-terminated списък от адреси</span></div><div class="MsoNormal" style="margin-left: 2.5in; mso-layout-grid-align: none; text-autospace: none; text-indent: .5in;"><span lang="BG">// на хоста в network byte order</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">}</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#define <b>h_addr</b> h_addr_list[0]; // I-ият адрес от h_addr_list</span></div><div class="MsoNormal" style="margin-left: 3.0in; mso-layout-grid-align: none; text-autospace: none; text-indent: .5in;"><span lang="BG"> // за backward compatibility</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <netdb.h></netdb.h></span></div><div class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none; text-indent: .5in;"><span lang="BG">#include <sys socket.h=""></sys></span></div><div class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none; text-indent: .5in;"><span lang="BG">struct hostent *<b>gethostbyname</b>(const char *name);</span></div><div class="MsoNormal" style="margin-left: 3.5in; mso-layout-grid-align: none; text-autospace: none; text-indent: -3.0in;"><span lang="BG">struct hostent *<b>gethostbyaddr</b>(const char *addr, int addr_len, int addr_type);</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Функцията <b>gethostbyname</b> връща указател към структура от тип <u>hostent</u> за даденото име <u>name</u>. Това име <u>name</u> може да бъде или име на хост, или IPv4 адрес в dot notation, или IPv6 адрес в colon notation. Ако е IPv4 или IPv6 адрес, то не се извършва lookup.</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Функцията <b>gethostbyaddr</b> връща структура <u>hostent</u> по зададен Интернет адрес. Въпреки че <u>addr</u> е char *, всъщност се иска указател към структура от тип <u>in_addr</u>. <u>addr_len</u> трябва да е sizeof(struct in_addr), т.е. дължината в байтове на този Интернет адрес, а <u>addr_type</u> трябва да е AF_INET.</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Както е споменато по-горе, във файла <u>/etc/services</u> се извършва map-ване на портове и протоколи към имена на услуги. Всеки ред от този файл представлява запис за една услуга и има следната структура:</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">service_name port/protocol [aliases …]</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><u><span lang="BG">service_name</span></u><span lang="BG"> е името на услугата и е case sensitive, т.е. има значение дали буквите са малки или главни. <u>port</u> е десетично число, представляващо номер на порт, на който работи услугата. <u>protocol</u> е име на протокол (например tcp, udp), с който работи услугата, и трябва да съответства със запис от файла protocols. <u>aliases</u> е опционален списък от псевдоними, т.е. алтернативни имена на тази услуга, които също са case sensitive.</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Файлът <u>/etc/protocols</u> пък представя наличните протоколи и всеки запис (т.е. всеки ред) от него има следния вид:</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">protocol number [aliases …]</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><u><span lang="BG">protocol</span></u><span lang="BG"> е името на протокола (ip, tcp, udp, …). <u>number</u> е официалното число, съответстващо на този протокол, такова, каквото се изписва в IP header-а. <u>aliases</u> е опционален списък от псевдоними на протокола.</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Структурата <b>servent</b> представя запис за дадена услуга:</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <netdb.h></netdb.h></span></div><div class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none; text-indent: .5in;"><span lang="BG">struct <b>servent</b> {</span></div><div class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none; text-indent: .5in;"><span lang="BG"> char *s_name; // официалното име на услугата</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none; text-indent: .5in;"><span lang="BG">char **s_aliases; // zero-terminated списък от</span></div><div class="MsoNormal" style="margin-left: 2.5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> // алтернативни имена на услугата</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none; text-indent: .5in;"><span lang="BG">int s_port; // номер на порт в network byte order</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none; text-indent: .5in;"><span lang="BG">char *s_proto; // име на протокол</span></div><div class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none; text-indent: .5in;"><span lang="BG">}</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">struct servent *<b>getservent</b>(void);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">struct servent *<b>getservbyname</b>(const char *name,</span></div><div class="MsoNormal" style="margin-left: 3.0in; mso-layout-grid-align: none; text-autospace: none; text-indent: .5in;"><span lang="BG">const char *proto);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">struct servent *<b>getservbyport</b>(int port, const char *proto);</span></div><div class="MsoNormal" style="text-indent: .5in;"><br />
</div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Функцията <b>getservent</b> прочита следващия ред от файла /etc/services и връша структура <u>servent</u>, описваща тази услуга. Ако се налага, файлът /etc/services първо се отваря за четене.</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Функцията <b>getservbyname</b> връща структура <u>servent</u> за някой ред от файла /etc/services, който съответства на указаното име на услуга <u>name</u> и протокол <u>proto</u>. Ако <u>proto</u> е null, то няма ограничение за протокола.</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Функцията <b>getservbyport</b> връща структура <u>servent</u> за някоя услуга от файла /etc/services, която съответства на порта <u>port</u> в network byte order и на протокола <u>proto</u>. Отново, ако <u>proto</u> е null, то протоколът няма значение.</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><span lang="BG">Ако има грешка или се достигне края на файла /etc/services, функциите <b>getservent</b>, <b>getservbyname</b> и <b>getservbyport</b> връщат null.</span></div><div class="MsoNormal" style="margin-left: .5in; text-align: justify;"><br />
</div><ol start="1" style="margin-top: 0in;" type="1"><li class="MsoNormal" style="mso-list: l2 level1 lfo3; tab-stops: list .5in; text-align: justify;"><span lang="RU" style="font-family: "Verdana","sans-serif"; mso-ansi-language: RU;">Клиент на стандартната услуга </span><b><span style="font-family: "Verdana","sans-serif"; mso-ansi-language: EN-US;">daytime</span></b><span lang="RU" style="font-family: "Verdana","sans-serif"; mso-ansi-language: RU;"><o:p></o:p></span></li>
</ol><div class="MsoNormal" style="margin-left: .75in; mso-list: l1 level1 lfo1; tab-stops: list .75in; text-align: justify; text-indent: -.25in;"><!--[if !supportLists]--><span lang="RU" style="font-family: Symbol; font-size: 11.0pt; mso-ansi-language: RU; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·<span style="font: 7.0pt "Times New Roman";"> </span></span><!--[endif]--><span lang="RU" style="font-family: "Verdana","sans-serif"; font-size: 11.0pt; mso-ansi-language: RU;">Клиента получава от сървъра един символен низ с текущото време.(Използвайте името на услугата и името на сървъра.)<o:p></o:p></span></div><div class="VsTitle"><span lang="BG" style="font-family: "Verdana","sans-serif"; font-size: 11.0pt;">Клиент на стандартната услуга daytime<o:p></o:p></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/******************/</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Daytime client */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/******************/</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Start with the usual includes and declarations. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <sys socket.h=""></sys></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <netinet in.h=""></netinet></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <netdb.h></netdb.h></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <stdio.h></stdio.h></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <unistd.h></unistd.h></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">int main(int argc, char *argv[])</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">{</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> char *host;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int sockfd;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int len, result;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> struct sockaddr_in address;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> struct hostent *hostinfo;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> struct servent *servinfo;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> char buffer[128];</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> if(argc == 1)</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> host = "localhost";</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> else</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> host = argv[1];</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Find the host address and report an error if none is found. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> hostinfo = gethostbyname(host);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> if(!hostinfo) {</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> fprintf(stderr, "no host: %s\n", host);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> exit(1);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> }</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Check that the daytime service exists on the host. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> servinfo = getservbyname("daytime", "tcp");</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> if(!servinfo) {</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> fprintf(stderr,"no daytime service\n");</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> exit(1);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> }</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> printf("daytime port is %d\n", ntohs(servinfo -> s_port));</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Create a socket. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> sockfd = socket(AF_INET, SOCK_STREAM, 0);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Construct the address for use with connect... */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> address.sin_family = AF_INET;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> address.sin_port = servinfo -> s_port;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> address.sin_addr = *(struct in_addr *)*hostinfo -> h_addr_list;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> len = sizeof(address);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* ...then connect and get the information. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> result = connect(sockfd, (struct sockaddr *)&address, len);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> if(result == -1) {</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> perror("oops: getdate");</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> exit(1);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> }</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> result = read(sockfd, buffer, sizeof(buffer));</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> buffer[result] = '\0';</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> printf("read %d bytes: %s", result, buffer);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> close(sockfd);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> exit(0);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">}</span></div><div class="MsoNormal" style="margin-left: .5in; text-align: justify;"><br />
</div><span lang="RU" style="font-family: "Verdana","sans-serif"; font-size: 12.0pt; mso-ansi-language: RU; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: BG;"><br clear="all" style="page-break-before: always;" /> </span> <div class="MsoNormal" style="margin-left: .25in; mso-list: l0 level1 lfo2; tab-stops: list .25in; text-align: justify; text-indent: -.25in;"><!--[if !supportLists]--><b><span lang="RU" style="font-family: "Verdana","sans-serif"; mso-ansi-language: RU; mso-bidi-font-family: Verdana; mso-fareast-font-family: Verdana;">2.<span style="font: 7.0pt "Times New Roman";"> </span></span></b><!--[endif]--><span lang="RU" style="font-family: "Verdana","sans-serif"; mso-ansi-language: RU;">Клиент и </span><span lang="BG" style="font-family: "Verdana","sans-serif";">с</span><span lang="RU" style="font-family: "Verdana","sans-serif"; mso-ansi-language: RU;">ъврър за отдалечено разпечатване на съдържанието на директория.<o:p></o:p></span></div><div class="MsoNormal" style="margin-left: .75in; mso-list: l0 level2 lfo2; tab-stops: list .75in left 63.0pt; text-align: justify; text-indent: -.25in;"><!--[if !supportLists]--><span lang="RU" style="font-family: Symbol; font-size: 11.0pt; mso-ansi-language: RU; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·<span style="font: 7.0pt "Times New Roman";"> </span></span><!--[endif]--><span lang="RU" style="font-family: "Verdana","sans-serif"; font-size: 11.0pt; mso-ansi-language: RU;">Клиента изпраща име на директория. Той получава от сървъра съдържанието на директорията и го извежда на стандартния си изход. <o:p></o:p></span></div><div class="VsTitle" style="margin-bottom: .0001pt; margin-bottom: 0in; mso-outline-level: 1;"><span lang="BG" style="font-family: "Verdana","sans-serif"; font-size: 11.0pt; mso-bidi-font-weight: bold;">Клиент и сървър за отдалечено разпечатване на директория<o:p></o:p></span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><u><span lang="BG">Пример</span></u><span lang="BG"> за комуникация между клиент и сървър, при която клиентът изпраща име на директория, получава от сървъра съдържанието на директорията и го извежда на стандартния си изход:</span></div><div class="MsoNormal" style="tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/***************/</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* "ls" server */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/***************/</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Make the necessary includes and set up the variables. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <sys types.h=""></sys></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <sys socket.h=""></sys></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <stdio.h></stdio.h></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <netinet in.h=""></netinet></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <arpa inet.h=""></arpa></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <unistd.h></unistd.h></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">int main()</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">{</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int server_sockfd, client_sockfd;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int server_len, client_len;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> struct sockaddr_in server_address;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> struct sockaddr_in client_address;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int n;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> char dir[1024];</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Create an unnamed socket for the server. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> server_sockfd = socket(AF_INET, SOCK_STREAM, 0);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Name the socket. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> server_address.sin_family = AF_INET;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> server_address.sin_addr.s_addr = inet_addr("127.0.0.1");</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> server_address.sin_port = htons(9999);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> server_len = sizeof(server_address);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> bind(server_sockfd, (struct sockaddr *)&server_address, server_len);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Create a connection queue and wait for clients. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> listen(server_sockfd, 5);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> while(1) {</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> printf("server waiting\n");</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Accept a connection. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> client_len = sizeof(client_address);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* We can now read/write to client on client_sockfd. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> while (n = read(client_sockfd, dir, 1024) > 0) {</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> write(1, "server receives: ", 17);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> write(1, dir, 3);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> write(1, "\n", 1);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> </span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> close(1);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> dup(client_sockfd);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> close(client_sockfd);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> </span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> execlp("ls", "ls", dir, "-l", 0);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> } </span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> printf ("server closes\n");</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> }</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> return 0;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">}</span></div><div class="MsoNormal" style="margin-left: .5in; tab-stops: .5in; text-align: justify;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/***************/</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* "ls" client */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/***************/</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Make the necessary includes and set up the variables. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <sys types.h=""></sys></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <sys socket.h=""></sys></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <stdio.h></stdio.h></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <netinet in.h=""></netinet></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <arpa inet.h=""></arpa></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">#include <unistd.h></unistd.h></span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">int main()</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">{</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int sockfd;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int client_len;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int i;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> struct sockaddr_in client_address;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> int result, n;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> char dir[3] = "bla";</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> char buff[1024];</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Create a socket for the client. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> sockfd = socket(AF_INET, SOCK_STREAM, 0);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Name the socket, as agreed with the server. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> client_address.sin_family = AF_INET;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> client_address.sin_addr.s_addr = inet_addr("127.0.0.1");</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> client_address.sin_port = htons(9999);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> client_len = sizeof(client_address);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* Now connect our socket to the server's socket. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> result = connect(sockfd, (struct sockaddr *) &client_address, client_len);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> if(result == -1) {</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> perror("oops: client");</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> return 1;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> }</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">/* We can now read/write via sockfd. */</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> </span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> printf("client sends: %s\n", dir);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> </span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> write(sockfd, dir, sizeof(dir));</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> </span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> while(n = read(sockfd, buff, 1024) > 0) { </span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> printf("client receives:\n%s", buff);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> }</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> </span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> close(sockfd);</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG"> return 0;</span></div><div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><span lang="BG">}</span></div><br />
<div class="MsoNormal" style="margin-left: .5in; mso-layout-grid-align: none; text-autospace: none;"><br />
</div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-6971189769340059722009-01-28T07:29:00.000-08:002009-01-28T07:40:15.233-08:00Изпълняване на Shell команди от Java код.<pre><span class="constant">String</span> <span class="ident">cmd</span> <span class="punct">=</span> <span class="punct">"</span><span style="color: rgb(255, 153, 0);" class="string">ls -al</span><span class="punct">";</span><br /> <span class="constant">Runtime</span> <span class="ident">run</span> <span class="punct">=</span> <span class="constant">Runtime</span><span class="punct">.</span><span class="ident">getRuntime</span><span class="punct">();</span><br /> <span class="constant">Process</span> <span class="ident">pr</span> <span class="punct">=</span> <span class="ident">run</span><span class="punct">.</span><span class="ident">exec</span><span class="punct">(</span><span class="ident">cmd</span><span class="punct">);</span><br /> <span class="ident">pr</span><span class="punct">.</span><span class="ident">waitFor</span><span class="punct">();</span><br /> <span class="constant">BufferedReader</span> <span class="ident">buf</span> <span class="punct">=</span> <span class="ident">new</span> <span class="constant">BufferedReader</span><span class="punct">(</span><span style="color: rgb(51, 102, 255);" class="ident">new</span><span style="color: rgb(51, 102, 255);"> </span><span class="constant">InputStreamReader</span><span class="punct">(</span><span class="ident">pr</span><span class="punct">.</span><span class="ident">getInputStream</span><span class="punct">()));</span><br /> <span class="constant">String</span> <span class="ident">line</span> <span class="punct">=</span> <span style="color: rgb(255, 153, 0);" class="punct">"</span><span style="color: rgb(255, 153, 0);" class="string"></span><span class="punct"><span style="color: rgb(255, 153, 0);">"</span>;</span><br /> <span style="color: rgb(51, 102, 255);" class="keyword">while</span><span style="color: rgb(51, 102, 255);"> </span><span class="punct">((</span><span class="ident">line</span><span class="punct">=</span><span class="ident">buf</span><span class="punct">.</span><span class="ident">readLine</span><span class="punct">())!=</span><span style="color: rgb(51, 102, 255);" class="ident">null</span><span class="punct">)</span> <span class="punct">{</span><br /> <span class="constant">System</span><span class="punct">.</span><span style="color: rgb(51, 204, 0);" class="ident">out</span><span class="punct">.</span><span class="ident">println</span><span class="punct">(</span><span class="ident">line</span><span class="punct">);</span><br /> <span class="punct">}</span><br /><br /></pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-43399584575309197552009-01-19T03:33:00.000-08:002009-01-19T12:59:22.925-08:00Deploying на Web приложение на WebSphereЗа да deploy-нем приложение на IBM WebSphere трябва да направим .war файл. Ако нашето приложение е работило на Tomcat или JBOSS, то ние можем да го преместим на WebSphere като направим .war файл с помоща на jar.<br /><br />1) Отваряме терминала с текуща директория директорията на приложението ни.<br />2) За да направим .war файл изпълняваме следната команда "jar - cvf schoolsystem.war * "<br />(jar e tool от стандартния пакет на JRE)<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7X-ACobONLCJazRRrnGlz5mjCTY0o7uAh2M0k6BBE4_o6D_St_hRRNzA5noEO8XVXSi-TXIU7vB9aIN4RnfqGzxi5fl61pvtqGaJKZ2tKdUlCl4r_Ex_fQ72okUdXEnQLNq3JwGm8o9od/s1600-h/p1.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 575px; height: 459px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7X-ACobONLCJazRRrnGlz5mjCTY0o7uAh2M0k6BBE4_o6D_St_hRRNzA5noEO8XVXSi-TXIU7vB9aIN4RnfqGzxi5fl61pvtqGaJKZ2tKdUlCl4r_Ex_fQ72okUdXEnQLNq3JwGm8o9od/s320/p1.png" alt="" id="BLOGGER_PHOTO_ID_5292976406493492882" border="0" /></a><br />Нашия .war файл се появява в текущата ни директория.<br /><br />3) Стартираме WebSphere:<br /><span class="UI">Start menu > All Program > IBM WebSphere > Application Server v6 > Profiles > AppSrv01 > Start the server</span><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrWgInCsYg-qYRRZTzDdn8khmqT49TSsDBfSbwLa7E01i8odknB2optOplCw_HTqOH1UaUGLgPqnwyYjXRJtWQd-QN58_6-xcUKZrtNGDfUy-Tr67FmdXPoyBBX_w8vJGHtRteakO069P2/s1600-h/p2.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 713px; height: 280px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrWgInCsYg-qYRRZTzDdn8khmqT49TSsDBfSbwLa7E01i8odknB2optOplCw_HTqOH1UaUGLgPqnwyYjXRJtWQd-QN58_6-xcUKZrtNGDfUy-Tr67FmdXPoyBBX_w8vJGHtRteakO069P2/s320/p2.png" alt="" id="BLOGGER_PHOTO_ID_5292977020901352850" border="0" /></a><br />4) Отваряте Administration Console пак от същото място в StartMenu и се логваме с произволно име.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2Q3sLzEham4WiG8b7_bKXWi-AkUXgM70sRhriAFk9lL5DBU7AmgTqX4EUJtNJAI40XbQgeov88QAoqUp_FTL_RaGcbm5p5dwWoD1Ji1vSFhqusvC4HU3S-jcCEApzsz3vmQq_aQ8sVGCl/s1600-h/p3.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 594px; height: 230px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2Q3sLzEham4WiG8b7_bKXWi-AkUXgM70sRhriAFk9lL5DBU7AmgTqX4EUJtNJAI40XbQgeov88QAoqUp_FTL_RaGcbm5p5dwWoD1Ji1vSFhqusvC4HU3S-jcCEApzsz3vmQq_aQ8sVGCl/s320/p3.png" alt="" id="BLOGGER_PHOTO_ID_5292979170176407266" border="0" /></a><br /><br /><br />5) Избираме <span class="UI">Applications > Install New Application за да инсталираме нашия .war файл</span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9pYgXCpSPoUaNSL4Yd1E6d4xC8F7ywjn7bDnPedVJpgDCfNPEYVC8XAHaD6MiTbl4X3_wGiuVM1vetmtTXbp3sL2DmuojcIx65lhHsu3W5Jj4je_kigfbuFZpaCrMim5I5S5uiDw7IZ40/s1600-h/p4.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 666px; height: 535px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9pYgXCpSPoUaNSL4Yd1E6d4xC8F7ywjn7bDnPedVJpgDCfNPEYVC8XAHaD6MiTbl4X3_wGiuVM1vetmtTXbp3sL2DmuojcIx65lhHsu3W5Jj4je_kigfbuFZpaCrMim5I5S5uiDw7IZ40/s320/p4.png" alt="" id="BLOGGER_PHOTO_ID_5292980392916267250" border="0" /></a><br /><span class="UI"><br />6) Избираме файла от диска и в </span><span class="UI">Context Root задаваме име под което ще се отваря приложението приметно my_app означава </span><a target="_blank" href="http://localhost:9081/schoolsystem/index.html">http://localhost:9081/my_app</a><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhANpSnK63tR-0bfHt067EpcAE2OCdC4lfTanYk6DavpIWHKkMukEUREMl4I6n6be9acxWV-AZsqqDt4PPUqIWv8wIvG4nnQpCvLkjWLL7bCq_3dJ7YdfUFR4JZL1qAOGdYHF2H69MoFVM9/s1600-h/p5.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 574px; height: 319px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhANpSnK63tR-0bfHt067EpcAE2OCdC4lfTanYk6DavpIWHKkMukEUREMl4I6n6be9acxWV-AZsqqDt4PPUqIWv8wIvG4nnQpCvLkjWLL7bCq_3dJ7YdfUFR4JZL1qAOGdYHF2H69MoFVM9/s320/p5.png" alt="" id="BLOGGER_PHOTO_ID_5293001328633297362" border="0" /></a>7) Даваме Next и довършваме инсталацията<br /><br />8) Избираме <span style="font-weight: bold;" class="UI">Save to Master Configuration</span> и избираме <span class="UI">Save</span> за да запазим промените<br /><br /><br /><span class="UI"><br /><br /><br /></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDVoMb3eud6-eVLxhd5W146-cVYC5yUGtXkiH99XsdPxb3ZKkDsqKMGPOKM_9D_HhTW_c6SnjGGxIPVrm5JuC-leaONFa8NPSw8c-g87-9wZYCogGBAYKESsmjxqGpaiirRrJDqHiZFioq/s1600-h/p6.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 731px; height: 516px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDVoMb3eud6-eVLxhd5W146-cVYC5yUGtXkiH99XsdPxb3ZKkDsqKMGPOKM_9D_HhTW_c6SnjGGxIPVrm5JuC-leaONFa8NPSw8c-g87-9wZYCogGBAYKESsmjxqGpaiirRrJDqHiZFioq/s320/p6.png" alt="" id="BLOGGER_PHOTO_ID_5293002330666905634" border="0" /></a><br /><span class="UI"><br />9) Избираме </span><span style="font-weight: bold;" class="UI">Applications > Enterprise Application</span> и стартираме нашето приложение<br /><br /><br />10) Отваряме <a target="_blank" href="http://localhost:9081/schoolsystem/index.html">http://localhost:9081/my_app</a>, (в някой случаи може порта да е 9080) къ<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbxFLBKIk3k1dFBHGc789XUZkrJvxOuoYuy1plUXINstge6UdTfJwkCHBIEYiYR1ss9O_LKh8C0Yi3ixcT04M4P3Iw2yKKdeRccoGSj1lRsJfXtmUnBPkqXrrb9XSRBGDpB6ewzqhW_5_Z/s1600-h/p8.png">https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbxFLBKIk3k1dFBHGc789XUZkrJvxOuoYuy1plUXINstge6UdTfJwkCHBIEYiYR1ss9O_LKh8C0Yi3ixcT04M4P3Iw2yKKdeRccoGSj1lRsJfXtmUnBPkqXrrb9XSRBGDpB6ewzqhW_5_Z/s1600-h/p8.png</a>дето трябва да видим нашето приложение<br /><br /><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigEdGVrEaj_AhwsS46jX7xmt2o6Dq21sin2Qq7UduxNi3TRBRxUPaOgecZlFF4RvoPHr24kWw8x5WMBkr7F937eGkFJMGi5SVVnfdsa5MoLd2EadXY_OBWkIFwNkcsUyyFQ4NOWMiS-E1d/s1600-h/p9.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 700px; height: 443px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigEdGVrEaj_AhwsS46jX7xmt2o6Dq21sin2Qq7UduxNi3TRBRxUPaOgecZlFF4RvoPHr24kWw8x5WMBkr7F937eGkFJMGi5SVVnfdsa5MoLd2EadXY_OBWkIFwNkcsUyyFQ4NOWMiS-E1d/s320/p9.png" alt="" id="BLOGGER_PHOTO_ID_5293011958076263074" border="0" /></a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-76569946243530318562009-01-17T11:22:00.002-08:002009-01-17T11:23:22.635-08:00Създаване на прозорчета в Python„ Програмиране с Python“, ФМИ<br />Нено Ганчев<br />04.06.2007г.<br />Как да си създадем прозорци с Python?<br /><br /> * За щастие не се налага да си рисуваме сами прозорците по екрана, за това си има специализирани инструменти<br /> * Има няколко инструмента за Python които ни позволяват да си правим шарени програмки<br /> * Днес ще се запознаем с wxPython - порт на C++ библиотеката wxWidgets за Python<br /><br />Откъде да започнем?<br /><br /> 1. Първо да инсталираме магическата пръчица за прозорци - питонския модул wx<br /> * сваляме си инсталацията, демотата и документацията от http://wxpython.org/<br /> * инсталацията е в готови изпълними файлове, но за ентусиастите има и source-ове<br /> 2. Не е лоша идея преди да почнем да си правим собствено приложение първо да погледнем примерните програми и overview частта в документацията<br /> 3. Има и страхотно демо в което можете да видите примери за всички възможности които wxPython ви предоставя както в код, така и нагледно(незаменим помощник по време на разработка:)<br /> 4. Недостатък на документацията - има я само в C++ вариант със забележки за wxPython<br /><br />Основни концепции в wxPython<br /><br /> 1. Йерархия на класовете, представляващи прозорчетата по екрана<br /> * Основни класове: wxApp, wxWindow, wxFrame, wxDialog, wxPanel<br /> * Класове-контроли: всевъзможни бутончета, текстови полета, менюта и т.н.<br /> 2. Обработка на събития(event handling) и main loop<br /><br />Основните класове отблизо: wxApp<br /><br />wxApp има няколко метода които трябва да се дефинират или извикат:<br /><br /> 1. OnInit()<br /> * инициализира графичното ни приложение(играе ролята на конструктор)<br /> * трябва да върне True, иначе wxPython няма да покаже приложението<br /> 2. SetTopWindow(window)<br /> * Казва на програмата кой от всичките прозорци е главен<br /> * Програмата може да има няколко главни прозореца<br /> * Главните прозорци са специални<br /> 3. MainLoop()<br /> * стартира главния цикъл за прехващане на събития<br /> * без него главния прозорец може и да се покаже но ще стои "замръзнал" и няма да иска нито да си играе с нас, нито да си ходи<br /> 4. OnExit()<br /> * правилното място за деинициализация на потребителски данни<br /> * вика се след като потребителя е казал че ще затваря програмата, но преди вътрешните структури на wxPython да се деинициализират и да не можете да ги ползвате<br /><br />Основните класове отблизо: wxWindow<br /><br /> * wxWindow e базовия клас на всички прозорци по екрана<br /> * под прозорци се разбира всеки видим обект на екрана(менюта, бутони, диалогови прозорци, текстови полета, статични надписи, вдлъбнати линийки и т.н.)<br /> * поема memory management`а на своите деца<br /> * сам по себе си не предлага никаква полезна за диалог с потребителя функционалност<br /> * не работите директно с обекти от този тип а с производните му wxFrame и wxDialog<br /><br />Основните класове отблизо: wxFrame<br /><br /> * прозорец, чиито размери и положение могат да бъдат променяни от потребителя<br /> * притежава "бордюр" и лента за заглавието(titlebar)<br /> * може да съдържа всякакви прозорци с изключение на wxFrame и wxDialog(например лента с менюта, лента с инструменти(toolbar) и лента за състоянието(statusbar))<br /><br />Основните класове отблизо: wxDialog<br /><br /> * прозорец с лента за заглавието и евентуално системно меню в нея<br /> * може да бъде местен из екрана от потребителя<br /> * може да съдържа всякакви контроли вътре в себе си<br /> * обикновено се използва за предоставяне на възможност за избор на потребителя<br /> * има едно специално свойство: може да блокира изпълнението на програмата и възможността на потребителя да взаимодейства с други прозорци докато не направи необходимия избор в диалоговия прозорец<br /><br />Основните класове отблизо: wxPanel<br /><br /> * Прозорец в който могат да се слагат контроли<br /> * обикновено се съдържа в wxFrame за да не се поставят контролите директно в него<br /> * подобен по външен вид и функционалност на wxDialog, но с удобството че може да се съдържа във всякакъв вид прозорец<br /><br />Малко практика<br /><br />Да видим как изглежда казаното досега като код:<br /><br /> * Първо наследяваме wxApp:<br /><br /><br /> class MyApp(wx.App):<br /> def OnInit(self):<br /> frame = MyFrame(parent = None, title = "My own frame")<br /> frame.Show()<br /> self.SetTopWindow(frame)<br /> return True<br /> <br /><br /> * След това си дефинираме MyFrame като наследник на wxFrame:<br /><br /><br /> class MyFrame(wx.Frame):<br /> def __init__(self, parent, title, id = -1):<br /> wx.Frame.__init__(self, parent, id, title)<br /> panel = wx.Panel(parent = self)<br /> self.greeting = wx.StaticText(parent = panel, pos = (20, 20), label = "Hello pythoneers!")<br /> <br /><br /> * И накрая създаваме обект от MyApp:<br /><br /><br /> app = MyApp()<br /> app.MainLoop()<br /> <br /><br /> * Готово!<br /><br />Малки по-надълбоко: обработване на събития<br /><br />За да реагира на действията на потребителя, wxPython използва предварително зададени възможни събития( например натискане на бутон или преместване на прозореца) с които можете да асоциирате ваши функции които да обработват по желания от вас начин събитието. Това става като "свържете" някой прозорец с дадено събитие, което е възникнало в него, и с вашата функция която ще го обработи<br /><br />За удобство събитията не се виждат само от прозореца в който са възникнали, а и от всички прозорци нагоре в родителското дърво. Това означава че ако в панел имате няколко бутона, не е нужно събитието "натискане на бутон" да се прехваща във всеки бутон, може директо да ги прехванете в панела.<br /><br />Това става като извикате метода Bind на прозореца в който искате да прехванете събитието и му подадете типа събитие, функцията която ще се извика, и източника на събитието<br />Да си добавим меню в примера<br /><br />В конструктора на MyFrame добавяме:<br /><br /><br />menuBar = wx.MenuBar()<br /> menu = wx.Menu()<br /> menu.Append(self.ID_Exit, "E&xit")<br /> menuBar.Append(menu, "&File")<br /> menu = wx.Menu()<br /> menu.Append(self.ID_About, "&About")<br /> menuBar.Append(menu, "&Help")<br /> self.SetMenuBar(menuBar)<br /> <br /><br />Свързваме менютата с наши функции които искаме да се изпълнят когато менюте се избере:<br /><br /><br />self.Bind(wx.EVT_MENU, self.OnExit, id = self.ID_Exit)<br /> self.Bind(wx.EVT_MENU, self.OnAbout, id = self.ID_About)<br /> <br /><br />И добавяме handler`ите ни:<br /><br /><br />def OnExit(self, event):<br /> answer = wx.MessageBox("Do you really want to quit?", "Confirm", style = wx.YES_NO | wx.ICON_QUESTION)<br /> if answer == wx.YES: self.Close()<br /><br /> def OnAbout(self, event):<br /> wx.MessageBox("wxPython greeter program", "About", style = wx.OK)<br /> <br /><br />Как да си подредим бутончетата в прозореца<br /><br />При слагането на повече контроли в един прозорец става малко трудно да ги наредите всички така че да не си пречат. Указването на точна позиция(в координати) на всеки е дейност, достойна за наказание в програмисткия ад. Едно решение на проблема са така наречените sizers<br /><br />Sizer-ите разчитат на това че в повечето случаи разположението на обектите в прозореца следва прости геометрични правила като например в колона, редица или таблица. Използването им е съвсем просто - при създаване на прозорец създавате и sizer който ще отговаря за него, добавяте всички деца на прозореца в sizer-а и накрая не забравяте да кажете на прозореца кой му е sizer-a. След това sizer-а автоматично поема отговорността за разположението на обектите в прозореца<br /><br />При добавяне на обекти в sizer-а можете да укажете дали обекта ще се разширява при разширяване на целия прозорец и в какво съотношение в сравнение с останалите обекти в прозореца<br />Да позапълним прозореца<br /><br />Засега прозореца в приложението ни е много пуст и на самотния низ му е много скучно, а и му е писнало да поздравява само едни и същи хора. Нека му разнообразим съществуването: ще добавим поле в което да се казва кого ще поздравява програмата ни и бутон с който да поздравим въведеното същество<br /><br />За целта създаваме BoxSizer в конструктора на MyFrame и добавяме текста и новите контроли в него<br /><br /><br /> self.textField = wx.TextCtrl(panel, -1)<br /> self.greetButton = wx.Button(panel, ID_Greet, "Greet")<br /> buttonSizer = wx.BoxSizer(wx.HORIZONTAL)<br /> buttonSizer.Add(wx.StaticText(parent = panel, label = "Enter name:"), 0, wx.ALL, 10)<br /> buttonSizer.Add(self.textField, 1, wx.ALL | wx.EXPAND, 10)<br /> buttonSizer.Add(self.greetButton, 0, wx.ALL, 10)<br /> panelSizer = wx.BoxSizer(wx.VERTICAL)<br /> panelSizer.Add(self.greeting, 1, wx.ALL | wx.EXPAND | wx.CENTRE, 10)<br /> panelSizer.Add(buttonSizer, 0, wx.ALL | wx.EXPAND, 10)<br /> <br /> panel.SetSizer(panelSizer)<br /> panel.Fit()<br /> <br /> self.Bind(wx.EVT_BUTTON, self.OnGreet, self.greetButton)<br /><br /> frameSizer = wx.BoxSizer(wx.VERTICAL)<br /> frameSizer.Add(panel, 1, wx.EXPAND)<br /> self.SetSizerAndFit(frameSizer)<br /> <br /><br />Да позапълним прозореца 2<br /><br />Остана да добавим handler-а за новия бутон:<br /><br /><br />def OnGreet(self, event):<br /> name = self.textField.GetValue()<br /> if len(name) == 0:<br /> wx.MessageBox("Enter a name to greet first", "Error", style = wx.OK | wx.ICON_EXCLAMATION)<br /> return<br /> self.greeting.SetLabel("Hello %s!" % name)<br /> self.Refresh()<br /> self.Update()Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-30574315394069522492009-01-17T11:22:00.001-08:002009-01-17T11:22:49.349-08:00Някои добри практики в Python„ Програмиране с Python“, ФМИ<br />Стефан Кънев & Николай Бачийски<br />30.05.2007г.<br />Какво прави следния код?<br /><br /><br />for x in range(0, 12):<br /> print arr[x]<br /><br />А този?<br /><br /><br />fox index in range(0, NUMBER_OF_MONTHS):<br /> print monthNames[index]<br /><br />Писането на код като работа<br /><br />Когато пишете код, рядко го правите самоцелно. Вместо това, вие опитвате се да решите някакъв реален проблем със собствена логика, терминология и особености. Винаги когато пишете код трябва да се стараете той да отразява много добре този проблем - това го прави много по-четим, по-лесен за поддръжка и по-разбираем от външни хора. Още повече, така вие ясно показвате намерението което вашия код има, вместо да карате читателя да задълбава в особенностите на вашата реализация.<br />Първо правило: Добри имена на променливи<br /><br />Променливите обикновенно отговарят за съществуващи обекти/концепции в реалния проблем, който решавате. Това ги прави идеални за комуникиране на идеята на кода. За целта, обаче, се налага да избирате смислени имена.<br /><br /> * Използвайте смислени имена, които да показват ясно и недвусмислено за какво служи променливата<br /> * Спазвайте конвенция в именуването на нещата<br /> * Избягвайте думи, в които лесно се допускат правописни грешки<br /> * Избягвайте криптични съкращения или дълги имена - numberOfPeopleOnTheUsOlympicTeam, npot, teamMemberCount<br /> * Избягвайте като цяло безсмислени имена - thing, stuff, foo<br /> * Бъдете консистенти в наименоването на променливите - без shipsCount и numDocks в една програма.<br /> * Не използвайте една променлива два пъти за едни и същи неща.<br /><br />Типична грешка<br /><br /><br /># Грешно<br />temp = sqrt(b ** 2 - 4 * a * c)<br />x1 = (-b + temp) / (2 * a)<br />x2 = (-b - temp) / (2 * a)<br /><br /># По-правилно<br />discriminant = sqrt(b ** 2 - 4 * a * c)<br />x1 = (-b + discriminant) / (2 * a)<br />x2 = (-b - discriminant) / (2 * a)<br /><br />Лоши имена...<br /><br /><br />old = readOld()<br />tupple = getValues(r'c:\')<br />tup = {}<br />for t in tupple:<br /> if old[t] != tupple[t]: continue<br /> tup.update({t:tupple[t]})<br /><br />show(tup)<br />save(tupple)<br /><br />...и добри имена<br /><br /><br />oldHashsums = readCachedHashsums()<br />newHashsums = findHashsums(r'c:\')<br /><br />changedFiles = {}<br />for filename in oldHashsums:<br /> if oldHashsums[filename] != newHashsums[filename]:<br /> changedFiles[filename] = newHashsums[filename]<br /><br />reportChanges(changedFiles)<br />saveHashsums(newHashsums)<br /><br />Функции / методи / рутини<br /><br />Рутините са едно от най-често използваните средства в програмирането. И все пак, причините за които има смисъл да създавате рутина са.<br /><br /> * Опростяване на кода.<br /> * Избягване на повтаряне на код.<br /> * Скриване на последователни действия.<br /> * Разширяемост.<br /> * Подобряване на производителността.<br /> * За по-гъвкаво наследяване.<br /> * Изолиране на сложността.<br /> * Скриване на имплементационни детайли.<br /> * Като цяло: за създаване на абстракция.<br /><br />Именуване на рутини<br /><br />При именуване на рутини се съобразявайте внимателно със следните неща.<br /><br /> * Да обяснява всичко което рутината прави<br /> * Избягвайте безсмислени и размити имена - doStuff(), generateData(), processInput().<br /> * Не различавайте две рутини само по имена - wait2() и wait3().<br /> * Ако рутината връща стойност, кръстете я така че да описва връщаната стойност<br /> * Ако рутината е "процедура", използвайте глагол в името й, който да описва действието й.<br /> * Използвайте противоположни имена - add/remove, open/close, get/set - консистентно.<br /><br />Кохезия<br /><br />"Кохезията" на една рутина смътно описва действието й. Като говорим за "добра кохезия" имаме предвид, че една рутина прави едно единствено нещо и го прави добре. Най-силния вид "кохезия" е функционалната. Други видове са:<br /><br /> * Последователна кохезия - рутината капсулира няколко действия, които трябва да се направят последователно.<br /> * Комуникационна кохезия - рутината извършва няколко различни операции над едни и същи данни<br /> * Времева козехия - рутината извършва няколко действия, които трябва да станат едновременно - Startup(), Shutdown()<br /><br />Неприемлив вид кохезия<br /><br /> * Процедурна - когато рутината е създадена само защото това отговаря на последователността в която потребителя извършва действията.<br /> * Логическа - поведението на рутината зависи силно от стойността на някой параметър.<br /> * Случайна - когато действията в рутината не са особено свързани.<br /><br />Аргументи на рутините<br /><br /> * Действието на една рутина не трябва да зависи от стойностите на неин аргумент.<br /> * Старайте се да не ползвате повече от 7 (седем) аргумента в една рутина<br /> * Когато извиквате рутина с много аргументи, хубаво е да ползвате възможността на Python да предава аргументите наименовано.<br /> * Не променяйте състоянието на параметрите на функциите, ако може да го избегнете.<br /> * Ако ползвате параметри за изход, тогава избягвайте да ги ползвате и като входни.<br /> * Ако евентуално имате нужда от параметри за вход, вход-изход и изход, подреждайте ги консистентно в програмата си.<br /><br />Реакция при грешни параметри на рутината<br /><br />Лош подход.<br /><br /><br />def storePerson(name, age, address):<br /> if not isinsntace(name, str) or len(name) < 6: <br /> raise ValueError("Illegal name")<br /> if not isinstance(age, int, long) or age < 0:<br /> raise ArithmeticError("Illegal age")<br /> if not hasattr(address, "street") or not hassattr(address, "number"):<br /> raise ValueError("Illegal address")<br /> <br /> storeData(name, age, address.street, address.number)<br /><br />Реакция при грешни параметри на рутината (2)<br /><br />По-добър подход.<br /><br /><br />def storePerson(name, age, address):<br /> assert long(age) >= 6<br /> assert isinstance(name, str) and len(name) >= 6<br /> <br /> storeData(name, age, address.street, address.number)<br /><br />Не ползвайте глобални променливи<br /><br />Когато пиеше функции, не ползвайте глобални променливи. Ама въобще. Най-честия случай на неправилно ползване на глобавни променливи е когато се употребяват за комуникация между функции. Никога не правете това. В рядките случаи, в които имате нужда от "глобални" обекти правете Singleton-и или thread.local-и.<br />Не ползвайте goto<br /><br />В Python няма goto. Ако случайно пишете на друг език, в който има goto, това правило остава - не ползвайте goto.<br />Не използвайте глупави низове<br />в съобщенията за грешка<br />Основната задача на програмиста: да намалява сложността<br /><br />Подходи за намаляване на сложността:<br /><br /> * Модуларизация<br /> * Абстракия<br /> * ЕнкапсулацияUnknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-91744311791249049122009-01-17T11:21:00.000-08:002009-01-17T11:22:10.965-08:00Нишки в Python„ Програмиране с Python“, ФМИ<br />Стефан Кънев & Николай Бачийски<br />28.05.2007г.<br />Многозадачност<br /><br />Класически проблем е да накараме една програма да върши няколко неща едновременно. Има два стандартни подхода в повечето езици - fork-ове и нишки. Както можете да очаквате, те се срещат в Python в модулите os и threading.<br />fork<br /><br />fork е функция, чието изпълнение създава ново копие на програмата, което продължава от същото място където е извикана функцията. Досега заделените ресурси са общи за двата процеса, докато новите са локални. Създава се нов процес на ниво операционна система. В родителския процес функцията връща id-то на дъщерния, докато във дъщерния връща 0.<br /><br /><br />import os<br /><br />print "pre-forking"<br />pid = os.fork()<br />print "post-forking", pid<br /><br />pre-forking<br />post-forking 0<br />post-forking 6450<br /><br />fork (2)<br /><br />Отделни процеси могат да си комуникират по-успешно с други функции в модула os. Като цяло fork е твърде примитивен подход когато имате нужда от конкурентност в приложението и в почти всички случаи е много по-добре да използвате по-високо ниво на абстракция - нишки.<br />thread и threading<br /><br />Python предлага два модула за работа с нишки - thread и threading. Втория предлага по-високо ниво на абстракция и по-удобен интерфейс. Съответно е по-логичния избор от двата модула, ако нямате смислена причина да предпочетете thread.<br />threading.Thread<br /><br />Класът Thread ви дава прост механизъм да изпълнявате код в нова нишка. Нужно е да предоставите метод run, който да съдържа кода на нишката. След това я инстанцирате и викате методът и start.<br /><br /><br />import threading<br /><br />class MyThread(threading.Thread):<br /> def run(self):<br /> for i in range(0, 10000): print i<br /><br />thread = MyThread()<br />thread.start()<br />for i in range(0, 10000): print -i<br /><br />theading.Lock<br /><br />Стандартен проблем при конкуренти задачи са "критични секции" от програмата - такива, които трябва да бъдат изпълнявани само веднъж в даден момент. Това може да се постигне с класът Lock. Неговите инстанции имат два метода - acquire() и block(). Класът вътре пази флаг дали lock-а е свободен или зает. Ако acquire() се извика на свободен lock, флага се вдига и lock-а става зает. Ако acquire() се извика на зает lock, метода блокира докато lock-а не се освободи. Извикването на release() освобождава lock-а.<br />theading.Lock (2)<br /><br /><br />import threading<br /><br />lock = threading.Lock()<br /><br />class Gatherer(threading.Thread):<br /> def run(self):<br /> while True:<br /> foundStuff = gather()<br /> lock.acquire()<br /> for thing in foundStuff: report(thing)<br /> lock.release()<br /><br /><br />g1, g2 = Gatherer(), Gatherer()<br />g1.start()<br />g2.start()<br /><br />threading.Lock (3)<br /><br />Можете да използвате with с Lock.<br /><br /><br />from __future__ import with_statement<br />import threading<br /><br />lock = threading.Lock()<br />with lock:<br /> print "Do stuff"<br /><br />threading.Semaphore<br /><br />Semaphore представлява механизъм за разрешаване на конкурентен достъп, много подобен на Lock разликата е там, че вместо флаг, вътрешно се пази брояч. acquire() го намалява, докато release() го увеличава. acquire() се разблокира, когато брояча е по-голям от нула и блокира, ако той е нула.<br />threading.Event<br /><br />Event е проста комуникация между нишки, в която няколко нишки изчакват една да завърши с някакъв резултат. Нишките които изчакват викат метода wait() и изпълнението им блокира. Нишката, която продуцира резултата извиква метода set(). В този момент всички нишки които чакат продължават изпълнението си.<br />threading.Condition<br /><br />Condition е много сходен с Lock, но дава няколко нови метода. wait() освобождава lock-а, след което блокира докато не се събуди с извикване на notify() или notifyAll(). Като се "събуди", отново взема lock-а. notify() събужда една нишка, заспала с wait(). notifyAll() събуджа всички.<br /><br /><br /># Consume one item<br />cv.acquire()<br />while not an_item_is_available():<br /> cv.wait()<br />get_an_available_item()<br />cv.release()<br /><br /># Produce one item<br />cv.acquire()<br />make_an_item_available()<br />cv.notify()<br />cv.release()<br /> <br /><br />threading.local<br /><br />Инстанциите на local представляват обекти, които са "локални" за дадена нишка. Тяхните атрибути са уникални за всяка нишка. Например:<br /><br /><br />import threading<br />foo = threading.local()<br /><br />foo.blah = 1<br /><br />class MyThread(threading.Thread):<br /> def run(self):<br /> if (hasattr(foo, 'blah')): print "MyThread sees foo.blah"<br /> foo.blah = 4<br /> print "MyThread(foo.blah) = ", foo.blah<br /> <br />MyThread().start()<br />print "BaseThread(foo.blah) = ", foo.blahUnknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-66994652674065215682009-01-17T11:20:00.000-08:002009-01-17T11:21:28.120-08:00Метакласове в Python„ Програмиране с Python“, ФМИ<br />Стефан Кънев & Николай Бачийски<br />11.04.2007г.<br />Метакласове<br /><br />Метакласовете са инструмент, който ще ползвате в много малко случаи и клиента на вашия код винаги ще е друг програмист. Те помагат за създаване на по-устойчиви и използваеми абстракции, а не решават проблеми директно. Въпреки това, те имат големи възможности и можете да постигнете с тях много неща по елегантен начин. Имайте предвид, че всичко което можете да постигнете с метакласове може да стане и със стандартни способи.<br />Концепцията<br /><br />Метакласовете представляват "типове" на класовете. Тези типове определят механиката и правилата на които класът се подчинява. Пример биха могли да бъдат класовете нов и стар стил, които работят по различни правила. Но като нищо може да си измислим и наши типове класове. Например:<br /><br /> * singleton-и<br /> * класове, чиито методи при грешка просто връщат None<br /> * класове, чиито методи получават self неявно<br /><br />Singleton<br /><br /><br />class DatabaseConnector(object):<br /> self = None<br /> def __new__(cls):<br /> if not DatabaseConnector.self:<br /> DatabaseConnector.self = object.__new__(cls)<br /> return DatabaseConnector.self<br /><br />class Mailer(object):<br /> self = None<br /> def __new__(cls):<br /> if not Mailer.self:<br /> Mailer.self = object.__new__(cls)<br /> return Mailer.self<br /><br />mailer1 = Mailer()<br />mailer2 = Mailer()<br />print mailer1 is mailer2 # True<br /><br />Същото, но с метакласове<br /><br /><br />class singleton(type):<br /> def __new__(cls, name, bases, classDict):<br /><br /> def getInstance(klass):<br /> if not klass.self:<br /> klass.self = object.__new__(klass)<br /> return klass.self<br /><br /> classDict['self'] = None<br /> classDict['__new__'] = getInstance<br /><br /> return type.__new__(cls, name, bases, classDict)<br /><br />class Mailer(object):<br /> __metaclass__ = singleton<br /><br />mailer1 = Mailer()<br />mailer2 = Mailer()<br />print mailer1 is mailer2<br /><br />Класове, чиито методи не хвърлят грешки<br /><br /><br />def silent(func):<br /> def wrapper(*args, **kwargs):<br /> try:<br /> return func(*args, **kwargs)<br /> except:<br /> return None<br /> return wrapper<br /><br />class Something(object):<br /> @silent<br /> def foo(self): assert false<br /><br /> @silent<br /> def bar(self): print belch<br /><br /> @silent<br /> def omgTooMuchDecorators(self): pass<br /><br />something = Something()<br />something.foo()<br /><br />Отново, с метакласове<br /><br /><br />def silent(func):<br /> def wrapper(*args, **kwargs):<br /> try:<br /> return func(*args, **kwargs)<br /> except:<br /> return None<br /> return wrapper<br /><br />class silentType(type):<br /> def __new__(cls, name, bases, classDict):<br /> for name, attr in classDict.items():<br /> if callable(attr):<br /> classDict[name] = silent(attr)<br /><br /> return type.__new__(cls, name, bases, classDict)<br /> <br />class Something(object):<br /> __metaclass__ = silentType<br /> def foo(self): assert false<br /> def bar(self): print belch<br /> def omgTooMuchDecorators(self): pass<br /><br />something = Something()<br />something.foo()<br />something.bar()<br /><br />Класове без self<br /><br /><br />class Person(object):<br /> __metaclass__ = selfless<br /> def __init__(name, age):<br /> self.name = name<br /> self.age = age<br /><br /> def __repr__():<br /> return "Person(%s, %d)" % (repr(self.name), self.age)<br /><br /> def sayHi():<br /> print "Hello, I'm %s and I'm %d years old" % (self.name, self.age)<br /><br /> def rename(newName):<br /> self.name = newName<br /><br />Класове без self (2)<br /><br /><br />from types import FunctionType<br /><br />class selfless(type):<br /> def __new__(cls, name, bases, classDict):<br /> for attr in classDict:<br /> if not isinstance(classDict[attr], FunctionType): continue<br /> classDict[attr] = selflessWrapper(classDict[attr])<br /> return type.__new__(cls, name, bases, classDict)<br /><br />def selflessWrapper(func):<br /> def wrapper(self, *args, **kwargs):<br /> hadSelf, oldSelf = func.func_globals.has_key('self'), <br /> func.func_globals.get('self')<br /> func.func_globals['self'] = self<br /> returnValue = func(*args, **kwargs)<br /> if hadSelf:<br /> func.func_globals['self'] = oldSelf<br /> else:<br /> del func.func_globals['self']<br /> return returnValue<br /> wrapper.func_name = func.func_name + "_wrapper"<br /> return wrapperUnknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-41644949987742091432009-01-17T11:19:00.002-08:002009-01-17T11:21:45.719-08:00Пак Метакласове в Python„ Програмиране с Python“, ФМИ<br />Стефан Кънев & Николай Бачийски<br />16.05.2007г.<br /><br /> [Metaclasses] are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why).<br /><br /> Tim Peters<br /><br />Какво е метаклас?<br /><br /><br />Метаклас — клас, чийто инстанции са класове.<br /><br /><br />Забравете предишнoto твърдение.<br />Метапрограмиране<br /><br /> * Meta (from Greek: μετά = "after", "beyond", "with"), is a prefix used in English in order to indicate a concept which is an abstraction from another concept, used to complete or add to the latter.<br /> * Програмиране за програмирането.<br /> * Програмиране, при което клиентите са програмисти.<br /> * При ООП:<br /> o разширяване на езика с нови ”типове класове“<br /> o промяна на природата на обектите<br /> + добавяне на функционалност (методи от метакласа например)<br /> + създаване на обекти, които приличат на класове (от които могат да се правят нови инстанции)<br /> + налагане на ограничения върху класовете<br /> o автоматизиране на сложни задачи<br /> + регистриране на новосъздадени класове в някаква система<br /><br />Метакласовете като инструмент за метапрограмиране<br /><br /> * Почти всичко може да се направи и без метакласове:<br /> o factory класове<br /> o функции, които обработват класа след създаването му<br /> o функции, които регистрират новосъздадения клас в системата<br /> * С метакласове просто е по-лесно и по-елегантно<br /> * Използват се вътрешно в типовата система на Python<br /><br />Употреба: регистрация/търсене<br /><br />Искаме да видим всички класове, които са се регистрирали в нашата система.<br /><br />Пример: имаме зоологическа градина с цяла йерархия от класове, като позволяваме на програмистите да дефинират нови класове от животни. Как да видим всички класове животни? Как да видим всичко животни, които могат да плуват? Как да намерим всички животни наследник на класа Риба?<br />Употреба: проверки при създаване на класове<br /><br /> * Гаранция, че класът удовлетворява определен интерфсейс<br /> * Проверка за стил на кода:<br /> o наличие на docstring-ове<br /> o имена на методи — getName срещу get_name<br /> o дълбочина на наследяването — ≤ 5<br /> * Всякакви други проверки, които ще гарантират, че нмовосъздадения клас отговаря на изискванията на вашата система<br /><br />Внимавайте да не сте много строги.<br />Употреба: създаване на специални класове<br /><br /> * обвиване на методи (pre/post conditions)<br /> * добавяне, преименуване на методи<br /> * зареждане на методи/родители от някъде:<br /> o зависещи от системата: разширения (plugins)<br /> o XML схеми и DTD<br /><br />В Python<br /><br /> * при създаване на тялото на клас се гледа стойността на __metaclass__<br /> * по подразбиране метакласа е type или types.ClassType (стар стил)<br /> * метаклас може да се наследи и от родителски клас<br /><br />Какво може/трябва да има един метаклас?<br /><br /> * (Мета)класовете са частен случай на обикновени обекти — с техните методи, свойства<br /> * Всичко основно може да се наследи от type и за нас не остава кой знае колко за добавим<br /> * Най-често се променят:<br /> o Инициализатори: __new__, __init__<br /> o Представяне на класовете като низове<br /> o Атрибути и свойства на новия клас (включително методи:)<br /> * Не могат да се ползват за промяна на логиката на:<br /> o търсене в пространсвата от имена<br /> o MRO (Method Resolution Order)<br /> o Дескрипторите (за тях по-нататък)Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-27474086857921960032009-01-17T11:19:00.001-08:002009-01-17T11:19:40.990-08:00Регулярни изрази в Python<div class="presentation"> <div class="slide"> <h1>
<br /></h1> <h3>„ Програмиране с Python“, <acronym title="Факултет по Математика и Информатика при Софийски Университет">ФМИ</acronym></h3> <h4>28.02.2007г.</h4> </div> <div class="slide"> <h1>Идеята</h1> <p>Регулярните изрази се използват за търсене и заместване в текст. Те предлагат апарат, с който дефинирате шаблони, описващи последователност от символи, след което да проверявате дали даден текст съдържа съответния шаблон. Основават се на идея от дискретната математика, макар че реализацията им в езиците за програмиране е доста по-сложна.</p> </div> <div class="slide"> <h1>Прост пример</h1> <ul><li>на <code>pam</code> съответстват <code>spam</code> и <code>pamela</code></li><li>на <code>h(ot|ound) dog</code> съответстват <code>hot dog</code> и <code>hound dog</code></li><li>на <code>fn\d+</code> съответстват <code>fn1</code>, <code>fn44444</code>, <code>fn420169</code> и т.н.</li><li>на <code>.at</code> съответстват <code>hat</code>, <code>cat</code>, <code>rat</code> и т.н.</li><li>на <code>[a-zA-Z0-9._]+@[a-aA-Z0-9._]+\.[a-z]+</code> съответстват повечете email адреси</li></ul> </div> <div class="slide"> <h1>В детайли</h1> <ul><li>Регулярните изрази представляват текстови низове</li><li>Буквите и цифрите съответстват на себе си</li><li>Точката съответства на всеки символ, без новия ред</li><li><code>\d</code> съответства на цифра</li><li><code>\w</code> съответства на буква</li><li><code>\s</code> съответства на бяло пространство</li><li><code>\D</code>, <code>\W</code> и <code>\S</code> са инверсии на съответните символи</li></ul> </div> <div class="slide"> <h1>В детайли (2)</h1> <ul><li><code>\d\d\d\d\d\d\d</code> съответства на ЕГН</li><li><code>\w\w\w\d\w\w\d\d</code> съответства на три букви, цифра, две букви и после две цифри (например <code>ani4ka92</code>)</li><li><code>fn\d\d\d\d\d</code> съответства на част от факултетните номера</li><li><code>M\w\w\w\w\sT\w\w\sP\w\w\w\w\w</code> би хванало <code>Mityo The Python</code></li><li><code>s..m</code> съответства на <code>spam</code> и <code>sram</code></li></ul> </div> <div class="slide"> <h1>В Python</h1> <p>В Python се ползва модулът <code>re</code></p> <pre><code>import re
<br />>>> import re
<br />>>> re.search('spam', 'gmail')
<br />>>> re.search('s..m', 'spam')
<br /><_sre.sre_match>
<br />>>> re.search('\\d\\d', 'asnwer: 42')
<br /><_sre.sre_match>
<br /></code></pre> </div> <div class="slide"> <h1>Още детайли</h1> <ul><li>Операторът <code>|</code> в регулярните изрази означава това отляво или това отдясно</li><li><code>(c|h)at</code> намира <code>cat</code> и <code>hat</code> </li><li><code>^</code> съвпада с началото на низа. <code>^oo</code> ще намери <code>oop</code>, но не и <code>foo</code>.</li><li><code>$</code> съвпада с края на низа. <code>ar$</code> ще намери <code>bar</code>, но не и <code>argh</code>.</li></ul> </div> <div class="slide"> <h1>Повторения</h1> <ul><li><code>?</code> означава, че да го има 0 или 1 пъти</li><li><code>+</code> означава, че нещо може да го има един или повече пъти</li><li><code>*</code> означава, че нещо може да го има нула или много пъти</li><li><code>{x, y}</code> означава, че нещо може да го има от <code>x</code> до <code>y</code> пъти</li></ul> Примери: <pre>\d{8}
<br />fn\d+
<br />\d{1,2}\.\d{1,2}.\d{4}
<br />route\d*
<br /></pre> </div> <div class="slide"> <h1>Класове</h1> <ul><li>Класовете съответстват на някакво множество от символи.</li><li>Бележат се с <code>[]</code>.</li><li><code>[chr]at</code> съответства на <code>cat</code>, <code>hat</code> и <code>rat</code>.</li><li>Могат да включват и последователности от символи - <code>[a-z0-8]</code> съответства на малка буква или цифра, без 9</li><li> Ако започва с <code>^</code>, класът се интерпретира като отрицание на символите вътре - <code>[^A-Z]</code> съответства на нещо, което не е голяма буква </li></ul> </div> <div class="slide"> <h1>Област</h1> <p>Върнатия от <code>search</code> обект има методи <code>start</code>, <code>end</code> и <code>span</code>.</p> <pre><code>
<br />>>> import re
<br />>>> text = 'Bla bla bla mityo blabla bla'
<br />>>> match = re.search(r'mityo', text)
<br />>>> match.span()
<br />(12, 17)
<br />>>> match.start(), match.end()
<br />12, 17
<br />>>> text[match.start(), match.end()]
<br />'mityo'
<br /></code></pre> </div> <div class="slide"> <h1>Групи</h1> <p>Всички изрази оградени със скоби се запазват в обекта върнат от re.search. Те се наричат групи</p> <pre><code>
<br />>>> import re
<br />>>> match = re.search(r'\w+ (\w+), fn(\d+)',
<br /> 'Nickolay Bachiiski, fn43600')
<br />>>> match.group(1)
<br />'Bachiiski'
<br />>>> match.group(2)
<br />'43600'
<br /></code></pre> </div> <div class="slide"> <h1>Субституции</h1> <p>Всички изрази оградени със скоби се запазват в обекта върнат от re.search. Те се наричат групи</p> <pre><code>
<br />>>> import re
<br />>>> re.sub(r':(.*)!', r'!\1?', "I'm a :very big! hacker!")
<br />"I'm a !very big hacker?"
<br /></code></pre> </div> <div class="slide"> <h1>Алчни "квантификатори"</h1> <p><code>+</code>, <code>*</code> и <code>{x,y}</code> намират максималния брой символи, които могат. Това се нарича "алчно поведение" (greedy). Ако искате да намирате минималния брой, добавете едно ? към края</p> <pre><code>
<br />>>> import re
<br />>>> re.sub(r'<b>(.*)</b>', r'<strong>\1</strong>',
<br /> 'My name is <b>Mityo</b> the <b>Python</b>')
<br />'My name is <strong>Mityo</b> the <b>Python</strong>'
<br />
<br />>>> re.sub(r'<b>(.*?)</b>', r'<strong>\1</strong>',
<br /> 'My name is <b>Mityo</b> the <b>Python</b>')
<br />'My name is <strong>Mityo</strong> the <b>Python</b>'
<br /></code></pre> </div> </div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-83629263475810218882009-01-17T11:17:00.002-08:002009-01-17T11:18:23.187-08:00Още за типовете и обектите в Python<div class="slide"> <h1><br /></h1> <h3>„ Програмиране с Python“, <acronym title="Факултет по Математика и Информатика при Софийски Университет">ФМИ</acronym></h3> <h3>Стефан Кънев & Николай Бачийски</h3> <h4>14.05.2007г.</h4> </div> <div class="slide"> <h1>За какво ще става дума</h1> <ul><li>Разпознаване на типове</li><li>Копиране на обекти</li><!-- <li>Отпечатване на обекти, годни за интерпретация</li> <li>Слаби връзки към обекти</li> --><li>Наследяване на вградени типове</li></ul> </div> <div class="slide long"> <h1>type</h1> <ul><li><code>type</code>връща специален обект от тип тип, стойност годна само за директни проверки</li><li class="code"><pre><code>def update(val):<br /> if type(val) == type(0):<br /> _update(val)<br /> else:<br /> raise ValueError("Cannot update non-integer!")</code></pre></li><li class="code"><pre><code>>>> type('baba')<br /><type></code></pre></li><li class="code"><pre><code>>>> type([])<br /><type></code></pre></li><li class="code"><pre><code>>>> type(type('sugrug'))<br /><type></code></pre></li></ul> </div> <div class="slide long"> <h1>Модулът <code>types</code></h1> <ul><li>Ако става дума за вграден тип, <code>type</code> връща обект, който може да бъде намерен в модула <code>types</code></li><li class="code"><pre><code><br />from types import *<br />def update(val):<br /> if type(val) == IntType:<br /> _update(val)<br /> else:<br /> raise ValueError("Cannot update non-integer!")</code></pre></li><li>В този модул може да намерите повечето вградени типове, като имената им са с главни букви и имат <code>Type</code> отзад: <code>DictType</code>, <code>ListType</code>, <code>TupleType</code>, <code>BuiltinFunctionType</code> и т.н.</li></ul> </div> <div class="slide long"> <h1>Копиране на обекти</h1> <ul><li><code>a = b</code> <strong>не</strong> копира стойностите, а насочва <code>a</code> и <code>b</code> към един и същи обект!</li><li>Идиом за <em>плитко</em> копиране на списъци: <code>newlist = l[:]</code></li><li>Още един идиом за плитко копиране: <code>newlist = [x for x in l]</code>, прави същото като горния</li><li class="code"><pre><code>names = 'a b c'.split()<br />grades = [1, 2, 3]<br />both = [names, grades]<br />shallowCopy = both[:]<br />names.append('d')<br />print shallowCopy[0]</code></pre></li><li>Така копираме елементите само на едно ниво.</li></ul> </div> <div class="slide longlong"> <h1>Плитко копиране на произволни обекти</h1> <ul><li>Не винаги си имаме работа със писъци, понякога не е толкова лесно да копираме един обект.</li><li>На помощ ни идва вградения модул <code>copy</code></li><li class="code"><pre><code>import copy<br />class C:<br /> def __init__(self, l): self.l = l<br /> def __getitem__(self, i): return self.l[i]<br />items = [1, 2, 3]<br />c = C(items)<br />shallow = copy.copy(c)<br />print c[2], shallow[2]<br />(3, 3)<br />items.append(4)<br />print c[3], shallow[3]<br />(4, 4)<br />shallow.l = [42]<br />print c.l, shallow.l<br />([1, 2, 3, 4], [42])</code></pre></li></ul> </div> <div class="slide long"> <h1>Дълбоко копиране</h1> <ul><li>Защо е необходимо?</li><li class="code"><pre><code>import copy<br />items = [1, 2, 3]<br />d = dict(items=items)<br />shallow = copy.copy(d)<br />deep = copy.deepcopy(d)<br />items.append(4)<br />print shallow['items'], deep['items']</code></pre></li></ul> </div> <div class="slide long"> <h1>В картинки (1)</h1> <pre><code>items = [1, 2, 3]<br />d = dict(items=items)<br />shallow = copy.copy(d)<br />deep = copy.deepcopy(d)</code></pre><br /><img src="file:///C:/Documents%20and%20Settings/Ivaylo.Ivanov/Desktop/pt/15-files/copy_before.png" alt="state and references before the items modification" /> </div> <div class="slide long"> <h1>В картинки (2)</h1> <pre><code>items.append(4)</code></pre><br /><img src="file:///C:/Documents%20and%20Settings/Ivaylo.Ivanov/Desktop/pt/15-files/copy_after.png" alt="state and references after the items modification" /> </div> <div class="slide"> <h1>Наследяване на вградени типове</h1> <ul><li>Цел: създаване на обекти, които приличат на такива от някой вграден тип (речник, списък, низ)</li><li>Разширяване функционалността на вградени типове — речник, чийто ключове могат да се достъпват и като атрибути</li><li>Удобство — ако обектът ни има поведение на списък, по-добре да ползваме познатия писъчен протокол, вместо да измисляме нови методи</li></ul> </div> <div class="slide"> <h1>Без наследяване</h1> <ul><li>Можем да постигнем целта си и без наследяване</li><li>Ако имате желание да дефинирате сами всички методи на <code>list</code>, огромна част, от които се припокриват като функционалност с тези от вградените списъци</li><li>Понякога е удачно: трябва ни само индексиране(<code>[]</code>, <code>__getitem__</code>) и не искаме да си замърсяваме класа с всички методи на <code>list</code></li></ul> </div> <div class="slide longlong"> <h1>Старият начин</h1> <p>Преди 2.3 не е било възможно стандартните класове като <code>list</code>, <code>dict</code>, <code>str</code> да се наследяват. Използвали са се няколко стандартни модула, които са предоставяли специални класове, които да бъдат наследявани:</p> <ul><li><code>UserDict.UserDict</code> — речник, който не поддържа итерация (за съвместимост със стари версии)</li><li><code>UserDict.IterableUserDict</code> — речник, който си поддържа и итерация</li><li><code>UserDict.DictMixin</code> — добавя стандартните методи на класове, които вече поддържат стандартния интерфейс: <code>__getitem__()</code>, <code>__setitem__()</code>, <code>__delitem__()</code>, <code>keys()</code>.</li><li><code>UserList.UserList</code></li><li><code>UserString.UserString</code></li><li><code>UserString.MutableString</code> — малко по-различен низ, може да бъде променян в движение</li></ul> <p>Всички си имат по един атрибут <code>data</code>, в който се пазят реално данните.</p> </div> <div class="slide long"> <h1>Пример: речник с атрибути</h1> <pre><code>class AttrDict(dict):<br /> def __getattr__(self, attr):<br /> if attr in self:<br /> return self[attr]<br /> else:<br /> raise AttributeError("exists neither an attribute nor a key called '%s'." % attr)<br /><br />if __name__ == "__main__":<br /> d = AttrDict(a = 5, get = 6)<br /> print d.a<br /> print d.get<br /> print d.baba</code></pre> </div> <div class="slide longlong"> <h1>Частичен пример: низове с case-insensitive сравнения</h1> <pre><code>def lowerFuncs(*names):<br /> def lowerFunc(clsname, bases, classDict):<br /> for name in names:<br /> def comparator(self, other, *args, **kwargs):<br /> return getattr(str, name)(self._lower, other.lower(), *args, **kwargs)<br /> classDict[name] = comparator<br /> return type(clsname, bases, classDict)<br /> return lowerFunc<br /><br />class CIStr(str):<br /> __metaclass__ = lowerFuncs('__eq__', '__le__', '__lt__', '__ge__', '__gt__')<br /><br /> def __init__(self, *args, **kwargs):<br /> str.__init__(self, *args, **kwargs)<br /> # string will never change, so calc once<br /> self._lower = self.lower()<br /> def startswith(self, prefix, *args, **kwargs):<br /> return str.startswith(self.__lower, prefix.lower(), *args, **kwargs)<br /> def index(sub, *args, **kwargs):<br /> return str.index(self.__lower, sub.lower(), *args, **kwargs)<br /> … # и така нататък...<br /><br />if __name__ == "__main__":<br /> s = CIStr("Baba")<br /> print s == "baba"</code></pre> </div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-1322753102931051062009-01-17T11:17:00.001-08:002009-01-17T11:18:49.167-08:00Сериализация в Python<div class="slide"> <h1><br /></h1> <h3>„ Програмиране с Python“, <acronym title="Факултет по Математика и Информатика при Софийски Университет">ФМИ</acronym></h3> <h3>Стефан Кънев & Николай Бачийски</h3> <h4>11.04.2007г.</h4> </div> <div class="slide"> <h1>Проблем</h1> <p>Имаме нужда да пазим информация между две изпълнения на едно и също приложение. Искаме достъпа до тази информация да е лесен и да добавя минимално код в самото приложение. Нуждите на приложението са прости и няма да имаме нужда от конкурентен достъп или заключване на ресурси.</p> </div> <div class="slide"> <h1>Решение</h1> <p>Сериализация се нарича възможността да представяме обекти като поредица от байтове. По този начин те могат да бъдат записвани във файловата система или изпращани през TCP/IP и реконструирани в последствие.</p> </div> <div class="slide"> <h1>Pickle</h1> <p><code>pickle</code> е модул, който може да сериализира прости Python обекти. </p> <dl><dt><code>pickle.dump(<em>object</em>, <em>file</em>)</code></dt><dd>Приема отворен за писане файл <em>file</em> и Python обект <em>object</em>. Записва обекта в файла.</dd><dt><code>pickle.load(<em>object</em>)</code></dt><dd>Приема отворен за четене файл и прочита един обект, който е и резултат от функцията</dd></dl> </div> <div class="slide"> <h1>Pickle (2)</h1> <pre><code><br />from __future__ import with_statement<br />import pickle<br /><br />with open('/home/aquarius/foo.txt', 'w') as file:<br />pickle.dump("The answer", file)<br />pickle.dump(["spam", "eggs", "ham"], file)<br /><br />with open('/home/aquarius/foo.txt', 'r') as file:<br />print pickle.load(file)<br />print pickle.load(file)<br /></code></pre> </div> <div class="slide"> <h1>Какво представлява сериализацията?</h1> <p><code>Pickle</code> сериализира обектите с един от три различни протокола. Протокола по подразбиране представя обектите като ASCII низове. Функциите <code>dumps</code> и <code>loads</code> връщат сериализирана форма вместо да я записват във файл.</p> <pre><code><br />import pickle<br /><br />serializedList = pickle.dumps(["spam", "eggs", "ham"])<br />print repr(serializedList)<br /></code></pre> <pre style="color: green;">"(lp0\nS'spam'\np1\naS'eggs'\np2\naS'ham'\np3\na."<br /></pre> </div> <div class="slide"> <h1>Какво може да се сериализира?</h1> <ul><li><code>True</code>, <code>False</code> и <code>None</code></li><li><code>int</code>, <code>long</code>, <code>float</code> и <code>complex</code></li><li><code>str</code> и <code>unicode</code></li><li>Списъци, речници, множества и n-орки, които съдържат само обекти, които могат да се сериализират</li><li>Функции и класове, дефинирани в корена на модула</li><li>Вградени функции, дефинирани в корена на модула</li></ul> </div> <div class="slide long"> <h1>Сериализиране на един обект два пъти</h1> <p>Ако сериализирате сложна структура, в която един обект присъства два пъти (по адрес), <code>pickle</code> ще го сериализира еднократно.</p> <pre><code><br />import pickle<br /><br />primes = [2, 3, 5, 7, 11, 13]<br />answer = 42<br />things = [primes, answer, primes]<br />print things[0] is things[2] # True<br /><br />serialized = pickle.dumps(things)<br />newThings = pickle.loads(serialized)<br />print newThings[0] is newThings[2] # True<br /><br />print newThings[0] is things[0] # False<br /></code></pre> </div> <div class="slide long"> <h1>Pickler и Unpickler</h1> <p>Имате достъп до същата функционалност под формата на класове.</p> <pre><code><br />from __future__ import with_statement<br />import pickle<br /><br />with open('/home/aquarius/foo.txt', 'w') as file:<br />pickler = pickle.Pickler(file)<br />pickler.dump('Under the Violet Moon')<br />pickler.dump('Soldier of Fortune')<br />pickler.dump('Colubrid on the Tree')<br /><br />with open('/home/aquarius/foo.txt') as file:<br />unpickler = pickle.Unpickler(file)<br />print unpickler.load()<br />print unpickler.load()<br />print unpickler.load()<br /></code></pre> </div> <div class="slide long"> <h1>cPickle</h1> <p><code>cPickle</code> e реализация на <code>pickle</code> на C, което я прави доста по-бърза.</p> <pre><code><br />from __future__ import with_statement<br />import cPickle<br /><br />with open('/home/aquarius/foo.txt', 'w') as file:<br />cPickle.dump("The answer", file)<br />cPickle.dump(["spam", "eggs", "ham"], file)<br /><br />with open('/home/aquarius/foo.txt', 'r') as file:<br />print cPickle.load(file)<br />print cPickle.load(file)<br /></code></pre> </div> <div class="slide long"> <h1>cPickle (2)</h1> <p>За сравнение</p> <pre><code>import pickle<br />import cPickle<br />from timeit import Timer<br /><br />fancy = [[x ** 2 for x in range(0, 1000)], ["spam", "ham", "eggs"],<br /> ["-" * i for i in range(0, 1000)],]<br /><br />def pickleWith(pickler):<br />serialized = pickler.dumps(fancy)<br />restored = pickler.loads(serialized)<br /><br />print "pickle: ", Timer("pickleWith(pickle)", "from __main__ import *").timeit(50)<br />print "cPickle: ", Timer("pickleWith(cPickle)", "from __main__ import *").timeit(50)<br /><br /># pickle: 3.28504800797<br /># cPickle: 0.722439050674<br /></code></pre> </div> <div class="slide"> <h1>shelve</h1> <p><code>shelve</code> е сравнително прост модул, който позволява да записвате данни във файл под формата на речник. Можете да ги достъпвате в последствие по ключовете, с които сте ги записали. Всички обекти се сериализират посредством <code>pickle</code>, докато организацията им във файла става посредством dbm, gdbm или berkeley db.</p> </div> <div class="slide long"> <h1>shelve (2)</h1> <pre><code><br />import shelve<br /><br />db = shelve.open('/home/aquarius/foo.db')<br />db['name'] = 'Mityo the Python'<br />db['age'] = 33<br />db['favouriteBands'] = ["Blackmore's Night", "Deep Purple", "Rainbow"]<br />db['favouriteSong'] = "Colubrid on the Tree"<br />db.close()<br /><br />db = shelve.open('/home/aquarius/foo.db')<br />print db.keys()<br />print db['name']<br />print db['favouriteBands']<br />print db['favouriteSong']<br />db.close()<br /></code></pre> </div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-5795579166168863212009-01-17T11:16:00.000-08:002009-01-17T11:17:30.487-08:00Още тестване и документация - Python<div class="slide"> <h1><br /></h1> <h3>„ Програмиране с Python“, <acronym title="Факултет по Математика и Информатика при Софийски Университет">ФМИ</acronym></h3> <h3>Стефан Кънев & Николай Бачийски</h3> <h4>16.02.2007г.</h4> </div> <div class="slide"> <h1>Примерно пакетче с модули</h1> <p>Нека разгледаме модула <code>world</code></p> <ul><li><code>__init__.py</code></li><li><code>destroyer.py</code></li><li><code>god.py</code></li></ul> </div> <div class="slide"> <h1>Прости тестове: test_world.py</h1> <ul><li>клас наследник на <code>unittest.TestCase</code></li><li>всеки негов метод започващ с <code>test</code> е отделен сценарий</li><li><code>unittest.main</code> се грижи да намери подходящите класове и да извика подходящите им методи</li><li>просто!</li></ul> </div> <div class="slide"> <h1>setUp и tearDown</h1> <ul><li>понякога се налага да правим едно и също преди и след някой сценарий (метод на <code>TestCase</code>)</li><li>методът <code>setUp</code> на <code>TestCase</code> ще се извика преди всеки сценарий</li><li>методът <code>tearDown</code>ще се извика след всеки сценарий</li><li class="code"><pre><code>def setUp(self):<br /> self.w = world.World()<br />def tearDown(self):<br /> self.w = None</code></pre></li></ul> </div> <div class="slide"> <h1>Специален TestCase</h1> <ul><li><code>world.destroyer.do</code> отпечатва разни неща, които не искаме да виждаме по време на тестовете</li><li>можем да си направим наследник на <code>unittest.TestCase</code>, който има желаната функционалност</li><li>и ползваме негов наследник в случаите, в които ни трябва тази функционалност</li><li>Пример: <code>world.test.testcases</code></li></ul> </div> <div class="slide"> <h1>Под капака на unittest</h1> <ul><li><code>TestLoader</code></li><li><code>TestSuite</code></li><li><code>TestResult</code></li><li><code>TextTestRunner</code></li><li>Пример: <code>world.test</code></li></ul> </div> <div class="slide long"> <h1>Документация—Интернет</h1> <ul><li><a href="http://docs.python.org/">http://docs.python.org/</a> — обновена, удобна, ако знаете къде да търсите, това което ви трябва <ul><li><a href="http://docs.python.org/lib/lib.html">Library Reference</a>—систематизирано описание на функции, модули</li><li><a href="http://docs.python.org/modindex.html">Global Module Index</a>—азбучен списък с подробни описания на модулите</li><li><a href="http://docs.python.org/ref/ref.html">Language Reference</a>—синтактични правила, твърдения, оператори</li></ul> </li><li>често най-бързия начин да намерите, каквото ви е нужно е търсене в Google за <code>python <функция/метод/клас/…></code> <ul><li>Пример: <a href="http://google.com/search?q=python+unittest">python unittest</a></li></ul> </li></ul> </div> <div class="slide"> <h1>Документация—на вашия компютър</h1> <ul><li>Под Windows—Python Manuals в <code>chm</code> формат. Може да се търси, на практика в него е цялата HTML документация.</li><li>HTML документация—почти същата като на сайта (малко по-стара вероятно) и й лиспва търсене. Ще я намерите на собствения си компютър някъде, освен ако за вашата ОС не се разпространява отделно от самия Python.</li></ul> </div> <div class="slide long"> <h1>pydoc</h1> <ul><li>Под Windows: <code>python.exe pydoc.py</code> Трябва да сложите в пътя директориите <code>PythonX.Y</code> и <code>PythonX.Y/Lib</code>.</li><li>На другите места: <code>pydoc</code></li><li><code>pydoc <име></code>—търси документация за тази функция, тема, модул ключова дума…</li><li><code>pydoc -k <ключова дума></code>—търси тази дума в описанията на всички модули</li><li><code>pydoc -p <порт></code>—пуска HTTP сървър на вашия компютър и можете да разглеждате HTML документацията като отворите с браузъра си <code>http://localhost:<порт>/</code></li><li><code>pydoc -g</code>—отваря графична програма, в която може да търсите по ключова дума</li></ul> </div> <div class="slide long"> <h1>Документация на наши модули</h1> <ul><li>Помните ли <code>docstring</code>-овете?</li><li class="code"><pre><code>def f(x, y):<br /> """f makes you happy putting a x into your y."""</code></pre></li><li>Стига вашия модул да се намира някъде в пътя за търсене на Pythоn <ul><li>можете да погледнете в <code>sys.path</code></li><li><code>PYTHONPATH</code></li><li>модулът <a href="http://docs.python.org/lib/module-site.html"><code>site</code></a></li></ul> </li><li>при разглеждане с <code>pydoc</code> ще се вижда и документацията на вашите модули</li><li><code>pydoc -w </code>—записва документация на диска в HTML формат</li></ul> </div> <div class="slide"> <h1>epydoc</h1> <ul><li>гъвкава система за генериране на документация</li><li>поддържа много формати</li><li>не е в стандартната Python дистрибуция</li></ul> </div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-32500707580238730852009-01-17T11:15:00.000-08:002009-01-17T11:16:15.059-08:00Автоматизирано тестване в Python<div class="slide"> <h1><br /></h1> <h3>„ Програмиране с Python“, <acronym title="Факултет по Математика и Информатика при Софийски Университет">ФМИ</acronym></h3> <h3>Стефан Кънев & Николай Бачийски</h3> <h4>11.04.2007г.</h4> </div> <div class="slide"> <h1>Disclaimer</h1> <p>Днес няма да си говорим за acceptance testing, quality assurance или нещо което се прави от "по-низшия" отдел във фирмата.</p> </div> <div class="slide"> <h1>Митът</h1> <p>Проектът идва с готово задание, подробно задание. Прави се дизайн, с помоща на който работата се разбива на малки задачи. Те се извършват последователно, като не се налага да се връщате към някоя след като сте я приключили. Изискванията не се променят и не се налага добавянето на нова функционалност.</p> </div> <div class="slide"> <h1>Митът v1.1</h1> <p>Щом съм написал един код, значи ми остава единствено да го разцъкам, да го пробвам в <code>main</code> метода/функцията и толкова. Няма да се променя така или иначе, а ако пък случайно ми се наложи да го пипам - аз съм го писал, знам го, няма как да допусна грешка. Най-много да го поразцъкам още малко.</p> </div> <div class="slide"> <h1>Тежката действителност</h1> <ul><li>Заданията <strong>винаги</strong> се променят.</li><li>Често се налага един код да се преработва.</li><li>Писането на код е сложна задача - могат да се направят много грешки.</li><li>Програмистите са хора - допускат грешки.</li><li>Или губите ужасно много време в разцъкване след всяка промяна, или рискувате да вкарате бъгове в приложението, които ще бъдат открити твърде късно.</li><li>Промяна в един модул в единия край на системата като нищо може да причини грешка в другия, без въобще да усетите.</li></ul> </div> <div class="slide"> <h1>Занятието</h1> <pre><code><br />class Programmer(object):<br /> ...<br /> def makeChange(self, project, change):<br /> self.openAssociatedFiles(project, change)<br /> while True:<br /> self.attemptChange(change)<br /> project.start()<br /> result = self.clickAroundAndTest(project)<br /> project.stop()<br /> if result.sucessful(): break<br /> self.commitCode(project)<br /> self.hopeEverythingWentOK()<br /></code></pre> </div> <div class="slide"> <h1>Идея</h1> <p>Това е автоматизирана задача. Всеки път повтаряме едно и също, отнема ни много време, уморява ни и има голям шанс да пропуснем нещо или да допуснем грешка. Защо вместо това не напишем малка програмка, която проверява дали кодът ни работи като хората? Така не просто ще имаме хубави критерии за кода, но и всеки друг ще може да проверява дали неговата промяна в модул А не е довела до грешка в нашия модул Б. Вместо да губим време да цъкаме всеки път, ще пускаме всички тестове автоматично и една команда, няма да въвеждаме никакви параметри и просто ще чакаме един от двата отгорова - "Всички тестове минаха усешно" или "Имаше грешка в тест Х".</p> </div> <div class="slide long"> <h1>Кодът който ще тестваме</h1> <pre><code><br />class Interval(object):<br /> <br /> def __init__(self, left, right):<br /> self.left, self.right = left, right<br /><br /> def leftOpen(self): return self.left == None<br /> def rightOpen(self): return self.right == None<br /><br /> def containsNumber(self, number):<br /> if self.leftOpen() and self.rightOpen(): return true<br /> if self.leftOpen(): return number <= self.right<br /> if self.rightOpen(): return self.left <= number<br /> return self.left < number < self.right<br /><br /> def __max(self, a, b): max(a, b) if not None in [a, b] else None<br /> def __min(self, a, b): min(a, b) if not None in [a, b] else None<br /><br /> def insersect(self, other):<br /> left = self.__max(self.left, other.left)<br /> right = self.__max(self.right, other.right)<br /> return Interval(left, right)<br /> </code></pre> </div> <div class="slide long"> <h1>Идеята...</h1> <pre><code><br /> class IntervalTest:<br /> def testContainsNumber(self):<br /> interval = Interval(None, 0)<br /> test("interval съдържа -3")<br /> test("interval съдържа 0")<br /> test("interval не съдържа 9")<br /> test("interval.leftOpen() е истина")<br /> test("interval.rightOpen() е лъжа")<br /><br /> def testIntersects(self):<br /> test("сечението на [0, 10] със [5, None] е [5, 10]")<br /> test("сечението на [None, 0] със [None, 42] е [None, 0]")<br /> test("сечението на [None, 20] със [-20, None] е [-20, 20]")<br /><br /> </code></pre> </div> <div class="slide long"> <h1>...реализацията...</h1> <pre><code> class IntervalTest(unittest.TestCase):<br /> def testContainsNumber(self):<br /> interval = Interval(None, 0)<br /> self.assertTrue(interval.containsNumber(-3))<br /> self.assertTrue(interval.containsNumber(0))<br /> self.failIf(interval.containsNumber(9))<br /> self.assertTrue(interval.leftOpen())<br /> self.failIf(interval.rightOpen())<br /><br /> def testIntersects(self):<br /> self.assertEquals(<br /> Interval(5, 10),<br /> Interval(0, 10).intersect(Interval(5, None)))<br /> self.assertEquals(<br /> Interval(None, 0),<br /> Interval(None, 42).intersect(Interval(None, 0)))<br /> self.assertEquals(<br /> Interval(-20, 20),<br /> Interval(None, 20).intersect(Interval(-20, None)))<br /><br /> if __name__ == "__main__":<br /> unittest.main()<br /> </code></pre> </div> <div class="slide"> <h1>...и резултата</h1> <pre><code>.F<br />======================================================================<br />FAIL: testIntersects (__main__.GoodieListTests)<br />----------------------------------------------------------------------<br />Traceback (most recent call last):<br /> File "./interval_test.py", line 16, in testCompact<br /> self.assertEquals(<br /> Interval(None, 0),<br /> Interval(None, 42).intersects(Interval(None, 0)))<br />AssertionError: Interval(None, 0) != Interval(0, 0)<br /><br />----------------------------------------------------------------------<br />Ran 2 tests in 0.000s<br /><br />FAILED (failures=1)<br /></code></pre> </div> <div class="slide"> <h1>Структура на тестовете</h1> <ul><li>test case - група сценарии които споделят нещо общо помежду си.</li><li>test method - единичен сценарий, който проверява нещо конкретно.</li><li>assertation - единична проверка по време на изпълнение на сценария</li></ul> </div> <div class="slide"> <h1>Структура на тестовете в Python</h1> <ul><li>test case - клас, наследяващ <code>unittest.TestCase</code></li><li>test method - метод във въпросния клас, чието име започва с <code>test</code> и изпълнява поне една асертация.</li><li>assertation - извикване на <code>self.assert*</code> в тестовия метод.</li></ul> </div> <div class="slide"> <h1>Видове тестове</h1> <ul><li>Unit tests - проверяват дали дадено парче код (клас) работи правилно в изолация.</li><li>Integration tests - проверяват дали няколко модула работят добре заедно.</li><li>Functional tests - проверяват дали крайната функционалност на продукта работи както се очаква.</li></ul> </div> <div class="slide"> <h1>За какво ни помагат тестовете</h1> <ul><li>Откриват грешки скоро след като са въведени в системата.</li><li>Позволяват ви уверено да правите промени в самата система</li><li>Дават сигурност на клиенти, шефове и програмисти</li><li>Представляват пример как се работи с кода.</li><li>Помага разделянето на интерфейс от имплементация.</li></ul> </div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-82790516674603677482009-01-17T11:14:00.000-08:002009-01-17T11:15:00.105-08:00Декоратори и with в python<div class="slide"> <h1><br /></h1> <h3>„ Програмиране с Python“, <acronym title="Факултет по Математика и Информатика при Софийски Университет">ФМИ</acronym></h3> <h3>Стефан Кънев & Николай Бачийски</h3> <h4>04.04.2007г.</h4> </div> <div class="slide"> <h1>Декоратори</h1> <ul><li>Припомнете си как правихме статични методи:</li><li class="code"><pre><code>class Mityo:<br /> # не зависи от инстанцията -- винаги пасуват<br /> def work(): pass<br /> work = staticmethod(work)</code></pre></li><li>Горното се нарича „декориране“ на метода <code>work</code></li><li>Подходът за смилане на метод или функция за да бъдат по-различни или по-полезни е често срещан в Python</li></ul> </div> <div class="slide long"> <h1>Синтаксис</h1> <pre><code>def add(a, b):<br /> return a+b<br />add = accepts2ints(add)</code></pre> <p>Поради честотата на използване и поради неудобността на горния синтаксис, в Python си има отделен синтаксис за декорирането.</p> <pre><code>@accepts2ints<br />def add(a, b):<br /> return a+b</code></pre> <p>В този случай, <code>accepts2ints</code> трябва да бъде функция, която приема функция и връща нейната нова версия.</p> </div> <div class="slide"> <h1>Пример за прост декоратор</h1> <pre><code>def notifyme(f):<br /> def logged(*args, **kwargs):<br /> print f.__name__, 'was called with', args, 'and', kwargs<br /> return f(*args, **kwargs)<br /> return logged<br /> <br />@notifyme<br />def square(x): return x*x<br /> <br />res = square(25)<br />square was called.</code></pre> </div> <div class="slide"> <h1>Няколко декоратора на една функция</h1> <pre><code>class Mityo:<br /> @staticmethod<br /> @notifyme<br /> def work(): pass<br /><br />Mityo.work()<br />work was called with () and {}<br /></code></pre> <p>Горният метод е еквивалентен на:</p> <pre><code>def work(): pass<br />work = notifyme(work)<br />work = classmethod(work)</code></pre> <p>Или:</p> <pre><code>work = classmethod(notifyme(work))</code></pre> </div> <div class="slide"> <h1>Параметри на декораторите</h1> <p>Ако се върнем към примера с <code>accepts2int</code>, сигурно ще ни се прииска да си напишем малко по-общ декоратор, на когото да казваме типовете, които искаме функцията ни искаме да приема а не да пишем нов декоратор за всяка комбинация, която ни хрумне.</p> <pre><code>@accepts(int, int)<br />def add(a, b): return a+b</code></pre> <p>Това се превежда до следното:</p> <pre><code>add = accepts(int, int)(add)</code></pre> <p>Другояче казано <code>accepts</code> трябва да бъде функция, която приема като аргументи типовете и връща друга фунцкия. Тя пък трябва да приема вече фунцкията, която ще декорираме и да върне декорираната.</p> </div> <div class="slide"> <h1>Код срещу думи</h1> <pre><code>def accepts(*types):<br /> def accepter(f):<br /> def decorated(*args):<br /> for (i, (arg, t)) in enumerate(zip(args, types)):<br /> if not isinstance(arg, t):<br /> raise TypeError("Argument #%d of '%s' should have been of type %s" % (i, f.__name__, t.__name__))<br /> #TODO: more complex checks: tuple of a type, list of type<br /> return f(*args)<br /> return decorated<br /> return accepter</code></pre> </div> <div class="slide"> <h1>Още код</h1> <pre><code><br />instances = {}<br /><br />def singleton(cls):<br /> def getinstance():<br /> if cls not in instances:<br /> instances[cls] = cls()<br /> return instances[cls]<br /> return getinstance<br /><br />@singleton<br />class MyClass:<br /> </code></pre> </div> <div class="slide"> <h1>Вградени декоратори</h1> <ul><li><code>staticmethod</code> — прави един метод статичен</li><li><code>classmethod</code> — прави класов метод (като първи аргумент приема класа)</li></ul> </div> <div class="slide long"> <h1>Работа с файлове</h1> <pre><code><br />src = raw_input()<br />target = raw_input()<br /><br />try:<br /> sourceFile = open(src, 'r')<br /> buffer = []<br /> try:<br /> buffer = sourceFile.readlines()<br /> finally:<br /> sourceFile.close()<br /><br /> targetFile = open(target, 'w')<br /> try:<br /> for line in reversed(buffer):<br /> targetFile.write(line)<br /> finally:<br /> targetFile.close()<br />except IOError:<br /> print "Tough luck, junior"<br /> </code></pre> </div> <div class="slide"> <h1>With</h1> <ul><li>Твърдението <code>with</code> позволява да преизползвате сходна <code>try/catch</code> логика (и не само)</li><li>Синтаксис: <pre><code>with <em>[израз]</em>:<br /> <em>[блок]</em><br /><br />или<br /><br />with <em>[израз]</em> as <em>[име]</em>:<br /> <em>[блок]</em><br /></code></pre> </li></ul> </div> <div class="slide"> <h1>Втори опит</h1> <pre><code><br />src = raw_input()<br />target = raw_input()<br /><br />buffer = []<br />try:<br /> with open(src) as sourceFile:<br /> buffer = sourceFile.readlines()<br /> with open(target) as targetFile:<br /> for line in reversed(buffer):<br /> targetFile.write(line)<br />except IOError:<br /> print "Much better, now, ain't it?"<br /></code></pre> </div> <div class="slide"> <h1>Как работи with?</h1> <ul><li>Изразът който получава се изпълнява и се взема върнатия обект. Той се нарича <em>context manager</em></li><li>Методът <code>__enter__()</code> на content manager-а се изпълнява. Получената от него стойност се записва в името след <em>as</em>.</li><li>Изпълнява се блокът подаден на <code>with</code></li><li>Ако се получи изключение в блока, се извиква метода <code>__exit__(type, value, traceback)</code> на context manager-а.</li><li>Ако не се получи изключение, пак се вика <code>__exit__(None, None, None)</code>.</li></ul> </div> <div class="slide"> <h1>Как се ползва with?</h1> <p>Понеже <code>with</code> е нова ключова дума, въведена в Python 2.5, се налага да добавите малко код към вашето приложение за да я ползвате:</p> <code>from __future__ import with_statement</code> <p>Ако не сте импортирали <code>with</code> и го ползвате като име, Python ще даде грешка. В Python 2.6 <code>with</code> ще го има по подразбиране и няма да се налага да го импортвате. Това е стандартния подход за приемане на нови feature-и в езика.</p> </div> <div class="slide long"> <h1>Малък пример</h1> <pre><code><br />from __future__ import with_statement<br /><br />class Manager:<br /> def __enter__(self):<br /> print "I've been entered!"<br /> return "ticket"<br /> def __exit__(self, type, value, traceback):<br /> print "I've been exited!"<br /><br />with Manager() as something:<br /> print "Am I inside?"<br /> print something<br /></code></pre> <pre>I've been entered!<br />Am I inside?<br />ticket<br />I've been exited!</pre> </div> <div class="slide"> <h1>contextlib</h1> <p>Модула contextlib предлага следните неща:</p> <ul><li>closing</li><li>nested</li><li>contextmanager</li></ul> </div> <div class="slide long"> <h1>closing</h1> <code>contextlib.closing</code> е нещо подобно на... <pre><code><br />class closing(object):<br /> def __init__(self, thing): self.thing = thing<br /> def __enter__(self): return thing<br /> def __exit__(self, type, value, traceback): self.thing.close()<br /></code></pre> ...и ви позволява да пишете така... <pre><code><br />from __future__ import with_statement<br />from contextlib import closing<br />import codecs<br /><br />with closing(urllib.urlopen('http://www.python.org')) as page:<br /> for line in page:<br /> print line<br /><br /></code></pre> </div> <div class="slide long"> <h1>nested</h1> <p>Долния код...</p> <pre><code><br />from contextlib import nested<br /><br />with nested(A, B, C) as (X, Y, Z):<br /> do_something()<br /></code></pre> ...е еквивалентен на... <pre><code><br />with A as X:<br /> with B as Y:<br /> with C as Z:<br /> do_something()<br /></code></pre> </div> <div class="slide long"> <h1>contextmanager</h1> <p><code>contextmanager</code> е декоратор, който превръща генератор функция в context manager:</p> <pre><code><br />from __future__ import with_statement<br />from contextlib import contextmanager<br /><br />@contextmanager<br />def entering(whom):<br /> print "I've been entered by %s" % whom<br /> yield "ticket"<br /> print "I've been exited!"<br /><br />with entering("someone") as something:<br /> print "Am I inside?"<br /> print something<br /></code></pre> <pre>I've been entered by someone<br />Am I inside?<br />ticket<br />I've been exited!<br /></pre> </div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-55464073383140078382009-01-17T11:13:00.000-08:002009-01-17T11:14:14.231-08:00Примерна задачка на Python<div class="slide"> <h1><br /></h1> <h3>„ Програмиране с Python“, <acronym title="Факултет по Математика и Информатика при Софийски Университет">ФМИ</acronym></h3> <h3>Стефан Кънев & Николай Бачийски</h3> <h4>02.04.2007г.</h4> </div> <div class="slide"> <h1>Какво ще правим?</h1> <ul><li>Ще си припомним условието</li><li>Ще ви предложим примерно решение</li><li>Ще видим дали може да се направи по-хубаво</li></ul> </div> <div class="slide longlong"> <h1>Условие—начало</h1> <p>Основната ви цел е да напишете функция със следните име и аргументи: <code>module_game(m1, m2)</code>.</p> <p>Входни данни: <code>m1</code> и <code>m2</code> са модули.</p> <p>Резултат: n-торка с 2 елемента, с броя на точките събрали първия и втория модул при играта, която е описана по-долу в условието.</p> <p>Предварително известни факти:</p> <ul><li>всички речници в модулите са или празни или само от цели числа. Ключовете им са винаги низове. Примери: <code>{} {'baba': 5} {'a': 42, 'b': -69, 'x': 4360000634}</code></li><li>всички списъци в модулите са или празни или са списъци от n-торки от числа. n-торките също могат да бъдат празни. Примери: <code>[] [()] [(1023, 4095, 8191), (), (), (0, 17), (3,)]</code></li><li>всички функции в модулите приемат два аргумента цели числа и връщат цяло число</li><li>може да разчитате, че тези условия ще бъдат изпълнени и няма нужда да ги проверявате</li></ul> <p>Правила на играта:</p> <p><em>За атрибути по-надолу ще смятаме само тези реални атрибути на модулите, които не започват с <code>_</code> (долна черта, подчертавка)</em></p> </div> <div class="slide long"> <h1>Условие—правило 0</h1> <p>Всеки модул получава <strong>1 точка</strong> за всяка функция в него, чието име започва с последните 3 символа на друга функция в същия модул. Ето пример за част от модул, която ни гарантира две точки по този параграф: </p><pre><code>s = "baba"<br />def destroy(x, y):<br /> print "Destroyed."<br /> return 0<br />def roy_keen(x, y):<br /> print "Babyboy."<br /> return 0<br />def roy_boss(x, y):<br /> print "Holy-shmolly, that is tea!"<br /> return 0</code></pre> </div> <div class="slide"> <h1>Условие—правило 1</h1> <p>Всеки модул получава 1 точка, за всеки списък в него, за който средното-аритметично на сумите от квадратите на n-орките в него е по-голямо от средно-аритметичното на всички цели числа в другия модул. Ако някоя n-торка е празна, нейната сума може да се смята за 0. Ако един списък е празен, неговото аритметично също може да се смята за 0.</p><br /><p>Пример: имаме списъка <code>[(1, 2), (), (8, -2), (-1, 5, -1)]</code>. Сумите на квадратите на n-торките са съответно: 5, 0, 68, 27. Средното им аритметично е точно 25.</p> </div> <div class="slide"> <h1>Условие—правило 2</h1> <p>По <strong>1 точка</strong> получава модул, за всяка функция в него, която удовлетворява следните условия: </p><ul><li>извикана с аргументи 0 и 0 връща 0</li><li>комутативна e за всички двойки числа от 0 до 99 включително</li></ul> <p>Пример за такава функция: <code>def f(x, y): return x*y</code></p> </div> <div class="slide long"> <h1>Условие—правило 2</h1> <p><strong>3 точки</strong> носи на модул всеки речник, за който: </p><ol><li>нека сортираме стойностите му по брой на цифрите в низходящ ред</li><li>ако две стойности имат равен брой цифри, приемаме, че те са ъгли в градуси и сравняваме техните тангенси (отново низходящо)</li><li>взимаме ключовете на първите 6 елемента. Ако елементите на речника са по-малко от 6, спираме дотук</li><li>ако тези 6 ключа са ‘Chapman’, ‘Cleese’, ‘Gilliam’, ‘Idle’, ‘Jones’, ‘Palin’ независимо в какъв ред или с малки или големи букви, модулът получва трите точки</li></ol> <p> Пример за такъв речник: <code>{'Chapman': 11, 'Charlie': 99, 'GILLIAM': 102, 'Idle': 666, 'Jones': 883, 'Palin': 55, 'Cleese': 1101}</code> </p> </div> <div class="slide long"> <h1>Код—начало</h1> <pre><code>def module_game(m1, m2):<br /> return (assess(m1, m2), assess(m2, m1))<br /><br />def assess(mod, mod_other):<br /> return sum((<br /> end3_funcs(mod),<br /> avg_lists(mod, mod_other),<br /> commutatives(mod),<br /> 3*monty_python_dicts(mod),<br /> ))<br /><br />def valid_attributes(mod):s<br /> return (attr for attr in dir(mod) if not attr.startswith('_'))<br /></code></pre> <ul><li><code>sum</code> приема последователност и му даваме n-торка: <code>sum((</code></li><li><code>valid_attributes</code> няма нужда да връща списък, може да ползваме generator expression</li></ul> </div> <div class="slide long"> <h1>Код—правило 0</h1> <pre><code>def end3_funcs(mod):<br /> func_names = [attr for attr in valid_attributes(mod) if callable(getattr(mod, attr))]<br /> count = 0<br /> for func in func_names:<br /> if len(func) < 3: continue<br /> start = func[:3]<br /> if any((otherfunc.endswith(start) for otherfunc in func_names if func != otherfunc)):<br /> count += 1<br /> return count</code></pre> <ul><li>Защо <code>func_names</code> е списък (или „за влагането на генератори“)?</li><li>Какво е <code>any</code>?</li></ul> </div> <div class="slide longlong"> <h1>Влагане на генератори</h1> <pre><code>g = (x*x for x in xrange(4))<br />for a in g:<br /> for b in g:<br /> print (a, b)<br />(0, 1)<br />(0, 4)<br />(0, 9)</code></pre> <ul><li>Ред на извикване:<ol><li><code>g.next()</code> във външния цикъл, <code>a</code>, става 0</li><li><code>g.next()</code> във вътрешния циъкл, <code>b</code>, става 1</li><li><code>g.next()</code> във вътрешния циъкл, <code>b</code>, става 4</li><li><code>g.next()</code> във вътрешния циъкл, <code>b</code>, става 9</li></ol> </li><li>генераторът не се копира</li><li>… и за съжаление не може лесно да се копира</li><li>генераторът може да се ползва само веднъж</li></ul> </div> <div class="slide longlong"> <h1>Ами тогава?</h1> <ol><li>Списъци: <code>g = [x for x in xrange(4)]</code></li><li>Създаване на 2: <pre><code>g = (x*x for x in xrange(4))<br />g_inner = (x*x for x in xrange(4))</code></pre></li><li>Създаване направо вътре: <pre><code>for a in (x*x for x in xrange(4)):<br /> for b in (x*x for x in xrange(4)):<br /> print (a, b)</code></pre></li><li>Функция генератор: <pre><code>def gen_sq(n):<br /> for x in xrange(n):<br /> yield x*x</code></pre></li><li>Още една функция: <pre><code>def gen_sq2(n):<br /> return (x*x for x in xrange(n))</code></pre></li></ol> </div> <div class="slide longlong"> <h1>Код—правило 1</h1> <pre><code>def avg_lists(mod, other):<br /> other_ints = [getattr(other, attr) for attr in valid_attributes(other)<br /> if isinstance(getattr(other, attr), (int, long))]<br /> other_sum, other_len = sum(other_ints), len(other_ints)<br /> mod_lists = (getattr(mod, attr) for attr in valid_attributes(mod)<br /> if isinstance(getattr(mod, attr), list))<br /> count = 0<br /> square = lambda x: x*x<br /> for l in mod_lists:<br /> jingled_items = [sum(imap(square, tup)) for tup in l]<br /> jingled_sum, jingled_len = sum(jingled_items), len(jingled_items)<br /> # don't use floats<br /> # we know that always both the sum and the len are non-negative<br /> # except that other_sum could be negative<br /> if jingled_sum > 0 and 0 == other_len:<br /> count += 1<br /> elif jingled_len == 0 and other_sum < 0:<br /> count += 1<br /> elif jingled_sum*other_len > jingled_len*other_sum:<br /> count += 1<br /> return count</code></pre> </div> <div class="slide long"> <h1>Код—правило 2</h1> <pre><code>def commutatives(mod):<br /> # този път ф-ии--не имена<br /> funcs = [getattr(mod, attr) for attr in valid_attributes(mod)<br /> if callable(getattr(mod, attr))]<br /> count = 0<br /> for func in funcs:<br /> if func(0,0) == 0 and\<br /> all((func(i, j) == func(j, i)<br /> for i in xrange(0, 99) for j in xrange(i+1, 100))):<br /> count += 1<br /> return count</code></pre> </div> <div class="slide long"> <h1>Код—правило 2</h1> <pre><code>def commutatives(mod):<br /> # този път ф-ии--не имена<br /> funcs = [getattr(mod, attr) for attr in valid_attributes(mod)<br /> if callable(getattr(mod, attr))]<br /> count = 0<br /> for func in funcs:<br /> point_commutative = ( func(i, j) == func(j, i)<br /> for i in xrange(0, 99) for j in xrange(i+1, 100))<br /> if func(0,0) == 0 and\<br /> all(point_commutative):<br /> count += 1<br /> return count</code></pre> </div> <div class="slide long"> <h1>any и all</h1> <ul><li><code>any(iterable)</code> — връща истина, ако поне един от елементите на <code>iterable</code> е истина.</li><li><code>all(iterable)</code> — връща истина, ако всички елементи на <code>iterable</code> са истина.</li></ul> <pre><code>>>>people = ('God', 'Monty', 'Pinkie', 'Mityo')<br />>>>wannaplay = lambda name: 'x' in name<br />>>>friends = lambda x,y: x[0] == y[0] and x != y<br />>>>capitalised = lambda x: x[0].isupper()<br />>>>print any(map(wannaplay, people))<br />False # Nobody wants to play<br />>>>print any([friends(name, 'Mityo') for name in people])<br />True # Monty<br />>>>print all(imap(capitalised, people))<br />True<br />>>>print all((friends(name, 'Mityo') for name in people))<br />False</code></pre> </div> <div class="slide long"> <h1>Код—правило 3 </h1> <pre><code>def monty_python_dicts(mod):<br /> WANTED = set(['chapman', 'cleese', 'gilliam', 'idle', 'jones', 'palin'])<br /> dicts = [getattr(mod, attr) for attr in valid_attributes(mod) if isinstance(getattr(mod, attr), dict)]<br /> count = 0<br /><br /> def make_strange_cmp(dict_):<br /> def strange_cmp(x, y):<br /> x, y = dict_[x], dict_[y]<br /> sx, sy = str(sx).lstrip('-'), str(sx).lstrip('-')<br /> if (len(sx) != len(sy)):<br /> return cmp(len(sx), len(sy))<br /> return cmp(math.tan(math.radians(x)), math.tan(math.radians(y)))<br /><br /> for d in dicts:<br /> ordered = sorted(d, cmp=make_strange_cmp(d), reverse=True)<br /> if set(imap(string.lower, ordered[:6])) == WANTED:<br /> count += 1<br /> return count</code></pre> </div> <div class="slide long"> <h1>Код—правило 3 </h1> <pre><code>def monty_python_dicts(mod):<br /> WANTED = set(['chapman', 'cleese', 'gilliam', 'idle', 'jones', 'palin'])<br /> dicts = [getattr(mod, attr) for attr in valid_attributes(mod)<br /> if isinstance(getattr(mod, attr), dict)]<br /> count = 0<br /> # DSU, DSU<br /> def make_decorate(dict_):<br /> def decorate(key):<br /> value = dict_[key]<br /> svalue = str(value).lstrip('-')<br /> return (len(svalue), math.tan(math.radians(value)))<br /> return decorate<br /><br /> for d in dicts:<br /> ordered = sorted(d, key=make_decorate(d), reverse=True)<br /> if set(imap(string.lower, ordered[:6])) == WANTED:<br /> count += 1<br /> return count</code></pre> </div> <div class="slide long"> <h1>DSU</h1> <ul><li>DSU = Decorate, Sort, Undecorate</li><li>Трансформацията на Шварц (<a href="http://en.wikipedia.org/wiki/Schwartzian_transform">Schwartzian transform</a>)</li><li>Искаме да сортираме списък от имена първо по второто име, после по пъврото</li><li class="code"><pre><code>names = ['Monty Python', 'Bilbo Baggins', 'Mityo Python']<br /># 2 пъти split<br /># цялото се вика n*log(n) пъти<br />def names_cmp(n1, n2):<br /> first1, last1 = n1.split()<br /> first2, last2 = n2.split()<br /> if last1 != last2:<br /> return cmp(last1, last2)<br /> else:<br /> return cmp(first1, first2)<br /><br />names.sort(names_cmp)<br /></code></pre> </li></ul></div> <div class="slide long"> <h1>DSU (2)</h1> <pre><code><br /># (('Python', 'Monty'), 'Monty Python')<br />decorated = zip([tuple(reversed(name.split())) for name in names], names)<br />decorated.sort()<br />undecorated = [value for (decor, value) in decorated]<br />print undecorated<br />['Bilbo Baggins', 'Mityo Python', 'Monty Python']<br /></code></pre> <ul><li>списъци и n-орки се сравняват първо по първи елемент, ако са равни—по-втори и т.н.</li><li><code>zip</code> взима няколко списъка и връща списък от n-орки с поредните елементи на списъците</li><li>обработката на един елемент се вика веднъж и се пише веднъж</li></ul> </div> <div class="slide long"> <h1>DSU (3)</h1> <pre><code>ready = sorted(names, key = lambda name: tuple(reversed(name.split())))</code></pre> <p>или:</p> <pre><code><br />def decorate(name):<br /> first, last = name.split()<br /> return last, first<br />ready = sorted(names, key = decorate)</code></pre> <ul><li>В Python 2.4 има доста нововъведения: sorted, <code>key</code> параметъра на <code>sort</code> и <code>sorted</code></li><li>Параметърът <code>key</code> очаква функция с един аргумент и сортира по нейната стойност, а не по стойността на елементите на поредицата</li><li>Стойностите на поредицата не се променят от викането на функцията, дадена на <code>key</code></li><li>DSU се прилага вече много по-лесно и кратко :)</li></ul> </div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-88846479168402140882009-01-17T11:12:00.000-08:002009-01-17T11:13:09.844-08:00Итератори и генератори в Python<div class="slide"> <h1><br /></h1> <h3>„ Програмиране с Python“, <acronym title="Факултет по Математика и Информатика при Софийски Университет">ФМИ</acronym></h3> <h3>Стефан Кънев & Николай Бачийски</h3> <h4>28.03.2007г.</h4> </div> <div class="slide long"> <h1>За приятелите</h1> <ul><li>Митьо Питона не е много паметлив.</li><li>Пази телефонните номера на приятелите си в прост текстов файл:<pre><code><br />062600400<br />+1800500<br />061830647<br />062633733</code></pre> </li><li>Една вечер Митьо решил да организира джакузи-парти и трябвало да се обади на всичките си приятели</li><li>За целта трябвало да прочете всички номера от файла и да им се обади един по един</li><li>Не забравяйте: Митьо не е много паметлив — може да помни само един номер в главата си</li></ul> </div> <div class="slide long"> <h1>Първа реализация</h1> <pre><code>numbers = open('friends', 'r').readlines()<br />for number in numbers:<br /> mityo.invite(number.strip())</code></pre> <ul><li><code>open</code> отваря файл и връща файлов обект</li><li><code>readlines</code> прочита целия файл и ни връща списък от низове (заедно с новите редове)</li><li><code>strip</code> маха белите полета от двата края на низа (+ новите редове)</li></ul> <ul class="incremental"><li>Виждате ли проблем с тази реализация?</li><li>Памет: четем целия файл в на Митьо паметта</li></ul> </div> <div class="slide long"> <h1>Втора реализация</h1> <pre><code>numbers = open('friends')<br />while (True):<br /> number = numbers.readline()<br /> if not number:<br /> break<br /> mityo.invite(number.strip())</code></pre> <ul><li><code>readline</code> чете един ред от файла, ако няма — връща празен низ</li></ul> <ul class="incremental"><li>Виждате ли проблем с тази реализация?</li><li>Простота: то не са while-ове, то не са if-ове</li></ul> </div> <div class="slide long"> <h1>Трета реализация (любима)</h1> <pre><code>for number in open('friends'):<br /> mityo.invite(number.strip())</code></pre> <ul class="incremental"><li>Виждате ли проблем с тази?</li><li>Функционално е еквивалентна на предишната!</li><li>Памет: ок</li><li>Четимост: да, да</li><li>Магия: да</li></ul> </div> <div class="slide"> <h1>Каква е магията?</h1> <p><strong>итератор</strong> — обект, с метод <code>next</code>, който при всяко извикване или връща пореден елемент или вдига <code>StopIteration</code>, ако няма повече</p> <br /> <p><strong>генератор</strong> — обект, за който вградената функция <code>iter</code> връща итератор</p> </div> <div class="slide long"> <h1>Как работи for</h1> <pre><code>for <em>target</em> in <em>sequence</em>:<br /> <em>блок</em></code></pre> <ol><li>Опитва се да се добере то итератор <ol><li>извиква iter(<em>sequence</em>) — на практика проверява дали обекта ни има метод <code>__iter__</code> и взима неговия резултат. Ако няма такова животно — отива на по-следващия слайд</li><li>на всяка стъпка от цикъла в <em>target</em> слага резултата от <code>next</code> метода на получения по-горе обект</li><li>… и така докато не прихване <code>StopIteration</code></li></ol> </li></ol> </div> <div class="slide long"> <h1>Пример</h1> <pre><code>class MityoIter:<br /> def __init__(self, filename = 'friends'):<br /> self.numbers = open(filename)<br /> def next(self):<br /> number = self.numbers.readline()<br /> if not number:<br /> raise StopIteration<br /> return number<br /> def __iter__(self):<br /> return self<br /> <br />for number in MityoIter():<br /> mityo.invite(number.strip())</code></pre> </div> <div class="slide long"> <h1>Как работи for (2)</h1> <pre><code>for <em>target</em> in <em>sequence</em>:<br /> <em>блок</em></code></pre> <ol start="2"><li>Цикли по стандартния начин: <ol><li>Проверява дали <em>sequence</em> поддържа оператора <code>[]</code> (<code>__getitem__</code>)</li><li>Започвайки от индекс <code>0</code> се опитва да достъпи елементите един по един, като увеличава на всяка стъпка индекса с <code>1</code></li><li>Свършва, когато прихване <code>IndexError</code></li></ol> </li></ol> </div> <div class="slide longlong"> <h1>Пример</h1> <pre><code>class MityoBeard:<br /> def __init__(self, step = 1, maxage = 33):<br /> self.step = step<br /> self.maxage = maxage<br /><br /> def immortalise(self):<br /> self.maxage = None<br /><br /> def __getitem__(self, day):<br /> if self.maxage != None and day > self.maxage:<br /> raise IndexError("Mityo's beard is already gone.")<br /> return self.step*day<br /> <br /> beard = MityoBeard(2)<br /> for l in beard:<br /> print "Mityo's beard is %d cm. long." % l<br /> beard.immortalise()<br /> for l in beard:<br /> print "Mityo's beard is %d cm. long." % l</code></pre> </div> <div class="slide"> <h1>Обратно към итераторите</h1> <ul><li>итерацията е нещо съвсем отнесено</li><li>не винаги можем да разберем лесно дали използваме списък или итератор</li><li>в повечето случаи не ни е нужно да знаем</li><li>от многото знания боли глава</li></ul> </div> <div class="slide"> <h1>Генераторите обичат питоните</h1> <ul><li><code>range</code> vs. <code>xrange</code></li><li><code>dict.keys</code> vs. <code>dict.iterkeys</code> vs. <code>dict</code></li><li><code>os.walk</code></li><li><code>enumerate</code></li><li><code>sorted</code></li><li><code>list(<em>генератор</em>)</code></li></ul> </div> <div class="slide long"> <h1>Примери</h1> <pre><code>>>> list(enumerate(xrange(37, 43)))<br />[(0, 37), (1, 38), (2, 39), (3, 40), (4, 41), (5, 42)]<br />>>> map(len, MityoIter()) # map и подобните са умни и разбират<br />>>> partners = {'Pena': 'Mityo', 'Kuna': 'Mityo', 'Boca': 'Mityo'}<br />>>> partners.keys()<br />['Kuna', 'Boca', 'Pena']<br />>>> partners.iterkeys()<br /><dictionary-keyiterator object="" at="" 0x00c49c80=""><br />>>> iter(partners)<br /><dictionary-keyiterator object="" at="" 0x00c49380=""><br />>>> for woman in partners:<br /> print "%s is with %s." % (woman, partners[woman])</dictionary-keyiterator></dictionary-keyiterator></code></pre> </div> <div class="slide"> <h1>Само вградените ли са лесни?</h1> <ul><li>вградените генератори се ползват лесно</li><li>досега не видяхме лесен начин да си правим сами — само с класове и <code>__iter__</code></li><li>е да, ама не</li></ul> </div> <div class="slide longlong"> <h1>ша та yield-на</h1> <p>Магията не спира дотук:</p> <pre><code>def mityo_iter(filename='friends'):<br /> numbers = open(filename)<br /> while(True):<br /> number = numbers.readline()<br /> if number:<br /> yield number<br /> else:<br /> return<br /> <br />>>> mityo_iter # най-обикновена ф-я<br /><function mityo_iter="" at="" 0x011627f0=""><br />>>> mityo_iter() # обикновена-чушки<br /><generator object="" at="" 0x0118abe8=""><br />>>> for number in mityo_iter():<br /> mityo.invite(number.strip())<br /></generator></function></code></pre> </div> <div class="slide"> <h1>Под капака</h1> <p>Функциите, които съдържат <code>yield</code> връщат генератори.</p><br /> <p><code>yield</code> връща стойността на поредната стъпка, а итерацията завършва когато функцията свърши</p><br /> <p><code>yield</code> приспива изпълнението на функцията и след това продължава от същото място</p><br /></div> <div class="slide longlong"> <h1>Подробен пример</h1> <pre><code>def mityo_rabbits(n):<br /> x, y = 0, 1<br /> for i in xrange(n):<br /> yield y<br /> x, y = y, x + y<br /><br />>>> list(mityo_rabits(7))<br />[1, 1, 2, 3, 5, 8, 13]<br /> </code></pre> </div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-16395070340060534992009-01-17T11:11:00.000-08:002009-01-17T11:12:17.848-08:00Изключения в Python<div class="slide"> <h1><br /></h1> <h3>„ Програмиране с Python“, <acronym title="Факултет по Математика и Информатика при Софийски Университет">ФМИ</acronym></h3> <h3>Стефан Кънев & Николай Бачийски</h3> <h4>21.03.2007г.</h4> </div> <div class="slide long"> <h1>Традицията повелява</h1> <p>Ето как най-често се справяме грешките в нашите програми:</p> <pre><code>"""Модул за зимнината на Митьо Питона"""<br />import jars<br /><br />ERROR = -1<br />SUCCESS = 0<br /><br />def prepare_for_winter():<br /> jar = jars.Jar()<br /> if jar.clean() == jars.ERROR:<br /> print "Couldn't clean Mityo's jar!"<br /> return ERROR<br /> if jar.fill('python juice') == jars.ERROR:<br /> print "Couldn't fill Mityo's jar!"<br /> return ERROR<br /> if jar.close() == jars.ERROR:<br /> print "Couldn't close Mityo's jar!"<br /> return ERROR<br /> return SUCCESS<br /></code></pre> </div> <div class="slide long"> <h1>Традицията не са това…</h1> <p>Сега да опитаме с изключения:</p> <pre><code>"""Модул за зимнината на Митьо Питона"""<br />import jars<br /><br />class MityoWinterError: pass<br /><br />def prepare_for_winter():<br /> try:<br /> jar = jars.Jar()<br /> jar.clean()<br /> jar.fill('python juice')<br /> jar.close()<br /> except jars.Error:<br /> raise MityoWinterError<br /></code></pre> </div> <div class="slide longlong"> <h1>Синтаксис и семантика</h1> <pre><code>try:<br /><br /> <em>блок</em><br /><br />except <em>изключения</em>:<br /><br /> <em>блок</em> <span>ако се случи някое от описаните изключения</span><br /><br />…<br /><br />except <em>още изключения</em>:<br /><br /> <em>блок</em> <span>ако се случи някое от описаните изключения</span><br /><br />except:<br /><br /> <em>блок</em> <span>ако изключението не е хванато по-горе</span><br /><br />finally:<br /><br /> <em>блок</em> <span>изпълнява се <strong>винаги</strong></span><br /><br />else:<br /><br /> <em>блок</em> <span>ако не е възникнала изключителна ситуация</span><br /></code></pre> </div> <div class="slide long"> <h1>Аз не (при|с)хващам</h1> <p>По подразбиране при неприхванато изключение Python спира изпълнението на програмата и отпечатва на стандартната грешка описание и реда на извикване на функциите до момента на грешката.</p> <p><strong>bad.py</strong>:</p> <pre><code>l = [1, 2, 3]<br />def bad(): print l[3]<br />bad()</code></pre> След изпълнение получаваме: <pre><code>$ python bad.py<br /><samp class="error">Traceback (most recent call last):<br /> File "bad.py", line 3, in <module><br /> bad()<br /> File "bad.py", line 2, in badfunc<br /> def badfunc(): print l[3]<br />IndexError: list index out of range</samp></code></pre> <p>Изключенията се използват активно от вградените средства в езика.</p> </div> <div class="slide longlong"> <h1>Започвам да (при|с)хващам</h1> <pre><code>def distribute_over(beers):<br /> try:<br /> return 333/beers<br /> except ZeroDivisionError:<br /> return 0</code></pre> <p>Изключенията са класове, инстанции или низове, като последните не е препоръчително да се ползват.</p> <p><code>>>> ZeroDivisionError<br /><type></code></p> <p>Можем да прихванем и по-общо тип изключение (родителски клас):</p> <pre><code>def distribute_over2(beers):<br /> try:<br /> return 333/beers<br /> except ArithmeticError:<br /> return 0</code></pre> <p>Ето и доказателство:</p> <p><code>>>> issubclass(ZeroDivisionError, ArithmeticError)<br />True</code></p> <p>Тази практика е много логична, тъй като делението на нула е и аритметична грешка и когато прихващаме аритметичните грешки би трябвало да хванем и делението на нула.</p> </div> <div class="slide longlong"> <h1>По-гъвкаво прихващане</h1> <ul><li>Можем да вземем и повече информация за изключението: <pre><code>try:<br /> x = [] / 4<br />except TypeError, data:<br /> print data</code></pre> Какво ще има в <code>data</code>, зависи от самото изключение, но е прието всички да връщат годна за отпечатване стойност, ако се дадат като аргументи на <code>str</code> или <code>repr</code>. </li><li>Ако за няколко изключения имаме една и съща реакция, можем да ги прихванем накуп: <pre><code>try:<br /> doomed()<br />except (NameError, TypeError), data:<br /> print data<br />except (MyError, YourError):<br /> print "Opps! This shouldn't've hapenned..."<br />except:<br /> print "Unknown exception."<br />else:<br /> print "It's my happy day!"</code></pre></li><li>с празен <code>except</code> прихващаме изключения, които не са били хванати до момента. Трябва да бъде поставен след всички други <code>except</code>-и</li></ul> </div> <div class="slide"> <h1>finally</h1> <pre><code>file = open('data.txt')<br />try:<br /> mymodule.load_info(file)<br />except IOError, data:<br /> print "Couldn't read from file: %s" % data<br />except (mymodule.BadDataError, mymodule.InternalError), data:<br /> print "Loading failed: %s" % data<br />else:<br /> print "Data loaded successfully from file."<br />finally:<br /> file.close()</code></pre> <p>Ако присъства, <code>finally</code> стои винаги най-отдолу.</p> </div> <div class="slide long"> <h1>Пораждане на изключителни ситуации — низове (1)</h1> <pre><code>LonelyError = "Mityo is lonely!"<br />def make_lonely(): raise LonelyError<br />try:<br /> make_lonely()<br />except LonelyError:<br /> print LonelyError</code></pre> <p>Можем към низа да дадем и допълнителна информация:</p> <pre><code>LonelyError = "Mityo is lonely!"<br />def make_lonely(level): raise MyError, level<br />try:<br /> make_lonely(666)<br />except LonelyError, level:<br /> print "Mityo's loneliness is at level %d" % level</code></pre> </div> <div class="slide long"> <h1>Пораждане на изключителни ситуации — низове (2)</h1> <p>За да се определи дали едно изключение съвпада с конкретно <code>except</code> твърдение двете изключение се сравняват с <code>is</code>, а не с <code>==</code>:</p> <pre><code>LonelyError0 = "Mityo is lonely!"<br />LonelyError1 = "Mityo is lonely!"<br /><br />def make_lonely(): raise LonelyError0<br />try:<br /> make_lonely()<br />except LonelyError1:<br /> print LonelyError1</code></pre> <p>води до:</p><pre><code><samp class="error">Traceback (most recent call last):<br /> File "<stdin>", line 2, in <module><br /> File "<stdin>", line 1, in make_lonely<br />Mityo is lonely!</samp></code></pre> </div> <div class="slide longlong"> <h1>Пораждане на изключения — класове (1)</h1> <pre><code>class MityoError:<br /> def __init__(self, msg = "There is something wrong with Mityo!"):<br /> self.msg = msg<br /> def __repr__(self): return self.msg<br /> def __str__(self): return self.__repr__()<br /><br />class LonelyMityoError(MityoError):<br /> def __init__(self):<br /> MityoError.__init__(self, "Mityo is Lonely!")<br /><br />class StupidMityoError(MityoError): pass<br /><br />def make_lonely(): raise LonelyMityoError()<br /><br />def eat_a_cockroach(): raise StupidMityoError<br /><br />try:<br /> make_lonely()<br />except StupidMityoError:<br /> print "Mityo has been somehow stupid!"<br />except MityoError, data:<br /> print data</code></pre> </div> <div class="slide longlong"> <h1>Пораждане на изключения — класове (2)</h1> <p>2 начина за пораждане:</p> <ul><li><code>raise <em>клас</em>, <em>инстанция</em> # инстанцията е от точно този клас</code></li><li><code>raise <em>инстанция</em> # примерът със самотния Митьо, същото като<br /> raise <em>инстанция</em>.__class__, <em>инстанция</em></code></li></ul><br /><p>За обратна съвместимост с низовите изключения могат да се използват и следните начини:</p> <ul><li><code>raise <em>клас</em> # примерът с тъпия Митью,<br />същото като raise <em>клас</em>()</code></li><li><code>raise <em>клас</em>, arg # същото като raise <em>клас</em>(arg)</code></li><li><code>raise <em>клас</em>, (arg0, arg1) # същото като raise <em>клас</em>(arg0, arg1)</code></li></ul> <p>Пример:</p> <pre><code>class MyError():<br /> def __init__(self, msg, num):<br /> print "%s (%d)" % (msg, num)<br /><br />try:<br /> raise MyError, ("Initialized", 99)<br />except MyError: pass<br /><br /><samp class="error">Initialized (99)</samp><br /></code></pre> </div> <div class="slide longlong"> <h1>Далаверата от изключенията с класове </h1> <ul><li>Прихващат се всички наследници — така лесно можем да си структурираме типовете грешки. <pre><code>class EmotionalMityoError(MityoError): pass<br />class LonelyMityoError(EmotionalMityoError): pass<br />class ConfusedMityoError(EmotionalMityoError): pass<br />class MoneyMityoError(MityoError): pass<br /><br />mityo = Mityo()<br />try:<br /> mityo.live_a_day()<br />except MoneyMityoError:<br /> mityo.rob_a_bank()<br /><br /># прихващаме по-общия проблем, а не по-частните Lonely и Confused<br /># от инстанцията на проблема психоаналитика може да извлече ценна информация<br />except EmotionalMityoError, problem:<br /> mityo.go_to_shrink(problem)<br /><br />except MityoError:<br /> mityo.call_911()<br />else:<br /> mityo.set_happy_bit()<br />finally:<br /> mityo.play_with(Girl(beauty=99, hair='blonde')*3)<br /></code></pre></li></ul> </div> <div class="slide longlong"> <h1>Същото ама с низове </h1> <pre><code>EmotionalMityoError = "Mityo has an emotional problem!"<br />LonelyMityoError = "Mityo is lonely!"<br />ConfusedMityoError = "Mityo is confused!"<br />MoneyMityoError = "Mityo is out of money!"<br /><br />mityo = Mityo()<br />try:<br /> mityo.live_a_day()<br />except MoneyMityoError:<br /> mityo.rob_a_bank()<br /><br /># налага се да опишем всички наследници на EmotionalError на ръка<br /># при всяко добавяне на грешка, трябва да я добавяме и тук<br />except (EmotionalMityoError, LonelyMityoError, ConfusedMityoError), problem:<br /> mityo.go_to_shrink(problem)<br /><br /># тук пък трябва да опишем всички други грешки...<br /># което си е ад за поддръжка, почти като москвич осмак<br />except MityoError:<br /> mityo.call_911()<br />else:<br /> mityo.set_happy_bit()<br />finally:<br /> mityo.play_with(Girl(beauty=99, hair='blonde')*3)<br /></code></pre> </div> <div class="slide long"> <h1>Ескалиране на грешката</h1> <ul><li>Когато Python се натъкне на изключение в даден блок и в него то не се обработи, изключението се праща към горния блок, после към по-горния и така докато или изключението не бъде прехванато или не стигнем най-отгоре и интерпретаторът не спре програма по познатия ни вече начин (в червеничко).</li><li>Можем да се намесим в следната схема или като прихванем изключението (вече знаем как), или като пратим изключението нагоре по трасето. Последното става с голо извикване на <code>raise</code>: <pre><code>try:<br /> mityo.live_a_day()<br />except GirlfriendMityoError:<br /> mityo.lonely = True<br /> # Митьо не може да се оправя с това, нека тези отгоре да се грижат<br /> raise</code></pre></li></ul> </div> <div class="slide longlong"> <h1>assert</h1> <ul><li><code>assert <em><проверка></em>, [<em><данни></em>]</code></li><li>Целта на твърдението <code>assert</code> е да се подсигурите, че важно за вашата програма условие е изпълнено</li><li><code>assert test, data</code> е еквивалентно на:<pre><code>if __debug__:<br /> if not test:<br /> raise AssertionError, data</code></pre> <code>data</code> никак не е задължително</li><li>Както си личи от примера, <code>assert</code> рядко се ползва в крайния продукт, а най-вече по време на разработка за да си спестим главоболия и да сме сигурни в целостта на данните си</li><li>По подразбиране глобалният атрибут <code>__debug__</code> има стойност <code>1</code> като може да бъде променена от вас или от опцията на командния ред <code>-O</code> (оптимизация), която го установява на <code>False</code></li><li class="code"><pre><code>def fib(n):<br /> assert n >= 0<br /> if n <= 1:<br /> return n<br /> else:<br /> return fib(n-2) + fib(n-1)</code></pre></li></ul> </div> <div class="slide longlong"> <h1>Вградени класове за изключения</h1> <ul><li>Основният, който всички наследяват е <code>Exception</code></li><li>Главни категории: <dl><dt><code>StandardError</code></dt><dd>родител на всички вградени изключения; директен наследник на <code>Exception</code></dd><dt><code>ArithmeticError</code></dt><dd>родител на <code>OverflowError</code>, <code>ZeroDivisionError</code>, <code>FloatingPointError</code></dd><dt><code>LookupError </code></dt><dd>родител на <code>IndexError</code>, <code>KeyError</code></dd><dt><code>EnvironmentError</code></dt><dd>родител на изключенията, които се случват извън интерпретора: <code>IOError</code>, <code>OSError</code></dd></dl> </li><li>Какво може да направи <code>Exception</code> за нас? <ul><li class="code"><pre><code>>>> class MyError(Exception): pass<br />>>> raise MyError("Failed, you have!", -1)<br />Traceback (most recent call last):<br /> File "<stdin>", line 1, in ?<br />__main__.MyError: ('Failed, you have!', -1)<br />>>> error = MyError("Failed, you have!", -1)<br />>>> error.args<br />('Failed, you have!', -1)<br /></code></pre></li><li>пази аргументите, които сме дали при създаване в <code>args</code></li><li>дефинира <code>__str__</code>, така че да връща нещо като: <code>map(str, self.args)</code></li></ul> </li></ul> </div> <div class="slide long"> <h1>Използване на изключение не само за грешки</h1> <ul><li>за прихващане на събития през няколко блока дълбочина <pre><code>try:<br /> for box in boxes:<br /> for jar in box.jars():<br /> jar.has(throw=True, colour='velvet', eyes='cheese')<br />except JarFound, good_jar:<br /> print "We found the jar! Its name is %s" % good_jar.name<br />else:<br /> print "I couldn't find it :("</code></pre> </li><li>за всякакви подобни странности на потока на програмата ни</li><li>за обработка на частни случаи</li></ul> </div> <div class="slide long"> <h1>Аз хващам прекалено много</h1> <ul><li><pre><code>def func():<br /> try:<br /> … # някъде тук възниква IndexError<br /> except:<br /> … # тук хващаме всичко и отпечатваме съобщение за грешка<br /><br />try:<br /> func()<br />except IndexError: # нъцки, няма да го хванем тук<br /> …</code></pre></li><li>прихващайте не повече отколкото ви трябва</li><li>използвайте гол <code>except</code> главно в най-високото ниво на програмата си</li></ul> </div> <div class="slide long"> <h1>Ти пък прекалено малко</h1> <ul><li><pre><code>try:<br /> mityo.live_a_day()<br />except (MityoWantsACracker, MityoWantsADrink,<br /> MityoWantsAnIsland, MityoWantsA333YearOldWhiskey,<br /> MityoNeedsPanties, MityoNeedsNewSlippers), thing:<br /> you.buy(whom=mityo, what=thing) </code></pre></li><li>какво ще се случи ако Митьо може да поиска и мармотче? Ами само 111 годишно?</li><li>винаги е по-добре изключенията да се структурират, за да се избегне дългото, кошмарно за поддръжка и податливо на много грешки изброяване: <pre><code>except (MityoWants, MityoNeeds), thing:<br /> …</code></pre></li></ul> </div> <div class="slide"> <h1>Нека обобщим</h1> Няколко неща, за които може да ползваме изключения: <ul><li>обработка на грeшки: <ul><li>структурирани, прихващаеми, позволяващи предаване на допълнителна информация</li><li>вградените функции и твърдения широко ги използват</li><li>пораждане и прихващане на собствени изключения</li></ul> </li><li>безусловно извършване на заключителни действия — <code>finally</code></li><li>предаване на събития между отдалечени структурно части от кода</li></ul> </div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-68594834717456286252009-01-17T11:10:00.000-08:002009-01-17T11:11:23.593-08:00Класове и обекти 2 в Python<div class="slide"> <h1><br /></h1> <h3>„ Програмиране с Python“, <acronym title="Факултет по Математика и Информатика при Софийски Университет">ФМИ</acronym></h3> <h4>19.03.2007г.</h4> </div> <div class="slide long"> <h1>Множествено наследяване (1)</h1> <p>При класове от стар стил, атрибутите се търсят в родителите по дълбочина</p> <pre><code>class A:<br /> def spam(self): print "A's spam"<br />class B(A): pass<br />class C(A):<br /> def spam(self): print "C's spam"<br />class D(B, C): pass<br /><br />d = D()<br />d.spam() # A's spam</code></pre> </div> <div class="slide long"> <h1>Множествено наследяване (2)</h1> <p>При класове от нов стил, атрибутите се търсят в родителите по широчина</p> <pre><code>class A(object):<br /> def spam(self): print "A's spam"<br />class B(A): pass<br />class C(A):<br /> def spam(self): print "C's spam"<br />class D(B, C): pass<br /><br />d = D()<br />d.spam() # C's spam</code></pre> </div> <div class="slide long"> <h1>Динамични класове</h1> <pre><code>class Person(object):<br /> def __init__(self, name): self.name = name<br /> def sayHi(self, someone): print "Hello %s, I'm %s" % (someone, self.name)<br /><br />class NamedThing(object):<br /> def sayMyName(self): print "Beware, for I am %s" % self.name<br /><br />popStarClass = type('PopStar', (Person,), {})<br />popStarClass.__bases__ = (Person, NamedThing)<br /><br />def popStarSayHi(self, someone):<br /> super(popStarClass, self).sayHi(someone)<br /> print "Do you want my autograph?"<br /><br />popStarClass.sayHi = popStarSayHi<br />mityo = popStarClass("Mityo the Python")<br />mityo.sayHi("Dim")<br />mityo.sayMyName()<br /><br />Hello Dim, I'm Mityo the Python<br />Do you want my autograph?<br />Beware, for I am Mityo the Python<br /></code></pre> </div> <div class="slide long"> <h1>Равенство на обекти</h1> <ul><li>Можете да проверите дали два обекта са равни по стойност с оператора <code>==</code></li><li>Можете да проверите дали две имена сочат към един и същи обект с оператора <code>is</code></li></ul> <pre><code><br />>>> a = ['spam', 'eggs', 42]<br />>>> b = ['spam', 'eggs', 42]<br /><br />>>> a is b<br />False<br />>>> a == b<br />True<br /><br />>>> c = a<br />>>> a == c<br />True<br />>>> a is c<br />True</code></pre> </div> <div class="slide long"> <h1>Предефиниране на равенство (1)</h1> <p>Можете да предефинирате равенството за обекти от даден клас с функцията <code>__eq__</code></p> <pre><code><br />class Person(object):<br /> def __init__(self, name, age):<br /> self.name, self.age = name, age<br /><br /> def __eq__(self, other):<br /> return isinstance(other, Person) and self.name == other.name \<br /> and self.age == other.age<br /><br />mityo = Person("Mityo the Python", 30)<br />mityo2 = Person("Mityo the Python", 30)<br />mityo3 = Person("Mityo the Gun", 30)<br /><br />print mityo == mityo2 # True<br />print mityo is mityo2 # False<br />print mityo == mityo3 # False<br /></code></pre> </div> <div class="slide"> <h1>Предефиниране на равенство (2)</h1> <p>По подразбиране, <code>__eq__</code> е имплементирана с <code>is</code></p> <pre><code><br />class Food(object): pass<br />spam = Food()<br />eggs = Food()<br />moreSpam = spam<br />print spam == moreSpam, spam is moreSpam # True True<br />print spam == eggs, spam is eggs # False False<br /></code></pre> </div> <div class="slide long"> <h1>str и repr (1)</h1> <ul><li>В Python от всеки обект могат да се получат две важни неща - текстов низ (<code>str</code>) и "репрезентация" (<code>repr</code>)</li><li>Текстовото представяне се използва при <code>str(<em>обект</em>)</code> или при <code>"%s" % <em>обект</em></code></li><li>Репрезентацията представлява текст, който ако се изпълни като Python код ще създаде обекта на който е извикан - т.е. <code>eval(repr(<em>обект</em>)) == <em>обект</em></code></li><li>Репрезентация се извежда с <code>repr(<em>обект</em>)</code>.</li></ul> <pre><code><br />>>> print "Spam\nand\neggs"<br />Spam<br />and<br />eggs<br />>>> print repr("Spam\nand\neggs")<br />'Spam\nand\neggs'<br /></code></pre> </div> <div class="slide long"> <h1>str и repr (2)</h1> <p>Можете да дефинирате текстово представяне и репрезентация със "служебните" методи <code>__str__</code> и <code>__repr__</code>.</p> <pre><code><br />class Person(object):<br /> ...<br /> def __repr__(self):<br /> return "Person(%s, %s)" % (repr(self.name), repr(self.age))<br /><br /> def __str__(self):<br /> return self.name<br /><br />>>> mityo = Person("Mityo the Python", 33)<br />>>> str(mityo)<br />Mityo the Python<br />>>> repr(mityo)<br />Person('Mityo the Python', 33)<br />>>> mityo<br />Person('Mityo the Python', 33)<br />>>> eval(repr(mityo))<br />Person('Mityo the Python', 33)<br /></code></pre> </div> <div class="slide long"> <h1>Сравняване на обекти (1)</h1> <pre><code>class Person:<br /> def __init__(self, name): self.name = name<br /> def __eq__(self, other):<br /> return self.name == other.name<br /><br />>>> mityo = Person("Mityo the Python")<br />>>> mityo2 = Person("Mityo the Python")<br />>>> mityo == mityo2<br />True<br />>>> mityo != mityo2<br />True<br />>>> print "WTF?!"</code></pre> <ul><li><code>__eq__</code> не предефинира <code>!=</code></li><li>За целта трябва да дефинирате метода <code>__ne__</code></li></ul> </div> <div class="slide"> <h1>Сравняване на обекти (2)</h1> <p>Други методи за сравняване на обекти:</p> <ul><li><code>__lt__(self, other)</code> # self <><li><code>__le__(self, other)</code> # self <= other</li><li><code>__gt__(self, other)</code> # self > other</li><li><code>__ge__(self, other)</code> # self >= other</li></ul> </div> <div class="slide long"> <h1>Сравняване на обекти (3)</h1> <p>Можете да предефинирате всичките шест оператора <code>__cmp__(self, other)</code>. Този метод трябва да сравнява <code>self</code> и <code>other</code> и да връща:</p> <ul><li>Отрицателно число, ако <code>self <>.</li><li>Нула, ако <code>self == other</code>.</li><li>Положително число, ако <code>self > other</code>.</li></ul> <pre><code><br />class Person(object):<br /> ...<br /> def __cmp__(self, other):<br /> if self.name < other.name: return -1<br /> elif self.name == other.name: return 0<br /> else: return 1<br /><br />>>> mityo = Person("Mityo the Python")<br />>>> dim = Persom("Dim")<br />>>> mityo > dim<br />True</code></pre> </div> <div class="slide"> <h1>Хеш функции</h1> <p>Можете да "задавате" хеш стойностите на вашите обекти дефинирайки метода <code>__hash__</code>.</p> <pre><code>class Person(object):<br /> ...<br /> def __hash__(self):<br /> return len(self.name) + self.age</code></pre> <p>Можете да вземете хеша на даден обект с функцията <code>hash()</code>.</p> <pre><code>>>> mityo = hash(Person("Mityo da Gun", 30))<br />42</code></pre> </div> <div class="slide long"> <h1>Аритметични оператори (1)</h1> <p>Можете да предефинирате аритметичните оператори за вашите типове.</p> <ul><li><code>__add__(self, other)</code> за <code>self + other</code></li><li><code>__sub__(self, other)</code> за <code>self - other</code></li><li><code>__mul__(self, other)</code> за <code>self * other</code></li><li><code>__div__(self, other)</code> за <code>self / other</code></li><li><code>__floordiv__(self, other)</code> за <code>self // other</code></li><li><code>__mod__(self, other)</code> за <code>self % other</code></li><li><code>__lshift__(self, other)</code> за <code>self <<></li><li><code>__rshift__(self, other)</code> за <code>self >> other</code></li><li><code>__and__(self, other)</code> за <code>self & other</code></li><li><code>__xor__(self, other)</code> за <code>self ^ other</code></li><li><code>__or__(self, other)</code> за <code>self | other</code></li></ul> </div> <div class="slide"> <h1>Аритметични оператори (2)</h1> <ul><li>Всеки оператор има вариантен метод за прилагане на операцията "на място" - например <code>+=</code>, <code>/=</code> и т.н.</li><li>Метода има същото име, но със <code>i</code> след двете подчертавки - <code>__add__</code> става <code>__iadd__</code></li><li>Хубаво е когато дефинирате такива методи, те да променят <code>self</code> и да връщат <code>self</code></li></ul> <pre><code><br />a, b, c = MagicNumber(3), MagicNumber(5), MagicNumber(7)<br /><br />a = a + b # MagicNumber.__add__(a, b)<br />a += c # MagicNumber.__iadd__(a, c)<br /></code></pre> </div> <div class="slide"> <h1>Аритметични оператори (3)</h1> <ul><li>Аритметичните оператори имат още един вариант - когато обекта е от дясната страна на операцията</li><li>Те започват с <code>r</code>, т.e. "десния" вариант на <code>__add__</code> е <code>__radd__</code></li><li>При <code>a + b</code>, ще се извика <code>b.__radd__</code> само ако <code>а</code> не дефинира <code>__add__</code>, а <code>b</code> дефинира <code>__radd__</code>.</li><li>Ако <code>b</code> е от тип, наследник на <code>a</code>, то Python ще опита да извика <code>b.__radd__</code> преди да пробва с <code>a.__add__</code>. По този начин наследници могат да предефинират аритметични операции</li></ul> </div> <div class="slide"> <h1>Преобразуване до стандартни типове</h1> <p>Има методи, които може да предефинирате, за преобразования от вашия клас към стандартен тип:</p> <ul><li><code>__int__(self)</code> за <code>int(<em>обект</em>)</code>.</li><li><code>__long__(self)</code> за <code>long(<em>обект</em>)</code>.</li><li><code>__float__(self)</code> за <code>float(<em>обект</em>)</code>.</li><li><code>__complex__(self)</code> за <code>complex(<em>обект</em>)</code>.</li><li><code>__nonzero__(self)</code> за <code>bool(<em>обект</em>)</code>.</li></ul> </div> <div class="slide"> <h1>Колекции</h1> <p>Python ви предлага и оператори, с които можете да третирате вашия клас като колекция:</p> <ul><li><code>__len__(self)</code> за <code>len(<em>обект</em>)</code>.</li><li><code>__getitem__(self, key)</code> за <code><em>обект</em>[key]</code>.</li><li><code>__setitem__(self, key, value)</code> за <code><em>обект</em>[key] == value</code></li><li><code>__delitem__(self, key)</code> за <code>del <em>обект</em>[key]</code>.</li><li><code>__contains__(self, item)</code> за <code>item in <em>обект</em></code>.</li></ul> </div> <div class="slide"> <h1>Обекти които могат да бъдат извиквани като функции</h1> <p>Можете да предефинирате оператора две скоби <code>()</code>.</p> <pre><code>class Stamp(object):<br /> def __init__(self, name): self.name = name<br /> def __call__(self, something):<br /> print "%s was stamped by %s" % (something, self.name)<br /><br />>>> stamp = Stamp("The goverment")<br />>>> stamp("That thing there")<br />That thing there was stamped by The goverment<br /></code></pre> </div> <div class="slide long"> <h1>Атрибути (1)</h1> <ul><li><code>getattr(<em>обект</em>, <em>име_на_атрубит</em>)</code> връща <code>обект.атрибут</code>, където <em>атрибут</em>.</li><li><code>setattr(<em>обект</em>, <em>име_на_атрибут</em>, <em>стойност</em>)</code> присвоява стойност на <code>обект.атрибут</code>.</li><li><code>delattr(<em>обект</em>, <em>име_на_атрибут</em>)</code> работи като <code>del обект.атрибут</code>.</li></ul> <pre><code><br />class Spam: pass<br /><br />>>> spam = Spam()<br />>>> spam.eggs = "Eggs"<br />>>> getattr(spam, 'eggs')<br />Eggs<br />>>> setattr(spam, 'bacon', 'Spam, eggs and bacon')<br />>>> spam.bacon<br />Spam, eggs and bacon<br />>>> delattr(spam, 'bacon')<br /></code></pre> </div> <div class="slide"> <h1>Атрибути (2)</h1> <p>Можете да предефинирате достъпа до атрибутите на вашите обекти с <code>__getattr__</code>, <code>__setattr__</code> и <code>__delattr__</code>. Сигнатурите са следните:</p> <ul><li><code>__getattr__(self, name)</code> за <code>something = object.name</code></li><li><code>__setattr__(self, name, value)</code> за <code>object.name = "Foo"</code></li><li><code>__delattr__(self, name)</code> за <code>del object.name</code></li></ul> </div> <div class="slide long"> <h1>Атрибути (3)</h1> <p><code>__getattr__(self, name)</code> се извиква само, ако обекта няма атрибут с име <code>name</code>.</p> <pre><code><br />class Spam(object):<br /> def __getattr__(self, name):<br /> print "Getting attribute: " + name<br /> return None<br /><br />spam = Spam()<br />spam.eggs = "Eggs"<br />print spam.eggs<br />print spam.foo<br /><br /><br />Eggs<br />Getting attribute: foo<br />None</code></pre> </div> <div class="slide"> <h1>Атрибути (4)</h1> <p><code>__setattr__</code> се извиква, когато присвоявате стойност на атрибута на даден обект. За да не изпаднете в безкрайна рекурсия, ползвайте <code>object.__setattr__</code></p> <pre><code><br />class Turtle(object):<br /> def __setattr__(self, name, value):<br /> print "Setting attribute: " + name<br /> object.__setattr__(self, name, value)<br /><br />turtle = Turtle()<br />turtle.spam = "Spam" # prints 'Setting attribute: spam'<br /></code></pre> </div> <div class="slide long"> <h1>Атрибути (5)</h1> <p>Класовете нов стил имат специален метод <code>__getattribute__</code>, който работи подобно на <code>__getattr__</code>, с тази разлика че се извиква винаги, без значение дали обекта има такъв атрибут или не. Отново, за да не изпаднете в бездънна рекурсия, ползвайте <code>object.__getattribute__</code>.</p> <pre><code>class Crab(object):<br /> def __getattribute__(self, name):<br /> print "Getting attribute: " + name<br /> return object.__getattribute__(self, name)<br /> <br />crab = Crab()<br />crab.spam = "Spam"<br />crab.eggs = "Eggs"<br />print crab.spam<br />print crab.eggs<br /><br /><br /><br />Getting attribute: spam<br />Spam<br />Getting attribute: eggs<br />Eggs<br /></code></pre> </div> <h1>Множествено наследяване</h1> <p>Просто изброявате повече от един клас в скобите.</p> <pre><code>class A: pass<br />class B: pass<br />class C: pass<br />class D(A, B, C): pass</code></pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-19598026922093637232009-01-17T11:09:00.000-08:002009-01-17T11:10:21.713-08:00Класове и обекти в Python<div class="presentation"> <div class="slide"> <h1><br /></h1> <h3>„ Програмиране с Python“, <acronym title="Факултет по Математика и Информатика при Софийски Университет">ФМИ</acronym></h3> <h4>14.03.2007г.</h4> </div> <div class="slide long"> <h1>Python и Зен философията</h1> <pre><code>>>> import this<br />The Zen of Python, by Tim Peters<br /><br />Beautiful is better than ugly.<br />Explicit is better than implicit.<br />Simple is better than complex.<br />Complex is better than complicated.<br />Flat is better than nested.<br />Sparse is better than dense.<br />Readability counts.<br />Special cases aren't special enough to break the rules.<br />Although practicality beats purity.<br />Errors should never pass silently.<br />Unless explicitly silenced.<br />In the face of ambiguity, refuse the temptation to guess.<br />There should be one-- and preferably only one --obvious way to do it.<br />Although that way may not be obvious at first unless you're Dutch.<br />Now is better than never.<br />Although never is often better than *right* now.<br />If the implementation is hard to explain, it's a bad idea.<br />If the implementation is easy to explain, it may be a good idea.<br />Namespaces are one honking great idea -- let's do more of those!</code></pre> </div> <div class="slide"> <h1>Класовете, обектите и питоните</h1> <ul><li>Всичо е обект - дори функциите и модулите.</li><li>Обектите и класовете са динамични - може да ги разширявате с полета и методи по време на изпълнение</li><li>Има множествено наследяване.</li><li>Има „нов стил“ класове и „класически“ класове.</li><li>Може да предефинирате оператори.</li><li>Има и метакласове - както "клас" е тип на обекта, така "метаклас" е тип на класа.</li></ul> </div> <!-- * Класовете и обектите са отворени --> <div class="slide"> <h1>Основи на класовете (1)</h1> <ul><li>Дефинират се с <code>class</code>, последван от блок</li><li>Дефинираните функции в този блок са методи на класа</li><li>Първият им аргумент - <code>self</code> - reference към обекта, на който ги извиквате</li><li>Дефинираните в този блок променливи са статични за класа</li></ul> </div> <div class="slide long"> <h1>Основи на класовете (2)</h1> <pre><code><br />class Person:<br /> """Represents a person."""<br /> people = 0<br /><br /> def __init__(self, name):<br /> """Constructs a new person."""<br /> self.name = name<br /> Person.people += 1<br /><br /> def sayHi(self):<br /> """Presents one's self."""<br /> print "Hello, I'm %s!" % self.name<br /><br />>>> mityo = Person("Mityo the Python")<br />>>> mityo.sayHi()<br />Hello, I'm Mityo the Python!<br />>>> guido = Person("Guido")<br />>>> guido.sayHi()<br />Hello, I'm Guido!<br />>>> print Person.people<br />2<br /></code></pre> </div> <div class="slide long"> <h1>Полета (1)</h1> <ul><li>Методите имат достъп до полетата на обекта със <code>self</code></li><li>Извън тялото на класа, имате достъп до полетата му през неговото име</li></ul> <pre><code><br />class Spam:<br /> def __init__(self, arg)<br /> self.stored = arg<br /><br />>>> spam = Spam(42)<br />>>> print spam.stored<br />42<br />>>> spam.stored = 60<br />>>> print spam.stored<br />60<br />>>> spam.foo = 10<br />>>> print spam.foo<br />10<br /></code></pre> </div> <div class="slide"> <h1>Полета (2)</h1> <p>По този начин може да използвате класовете като структури:</p> <pre><code>class Student: pass<br /><br />>>> john = Student()<br />>>> john.name = "Ivan"<br />>>> john.age = 21<br />>>> john.facultyNumber = 98789</code></pre> </div> <div class="slide long"> <h1>Методи</h1> <ul><li>Всички методи вземат reference към обекта, на който са извикани като първи аргумент.</li><li>Стандарт е този reference да се казва <code>self</code>.</li><li>Можете да викате метода както с <code>обект.метод(аргументи)</code>, така и с <code>клас.метод(обект, аргументи)</code></li></ul> <pre><code><br />class Person:<br /> def __init__(self, name):<br /> self.name = name<br /><br /> def greet(self, somebody):<br /> print "Hello %s, I'm %s!" % (somebody, self.name)<br /><br />>>> mityo = Person("Mityo the Python")<br />>>> mityo.greet('Dim')<br />Hello Dim, I'm Mityo the Python!<br />>>> Person.greet(mityo, 'Dim')<br />Hello Dim, I'm Mityo the Python!<br /></code></pre> </div> <div class="slide"> <h1>Методи (2)</h1> <p>Интересен страничен (или не толкова страничен) ефект е следното:</p> <pre><code>>>> person = Person("Mityo the Python")<br />>>> greetSomeone = person.greet<br />...<br />>>> greetSomeone("Dim")<br />Hello Dim, I'm Mityo the Python!</code></pre> <p>Обаче:</p> <pre><code>>>> greeter = Person.greet<br />>>> greeter(mityo, "Dim")</code></pre> </div> <div class="slide"> <h1>Статични методи</h1> <p>При статичните методи положението е малко странно:</p> <pre><code>class Person:<br /> people = []<br /> def register(name):<br /> Person.people.append(name)<br /> print len(Person.people), "people are registered now"<br /> register = staticmethod(register)<br /><br />>>> Person.register("Mityo the Python")<br />1 people are registered now<br />>>> Person.register("Pooh")<br />2 people are registered now<br /></code></pre> </div> <div class="slide"> <h1>Класови методи</h1> <p>В Python има "класови" методи, които вземат класът на който са извикани като първи аргумент. Понякога е полезно при наследяване:</p> <pre><code>class Something:<br /> def greet(cls, someone):<br /> print someone, "was greeted from", cls<br /> greet = classmethod(greet)<br /><br />>>> Something.greet("Mityo")<br />Mityo was greeted from __main__.Something<br /></code></pre> </div> <div class="slide long"> <h1>Конструкция</h1> <ul><li>За да създадете инстанция на клас, ползвате оператора <code>()</code> върху класа</li><li>Конструктурът на класовете се кaзва <code>__init__</code> и взема новосъздадения обект като първи аргумент</li><li>Има и алтернативен начин на създаване - <code>__new__</code>, но той работи само при класове от нов стил</li></ul> <pre><code><br />class Person:<br /> def __init__(self, name, age, location="Sofia")<br /> self.name = name<br /> self.age = age<br /> self.location = location<br /><br />>>> person = Person("Mityo the Python", 30, "Great Tarnovo")<br /></code></pre> </div> <div class="slide long"> <h1>Наследяване</h1> <p>Проста хватка:</p> <pre><code>class Something:<br /> def __init__(self, name): self.name = name<br /> def introduce(self): "This is something called", self.name<br /><br />class Vegetable(Something):<br /> def eat(self): print self, "was eaten"<br /><br />class Animal(Something):<br /> def notice(self): print "Look! This is a", self.name<br /> def introduce(self): print "This is an animal called", self.name<br /><br />>>> snake = Animal("python")<br />>>> snake.introduce()<br />This is an animal called python<br />>>> snake.notice()<br />Look! It's a python<br /></code></pre> </div> <div class="slide"> <h1>Методи и променливи на родителите</h1> <p>Стандартното <code>клас.метод</code> би трябвало да ви е достатъчно:</p> <pre><code>class PopularPerson(Person):<br /> def greet(self, somebody):<br /> Person.greet(self, somebody)<br /> print "Do you want my autograph?"<br /><br />>>> pop = PopularPerson("Mityo the Python")<br />>>> pop.greet("Dim")<br />Hello Dim, I'm Mityo the Python!<br />Do you want my autograph?<br /></code></pre> </div> <div class="slide long"> <h1>Protected и private</h1> <ul><li>В Python няма protected и private променливи - всичко е достъпно отвън! Все пак има неписано правила.</li><li>Имена от типа <code>_име</code> се смятат за protected</li><li>Имена от типа <code>__име</code> се смятат за private</li><li>Интерпретаторът променя имената от типа <code>__име</code> до <code>_клас__име</code>. Това се нарича name mangling и ефектът му е подобен на private в други езици</li></ul> <pre><code><br />>>> class Spam:<br />... def __stuff(self): pass<br />...<br />>>> dir(Spam)<br />['_Spam__stuff', '__doc__', '__module__']<br /></code></pre> </div> <div class="slide long"> <h1>Protected и private (2)</h1> <pre><code>class Base:<br /> def __init__(self, name, age):<br /> self.__name = name<br /> self._age = age<br /><br /> def reportBase(self):<br /> print "Base:", self.__name, self._age<br /><br />class Derived(Base):<br /> def __init__(self, name, age, derivedName):<br /> Base.__init__(self, name, age)<br /> self.__name = derivedName<br /> self._age = 33<br /><br /> def reportDerived(self):<br /> print "Derived:", self.__name, self._age<br /><br />>>> derived = Derived("Mityo the Python", 30, "Mityo the Gun")<br />>>> derived.reportBase()<br />Base: Mityo the Python 33<br />>>> derived.reportDerived()<br />Derived: Mityo the Gun 33<br />>>> derived._Base__name, ", ", derived._Derived__name<br />Mityo the Python, Mityo the Gun<br /></code></pre> </div> <div class="slide"> <h1>Класове в нов стил</h1> <ul><li>Въведени в Python 2.2 за да добавят нови възможности в езика, без да чупят стар код</li><li>Наследяват <code>object</code> или клас, който наследява <code>object</code> - <code>list</code>, <code>dict</code>, <code>tuple</code>, <code>str</code> и т.н.</li><li>Другите класове се наричат "класически"</li><li>Променят малко множественото наследяване.</li><li>Дават ви нов начин за конструкция - <code>__new__</code>.</li><li>Можете да ограничавате полетата им със <code>__slots__</code>.</li></ul> </div> <div class="slide"> <h1>Класове в нов стил — __new__</h1> <pre><code><br />class SpamTuple(tuple):<br /> def __new__(cls, number = 1):<br /> result = ("Spam",) * number<br /> return tuple.__new__(cls, result)<br /><br /> def countSpam(self):<br /> return len(self)<br /><br />spams = SpamTuple(3)<br />print spams # ('Spam', 'Spam', 'Spam')<br />print spams.countSpam() # 3<br /></code></pre> </div> <div class="slide"> <h1>Класове в нов стил - __slots__</h1> <pre><code><br />class Something(object):<br /> __slots__ = ['spam', 'eggs']<br /><br />>>> smth = Something()<br />>>> smth.spam = 1<br />>>> smth.eggs = 2<br />>>> smth.foo = 3<br /><span style="color: red;">Traceback (most recent call last):<br /> File "<stdin>", line 5, in <module><br />AttributeError: 'Something' object has no attribute 'foo'</span><br /></code></pre> </div> <div class="slide"> <h1>Множествено наследяване</h1> <p>Просто изброявате повече от един клас в скобите.</p> <pre><code>class A: pass<br />class B: pass<br />class C: pass<br />class D(A, B, C): pass</code></pre> <p>Малко по-късно за класическите проблеми, които произтичат от това</p> </div> </div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-28551138788413435522009-01-17T11:08:00.000-08:002009-01-17T11:09:15.858-08:00Тескстови низове в Python<div class="presentation"> <div class="slide"> <h1><br /></h1> <h3>„ Програмиране с Python“, <acronym title="Факултет по Математика и Информатика при Софийски Университет">ФМИ</acronym></h3> <h4>12.03.2007г.</h4> </div> <div class="slide long"> <h1>Текстови низове</h1> <p>Текстовите низове са поредици (като списъците например), които обаче не могат да бъдат променяни на място — immutable</p> <pre><code>>>> sentence = "The quick brown fox jumps over the lazy dog"<br />>>> sentence[4]<br />'q'<br />>>> sentence[-1] = 't'<br /><span style="color: red;">Traceback (most recent call last):<br /> File "<stdin>", line 1, in <module><br />TypeError: 'str' object does not support item assignment</span><br />>>> for x in sentence: print x,<br />T h e q u i c k b r o w n f o x j u m p s o v e r t h e l a z y d o g<br />>>> sentence[-1:-4:-1]<br />'god'<br />>>> 'fox' in sentence<br />True<br /></code></pre> </div> <div class="slide"> <h1>Съединяване (конкатенация)</h1> <ul><li>Низове се съединяват с оператора <code>+</code> <pre><code>firstName, lastName = "Eric", "Idle"<br />print firstName + " " + lastName # "Eric Idle"</code></pre> </li><li>Не можете да съберете низ с нещо друго - трябва предварително да го преобразувате: <pre><code>>>> heading, answer = "The answer: ", 42<br />>>> print heading + answer<br /><span style="color: red;">Traceback (most recent call last):<br /> File "<stdin>", line 1, in <module><br />TypeError: cannot concatenate 'str' and 'int' objects</span><br />>>> print heading + str(answer)<br />The answer: 42<br /></code></pre> </li></ul> </div> <div class="slide long"> <h1>Форматиране (1)</h1> <p>Подобно е по функционалност на <code>printf</code> в C</p> <p>Синтаксис: <code><em>форматен низ</em> % <em>стойностите в n-торка</em></code></p> <p>Примери:</p> <pre><code>>>> "This is %d %s bird!" % (1, 'dead')<br />This is 1 dead bird!<br />>>> exclamation = "Ni"<br />>>> "The knights who say %s!" % exclamation<br />'The knights who say Ni!"</code></pre> <p>Параметрите могат да бъдат различни в зависимост от типа им:</p> <ul><li><code>%s</code> - текстов низ</li><li><code>%r</code> - текстов низ, но с <code>repr()</code></li><li><code>%d</code>, <code>%i</code> - цели числа</li><li><code>%f</code> - число с плаваща запетая</li><li><code>%%</code> - процент (%)</li></ul> </div> <div class="slide long"> <h1>Форматиране (2)</h1> <p>Същият механизъм работи може да работи и с речници</p> <pre><code>>>> "%(adjective)s %(noun)s" % {'adjective': 'Black',<br /> 'noun': 'Knight'}<br />Black Knight<br />>>> def word(adjective, noun):<br />... print "%(adjective)s %(noun)s" % vars()<br />>>> word('Black', 'Knight')<br />Black Knight</code></pre> </div> <div class="slide long"> <h1>Методи (1)</h1> <p>Преобразувания</p> <pre><code>>>> string = 'my Dead Parrot'<br />>>> string.capitalize() # Първата буква главна, другите малки<br />'My dead parrot'<br />>>> string.title() # Всички думи започват с главна буква<br />'My Dead Parrot'<br />>>> string.upper() # Прави всички букви главни<br />'MY DEAD PARROT'<br />>>> string.lower() # Прави всички букви малки<br />'my dead parrot'<br /># дава ни списък с отделните части на низа, разделени с аргумента на split<br />>>> string.split(' ')<br />['my', 'Dead', 'Parrot']<br /></code></pre> </div> <div class="slide"> <h1>Методи (2)</h1> <p>Премахване на символи отляво или отдясно.</p> <pre><code><br />>>> spam = " S P A M "<br />>>> spam.strip()<br />'S P A M'<br />>>> spam.lstrip()<br /></code></pre> <p>По подразбиране премахва white-space, но може и да му се каже изрично низ със символи, които да премахне.</p> <pre><code><br />'S P A M '<br />>>> "He said:muuuuuuuuuu".rstrip('mu')<br />'He said:'<br /></code></pre> </div> <div class="slide long"> <h1>Методи (3)</h1> <p>Търсене из низа</p> <pre><code>>>> message = "Be vewy vewy quiet. I'm hunting for wabbits!"<br />>>> string.startswith('Be') # Проверява дали string започва с 'my'<br />True<br />>>> string.endswith('bits!') # Проверява дали string завършва на 'bits!'<br />True<br />>>> message.find('vewy')<br />3<br />>>> message.index('vewy')<br />3<br />>>> message.rfind('vewy')<br />8<br />>>> message.rindex('vewy')<br />8<br />>>> message.replace('wabbits', 'Buggs Bunny')<br />"Be vewy vewy quiet. I'm hunting for Buggs Bunny!"<br /></code></pre> </div> </div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-9680080521400569442009-01-17T11:07:00.001-08:002009-01-17T11:07:53.481-08:00Модули в python<div class="slide"> <h1><br /></h1> <h3><span style="font-size:85%;">„ Програмиране с Python“, <acronym title="Факултет по Математика и Информатика при Софийски Университет">ФМИ</acronym></span></h3> <h3><span style="font-size:85%;">Стефан Кънев & Николай Бачийски</span></h3> <h4><span style="font-size:85%;">12.03.2007г.</span></h4> </div> <div class="slide"> <h1>Елементарен проблем</h1> <p>world.py:</p><pre><code><br />""" A module for playing with the world. """<br />def destroy():<br /> """Destroys the world."""<br /> print "The world was destroyed!"<br /><br />def save(kind):<br /> """Saves a kind."""<br /> print "All the", kind, "were saved."<br /></code></pre> <p> Искаме да ползваме горните функции в много програми, а не искаме да копираме кода във всяка от тях. </p> </div> <div class="slide"> <h1>Елементарно решение</h1> <p>women.py:</p> <pre><code>import world<br />world.save('women')<br />world.destroy()</code></pre> animals.py:<pre><code>import world<br />world.save('animals')<br />world.destroy()</code></pre> <p><small>Работи без проблеми ако трите файла са в една директория.</small><br />Чрез модули можем да използваме един и същи код много пъти (code reuse).</p> </div> <div class="slide longlong"> <h1>Атрибути</h1> <ul><li>Обектите имат свързани с тях имена, наречени <em>атрибути</em>, които се достъпват чрез оператора <code>.</code> (точка)</li><li>Нека разгледаме по-подробно <code>world.destroy()</code></li><li><code>destroy</code> е функция и е атрибут на обекта <code>world</code>, който пък е модул</li><li class="code"><pre><code>>>> world<br /><module></code></pre></li><li class="code"><pre><code>>>>world.destroy<br /><function></code></pre></li><li>с вградената функция <code>dir</code> можем да видим всички атрибути на обект:</li><li class="code"><pre><code>>>> dir(world)<br />['__builtins__', '__doc__', '__file__', '__name__', 'destroy', 'save']<br />>>> world.__doc__<br />' A module for playing with the world. '<br />>>> world.__name__<br />'world'</code></pre></li></ul> </div> <div class="slide"> <h1>Области от имена (1)</h1> <ul><li>Всяка програма е модул сама по себе си и всички глобални имена, са негови атрибути</li><li>savepoohs.py:</li><li class="code"><pre><code>import world<br />def savePoohs():<br /> world.save('Poohs')<br />insane = True<br />print dir()</code></pre></li><li>Ще отпечата: <code>[<системни атрибути> 'world', 'savePoohs', 'insane']</code></li></ul> </div> <div class="slide"> <h1>Области от имена (2)</h1> <ul><li>В различни модули можем да имаме едни и същи имена</li><li>Всеки модул си има различен набор от имена</li><li class="code"><pre><code>import pooh<br />import piglet<br />def breakfast():<br /> print "Is it already eleven?"<br />pooh.breakfast()<br />piglet.breakfast()<br />breakfast()</code></pre></li></ul> <p>Ако използваме модули няма нужда да се притесняваме, че в няколко програми сме използвали едни и същи имена.</p> </div> <div class="slide"> <h1>Търсене на атрибути</h1> <ul><li class="code"><code>answer = 42</code></li><li>в този случай е ясно, че обектът зад името <code>answer</code> трябва да се търси по стандартния начин (в разните обхвати)</li><li class="code"><code>pooh.naivete = 42</code></li><li>името <code>naivete</code> не трябва да се търси в стандартните обхвати, а трябва да се търси в списъка с атрибути на обекта зад името <code>pooh</code></li><li><code>universe.milkyway.earth.europe.bg.beautify()</code></li></ul> </div> <div class="slide long"> <h1>Модули и обхвати</h1> <ul><li>Глобалните променливи са на практика модулни променливи. Те са глобални само в рамките на модула, в който се намират.</li><li>mod.py:</li><li class="code"><pre><code>bottles = 1<br />def addBottle():<br /> global bottles<br /> bottles += 1</code></pre></li><li>bottler.py:</li><li class="code"><pre><code>import mod<br />bottles = 5<br />mod.addBottle()<br />print bottles, mod.bottles</code></pre></li></ul> </div> <div class="slide"> <h1>Използване на модули — <code>import</code></h1> <p>Чрез вградената фунцкия <code>import</code> ни дава възможност да ползваме код от външни файлове.</p> <p>Ето какво се случва, ако изпълним <code>import mod</code>:</p> <ol><li>Намира се файла, в който се намира модула</li><li>Кодът се компилира до байт-код (ако е необходимо)</li><li>Кодът на модула се изпълнява (дефиниции на функции, друг код)</li><li>На името <code>mod</code> се присвоява обекта на изпълнения модул</li></ol> </div> <div class="slide long"> <h1>Търсене на файла</h1> <code>import mod</code> <p>Търси се в:</p> <ol><li>текущата директория</li><li>променливата на средата <code>PYTHONPATH</code></li><li>системни директории с модули</li><li>директории, описани в <code>.pth</code> файлове</li></ol> <p>Всички по реда на претърсване: списъка <code>sys.path</code></p> </div> <div class="slide long"> <h1>Модул vs. Програма</h1> <ul><li>И в двата случая кодът ни се изпълнява</li><li>Искаме ако кодът ни е бил изпълнен директно да тестваме модула си</li><li>Искаме ако кодът ни е бил включен с <code>import</code> само да дефинираме фукнциите си</li><li>eater.py:</li><li class="code"><pre><code>def eat(what):<br /> print what, "was eaten."<br /> <br />if (__name__ == '__main__'):<br /> eat('The world as we know it')</code></pre></li><li><code>$ python eater.py<br />The world as we know it was eaten.</code></li><li><code>>>> import eater</code></li></ul> </div> <div class="slide"> <h1>Пакети от модули</h1> <p>Представете си, че имаме две отделни системи, в които има модул на име <code>game</code></p> <pre>system1/<br /> game.py<br /> <други модули><br />system2/<br /> game.py<br /> <други модули><br /></pre> <p>Сега напишете система, която използва модулите <code>game</code> и от двете други:</p> <code>import game<br />game.play()</code> <p>Тук вече имаме малък проблем.</p> </div> <div class="slide long"> <h1>Пакети от модули (2)</h1> <p>Би било много удобно ако можехме да разделим двата модула <code>game</code> в отделни пакети:</p> <pre><code>import system1.game<br />import system2.game<br />system1.game.play()<br />system2.game.play()</code></pre> <p>Това е възможно при няколко условия:</p> <ul><li>директориите system1 и system2 са някъде из пътя за търсене на python</li><li>във всяка от тях има файл с име <code>__init__.py</code></li></ul> <p>При import на по-сложно име се извършва следното:</p> <ul><li>намира се поредната компонента от пътя (разделени с точки)</li><li>ако има съответстващ файл — включва се</li><li>ако е директория — изпълнява се <code>__init__.py</code> в нея</li></ul> </div> <div class="slide"> <h1>Пакети от модули (3)</h1> <p>С пакети от модули можем с едни замах да import-нем много модули:</p> <p>forest/pooh.py:</p> <code>name = 'Pooh'</code> <p>forest/piglet.py:</p> <code>name = 'Piglet'</code> <p>forest/__init__.py:</p> <pre><code>import pooh<br />import piglet<br /></code></pre> user.py: <pre><code>import forest<br />print forest.pooh.name<br />print forest.piglet.name</code></pre> </div> <div class="slide long"> <h1>import</h1> <ul><li><code>import mod</code> — намира се модула и обектът му се присвоява на името <code>mod</code></li><li class="code"><pre><code>sys = '/usr/src/sys'<br />import os<br />def listByExt(path, ext):<br /> return [d for d in os.listdir(path) if d.endswith('.'+ext)]<br /><br /># искаме да отпечатаме sys.path<br />import sys<br />print sys.path<br /><br /># сега да видим всички питонски файлове в /usr/src/sys<br />print listByExt(sys, 'py')<br /># опс:<br /><span style="color: red;">TypeError: coercing to Unicode: need string or buffer, module found</span><br /></code></pre></li></ul> </div> <div class="slide"> <h1>import as</h1> <pre><code>import sys as sysmod</code></pre> print sysmod.path Почти същото е като: <pre><code>import sys<br />sysmod = sys<br />del sys<br />sysmod.path</code></pre> само че ще загубим старата стойност на <code>sys</code> </div> <div class="slide"> <h1>from mod import names</h1> <p>Понякога е досадно да извикваме всеки път цялото име на накой обект, като <code>universe.milkyway.earth.europe.bg.beautify()</code></p> <pre><code><br /><br />from universe.milkyway.earth.europe.bg import beautify<br />beautify()</code></pre> <p>Или даже:</p> <pre><code><br />from universe.milkyway.earth.europe.bg import beautify as b<br />b()</code></pre> </div> <div class="slide"> <h1>from mod import *</h1> <p>Хубаво ли ви е така:</p> <code>from mod import a,b,c,d,e,f,g,h,i,j,k,l</code> <p>И на мен. Затова Python ни позволява да внесем в нашия модул всички имена от някой друг: <code>from mod import *</code></p> <ul><li>Имената от типа <code>_име</code> не се внасят</li><li>Имената от типа <code>__име__</code> не се внасят</li><li>Ако в <code>mod</code> има списък с име <code>__all__</code>, то се внасят само имената съдържащи се в него</li></ul> </div> <div class="slide longlong"> <h1>Още разни модулни неща</h1> <ul><li>Съществува модул <code>__builtin__</code>, който съдържа всички вградени функции и други имена: <pre><code>import __builtin__<br />__builtin__.dir = abs<br />print dir(-3)</code></pre> </li><li>модулите се импортират само веднъж: <pre><code>>>> import world<br />>>> world.save('babas')<br />All the babas were saved.<br />>>> world.save = 5<br />>>> import world<br />>>> world.save<br />5</code></pre> За презареждане трябва да се ползва <code>reload()</code>: <pre><code>>>> world.save<br />5<br />>>> reload(world)<br />>>> world.save<br /><function></code></pre></li></ul> </div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4772941093753559531.post-1831210798321730272009-01-17T10:54:00.002-08:002009-01-17T11:06:45.110-08:00Функциите и техните приятели в Python<div class="presentation"> <div class="slide"> <h1><br /></h1> <h3><span style="font-size:78%;">„ Програмиране с Python“, <acronym title="Факултет по Математика и Информатика при Софийски Университет">ФМИ</acronym></span></h3> <h3><span style="font-size:78%;">Стефан Кънев & Николай Бачийски</span></h3> <h4><span style="font-size:78%;">07.03.2007г.</span></h4> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">Функции</span></h1> <ul><li><span style="font-size:100%;">Дефинират се с ключовата дума <code>def</code></span></li><li><span style="font-size:100%;">Връщат стойност с <code>return</code></span></li><li><span style="font-size:100%;">Например: </span><pre><span style="font-size:100%;"><code>def factorial(n):<br />if n == 0:<br />return 1<br />else:<br />return n * factorial(n-1)<br /><br />>>> factorial(4)<br />24<br /></code></span></pre></li></ul> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">Функции (2)</span></h1> <p><span style="font-size:100%;">Ако искате една функция да взема повече от един аргумент, просто ги разделяте със запетаи:</span></p> <pre><span style="font-size:100%;"><code>def orderPizza(type, ketchup, mayo):<br />order = "I want a " + type + " pizza."<br />if ketchup: order += " Please add ketchup."<br />if mayo: order += " And please add mayo."<br /><br />reply = callAndTell("555-PIZZA", order)<br />return reply<br /><br />>>> orderPizza("Margaritta", False, True)<br /></code></span></pre> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">Аргументи по подразбиране</span></h1> <p><span style="font-size:100%;">Може да слагате стойности по подразбиране на функциите</span></p> <pre><span style="font-size:100%;"><code>def orderPizza(type, ketchup = True, mayo = True):<br />order = "I want a " + type + " pizza."<br />if ketchup: order += " Please add ketchup."<br />if mayo: order += " And please add mayo."<br /><br />reply = callAndTell("555-PIZZA", order)<br />return reply<br /><br />>>> orderPizza("Margaritta")<br /></code></span></pre> </div> <div class="slide long" style="font-family:arial;"> <h1><span style="font-size:100%;">Аргументи по подразбиране (2)</span></h1> <p><span style="font-size:100%;">Имайте предвид, че стойностите по подразбиране се инициализират само веднъж</span></p> <pre><span style="font-size:100%;"><code>def addBeer(beers = []):<br />beers.append("Beer")<br />print beers<br /><br />>>> addBeer()<br />['Beer']<br /><br />>>> addBeer()<br />['Beer', 'Beer']<br /></code></span></pre> <p><span style="font-size:100%;">В този случай е по-добре да сложите <code>beers</code> със стойност по подразбиране <code>None</code> и създавате нов списък в тялото на функцията, ако потребителя не подаде нещо друго.</span></p> </div> <div class="slide long" style="font-family:arial;"> <h1><span style="font-size:100%;">Извикване с наименовани параметри</span></h1> <p><span style="font-size:100%;">При извикване можете да подавате параметрите с имената им. По този начин може да ги дадете в различен ред или да използвате само някои, които имат стойност по подразбиране.</span></p> <pre><span style="font-size:100%;"><code>def orderPizza(type, ketchup = True, mayo = True):<br />order = "I want a " + type + " pizza."<br />if ketchup: order += " Please add ketchup."<br />if mayo: order += " And please add mayo."<br /><br />reply = callAndTell("555-PIZZA", order)<br />return reply<br /><br />>>> orderPizza(ketchup = False, mayo = False, type = "Margaritta")<br />>>> orderPizza(type = "Margaritta", ketchup = False)<br />>>> orderPizza("Margaritta", ketchup = False)<br /></code></span></pre> </div> <div class="slide long" style="font-family:arial;"> <h1><span style="font-size:100%;">Имена на функции</span></h1> <p><span style="font-size:100%;">Python не прави разлика между имена на функции и обекти. Може да ги третирате по еднакъв начин</span></p> <pre><span style="font-size:100%;"><code>def scare(): print "Ni!"<br /><br />>>> sayIt = scare<br />>>> sayIt()<br />Ni!<br />>>> scare()<br />Ni!<br />>>> del scare<br />>>> sayIt()<br />Ni!<br />>>> scare()<br />Traceback (most recent call last):<br />File "<stdin>", line 1, in <module><br />NameError: name 'scare' is not defined<br /></module></stdin></code></span></pre> </div> <div class="slide long" style="font-family:arial;"> <h1><span style="font-size:100%;">Имена на функции (2)</span></h1> <p><span style="font-size:100%;">Съответно може да предавате функции като аргументи...</span></p> <pre><span style="font-size:100%;"><code>def calculate(operation, n1, n2): return operation(n1, n2)<br />def addition(n1, n2): return n1 + n2<br />def multiplication(n1, n2): return n1 * n2<br /><br />>>> calculate(addition, 6, 7)<br />13<br />>>> calculate(multiplication, 6, 7)<br />42<br /></code></span></pre><span style="font-size:100%;"> ...или като връщани стойности: </span><pre><span style="font-size:100%;"><code>def makeStamp(owner):<br />def stamp(something):<br /> return something + " is owned by " + owner<br />return stamp<br /><br />>>> stamper = makeStamp("The Goverment")<br />>>> print stamper("This thing there")<br />'This thing there is owned by The Goverment'<br /></code></span></pre> </div> <div class="slide long" style="font-family:arial;"> <h1><span style="font-size:100%;">Имена на функции (3)</span></h1> <p><span style="font-size:100%;"><code>def</code> твърденията се пресмятат по време на изпълнение</span></p> <pre><span style="font-size:100%;"><code><br />def operation(name, n1, n2):<br />if name == "addition":<br /> def oper(x, y):<br />return x + y<br />else:<br /> def oper(x, y):<br />return x * y<br />return oper(n1, n2)<br /><br />>>> operation('addition', 6, 7)<br />13<br />>>> operation('multiplication', 6, 7)<br />42<br /></code></span></pre> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">Динамични аргументи</span></h1> <p><span style="font-size:100%;">Като поставите <code>*</code> прeд списък...</span></p> <pre><span style="font-size:100%;"><code><br />>>> preference = ('Margaritta', True, True)<br />>>> orderPizza(*preference)</code></span></pre> <p><span style="font-size:100%;">...или <code>**</code> пред речник:</span></p> <pre><span style="font-size:100%;"><code><br />>>> preference = {'type': 'Margaritta', 'mayo': True}<br />>>> orderPizza(**preference)</code></span></pre> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">Функции с променлив брой аргументи</span></h1> <pre><span style="font-size:100%;"><code>def sum(prefix, *things):<br />result = 0<br />for n in things:<br /> result += n<br />print prefix + str(result)<br /><br />>>> sum("The answer:", 1, 2, 3, 5, 7, 11, 13)<br />The answer: 42</code></span></pre> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">Функции с променлив брой аргументи (2)</span></h1> <pre><span style="font-size:100%;"><code>def studentInfo(name, **things):<br />print "Hello, my name is " + name<br />print "I come from " + things['country']<br />print "I like " + thing['cheese']<br /><br />>>> studentInfo('The Black Knight',<br /> country = 'Assyria', cheese = 'Limburger')<br />Hello, my name is The Black Knight<br />I come from Assyria<br />I like Limburger</code></span></pre> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">Функции с променлив брой аргументи (3)</span></h1> <ul><li><span style="font-size:100%;">Когато имате и трита вида параметри: </span><pre><span style="font-size:100%;"><code>def func(param, param2, *args, **kwargs)</code></span></pre> </li><li><span style="font-size:100%;">Първо трябва да предавате позиционните аргументи</span></li><li><span style="font-size:100%;">След тях трябва да предадете именованите аргументи</span></li><li><span style="font-size:100%;">Ако предадете позиционен след именован, ще получите грешка</span></li></ul> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">Област на видимост</span></h1> <p><span style="font-size:100%;">В Python има четири области на видимост</span></p> <ul><li><span style="font-size:100%;">Локален</span></li><li><span style="font-size:100%;">Обграждаща функция</span></li><li><span style="font-size:100%;">Глобален</span></li><li><span style="font-size:100%;">Вграден</span></li></ul> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">Локален</span></h1> <pre><span style="font-size:100%;"><code>x = 11<br /><br />def stuff():<br />x = 14<br />print x<br /><br />stuff()<br />print x<br /></code></span></pre> <p><span style="font-size:100%;">Резултат:</span></p> <pre><span style="font-size:100%;"><code>14<br />11</code></span></pre> </div> <div class="slide long" style="font-family:arial;"> <h1><span style="font-size:100%;">Глобален</span></h1> <ul><li><span style="font-size:100%;">Ако искате да променяте глобални променливи, трябва ви ключовата дума <code>global</code></span></li></ul> <pre><span style="font-size:100%;"><code>x = 11<br /><br />def stuff():<br />global x<br />x = 14<br />print x<br /><br />stuff()<br />print x<br /></code></span></pre> <p><span style="font-size:100%;">Резултат:</span></p> <pre><span style="font-size:100%;"><code>14<br />14</code></span></pre> <p><span style="font-size:100%;">Глобалните променливи са ЗЛО!!! Не искайте да ги ползвате</span></p> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">Обграждаща функция</span></h1> <pre><span style="font-size:100%;"><code><br />def f1():<br />x = 88<br />def f2():<br /> print x<br />return f2<br /><br />action = f1()<br />action() # Отпечатва 88<br /></code></span></pre> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">Анонимни функции</span></h1> <ul><li><span style="font-size:100%;">Дефинират се с <code>lambda</code></span></li><li><span style="font-size:100%;">Могат да съдържат само един израз, който е връщаната им стойност</span></li><li><span style="font-size:100%;">Внасят нотка функционално програмиране в Python</span></li></ul> <pre><span style="font-size:100%;"><code><br />>>> operation = lambda x, y: x * y<br />>>> print operation(6, 7)<br />42<br /></code></span></pre> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">Функции от по-висок ред - map</span></h1> <ul><li><span style="font-size:100%;">Приема: едноаргументна функция и поредица</span></li><li><span style="font-size:100%;">Връща: списък образуван от елементите на дадената поредица, върху които е приложена функцията</span></li></ul> <pre><span style="font-size:100%;"><code><br />>>> map(lambda x: x ** 2, range(1, 10))<br />[1, 4, 9, 16, 25, 36, 49, 64, 81]<br /></code></span></pre> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">Функции от по-висок ред - filter</span></h1> <ul><li><span style="font-size:100%;">Приема: едноаргументна функция и поредица</span></li><li><span style="font-size:100%;">Връща: списък образуван от елементите на дадената поредица, за които функцията връща списък</span></li></ul> <pre><span style="font-size:100%;"><code><br />>>> filter(lambda x: x % 2, range(1, 10))<br />[1, 3, 5, 7, 9]<br /></code></span></pre> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">Функции от по-висок ред - reduce</span></h1> <ul><li><span style="font-size:100%;">Приема: двуаргументна функция и поредица</span></li><li><span style="font-size:100%;">Прилага функцията последователно на елементите в поредицата, като започва от първите два, след което го прилага с третия елемент и т.н. Връща крайния резултат</span></li><li><span style="font-size:100%;">Може да вземе начална стойност</span></li></ul> <pre><span style="font-size:100%;"><code><br />>>> reduce(lambda x, y: x + y, [3, 5, 7, 11, 13])<br />39<br />>>> reduce(lambda x, y: x + y, [3, 5, 7, 11, 13], 3)<br />42<br /></code></span></pre> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">List comprehension</span></h1> <ul><li><span style="font-size:100%;">Python има специален синтаксис за <code>map</code></span></li><li><span style="font-size:100%;"><code>[<em>израз</em> for <em>променлива</em> in <em>поредица</em>]</code></span></li><li><span style="font-size:100%;">Например:</span></li></ul> <pre><span style="font-size:100%;"><code><br />>>> [x * x for x in range(0, 10)]<br />[1, 4, 9, 16, 25, 36, 49, 64, 81]<br /></code></span></pre> </div> <div class="slide" style="font-family:arial;"> <h1><span style="font-size:100%;">List comprehension (2)</span></h1> <ul><li><span style="font-size:100%;">Можете да добавите функционалността и на <code>filter</code></span></li><li><span style="font-size:100%;"><code>[<em>израз</em> for <em>променлива</em> in <em>поредица</em> if <em>условие</em>]</code></span></li><li><span style="font-size:100%;">Например:</span></li></ul> <pre><span style="font-size:100%;"><code><br />>>> [x * x for x in range(0, 10) if x % 2]<br />[1, 9, 25, 49, 81]<br /></code></span></pre> </div> <div class="slide"> <h1 style="font-weight: normal;font-family:arial;" ><span style="font-size:100%;">List comprehension (3)</span></h1> <p style="font-family:arial;"><span style="font-size:100%;">Може да вложите list comprehension в друг такъв:</span></p> <pre><code><span style="font-family:arial;font-size:100%;"><br />>>> nums = range(0, 10)<br />>>> [(x, y) for x in nums for y in nums if x+y == 13]<br />[(4, 9), (5, 8), (6, 7), (7, 6), (8, 5), (9, 4)]</span><br /></code></pre> </div> </div>Unknownnoreply@blogger.com0