Poglavlja-1i1

Аутор: Павле Продановић

## **Поглавље -1. Шта је ново у „Уроните у Пајтон 3?“**

❝ Isn’t this where we came in? ❞
— Pink Floyd, The Wall

### **-1.1. тј. „негативни ниво“**

Да ли сте већ Пајтон програмер? Да ли сте прочитали ориганлну верзију „Уроните у Пајтон“? Да ли сте купили књигу(ако јесте, хвала!)? Да ли сте већ спремни да уроните у Пајтон 3? Ако је нешто од овога
тачно, онда наставите да читате ово поглавље(ако није, најбоље је да одмах почнете са поглављем 0).

Пајтон 3 долази са скриптом која се зове 2to3. Научите је. Волите је. Користите је. Преношење кода уз 2to3 (из Пајтона 2 у Пајтон 3) је само једна од ствари које 2to3 алатка може аутоматски да одради. Будући да су већина промена синтаксне, добра полазна тачка је да то прво научите (print је сада функција, `x` не функционише, &c,...)

Ствар за проучавање: поглавље где се говори о пребацивању скрипте chardet на Пајтон 3 представља мој (крајње успешан) подухват да пренесем не баш тривијалну библиотеку са Пајтона 2 на Пајтон 3. Можда ће вам помоћи, можда неће. Крива схватања је прилично стрма, пошто прво треба да схватите како сам модул функционише, да бисте схватили шта се покварило и како сам то поправио. Много проблема из пребацивања на Пајтон 3 се вртело око стрингова(срп. ниски). Кад смо већ код стрингова...

Стрингови... Где почети. Пајтон 2 је имао „стрингове“ и „Уникод стрингове“. Пајтон 3 има „бајтове“ и „стрингове“. Односно, сви стрингови су сад Уникод стрингови, а ако хоћете да се бавите низом бајтова, користите тип податка bytes. Пајтон 3 никад неће подразумевано да врши претварања између бајтова и стрингова, тако да ако нисте сигурни шта користите у датом тренутку, вероватно ћете „брејковати“ ваш код(енг. breaking code). Прочитајте поглавље о стринговима за више детаља.

Разлика између стрингова и бајтова помиње се више пута у овој књизи.

У поглављу о фајловима, научићете разлику између читања фајлова у „бинарном“ и „текстуалном“ моду. Читање(и писање!) фајлова у текстуалном моду захтева тзв „encoding” параметар (параметар за кодирање). Неке текст фајл методе броје карактере, али већина осталих броји бајтове. Ако ваш код претпостави да је један карактер == једном бајту, ваш код ће брејковати код вишебајтних карактера.

У поглављу о HTTP веб услугама, httplib2 модул узима заглавља и податке преко HTTP-a. HTTP заглавље се враћа као стринг, али тело HTTP-a се враћа као бајт.

У поглављу о серијализицији Пајтон објеката, научићете зашто „pickle“ модул у Пајтону 3 дефинише нови формат података, који није назадно компатибилиан са Пајтоном 2(помоћ: то је опет због бајтова и стрингова). Такође, Пајтон 3 подржава серијализацију објеката из JSON-a који чак ни нема тип података „бајт“. Показаћу вам како то да заобиђете.

У поглављу које сам вам дао за проучавање: моје пребацивање скрипте chardet било је пуно збрке са бајтовима и стринговима.

Чак иако вас не занима Уникод(али мораће), желећете сигурно да прочитате о форматирању стрингова у Пајтону 3, које се у потпуности разликује од истог у Пајтону 2.

Итератори су свуда у Пајтону 3 и разумем их пуно боље него пре пет година кад сам написао „Уроните у Пајтон“. Ви их такође морате разумети, зато што много фукнције које се користе да враћају „листе“ у Пајтону 2 сада враћају итераторе у Пајтону 3. У најмању руку, требало би да прочитате другу половину поглавља о итераторима и другу половину поглавља о напредним итераторима.

Звог велике количине захтева, написао сам додатно поглавље које се бави „Именима специјалних метода“, који је сличан као „Модел података“ из Пајтон документације, али више snarky(више критички одрађен).

Када сам писао „Уроните у пајтон“, све доступне XML билбиотеке су биле ужасне. Онда је Фредик Лундх написао „ElementTree“, који је заправо био сјајан. Богови пајтона су мудро убацили ЕlementTree у стандардну библиотеку, и сада је то основа за моје ново XML поглавље. Старни начини „парсовања“(срп. Расчлањивања) XML-a још увек постоји, али треба их избегавати, јер су стварно ужасни!

Такође новост у Пајтону(не у језику већ у заједници) јесте појава тзв. „складишта“ кода као што је The Python Package Index (PyPI). Пајтон долази са услужним програмима за паковање кода у стандардне формате и његово дистибуирање на PyPI. Ако желите да знате више, прочитајте о паковању Пајтон библиотека на линку.

### **1.3 Писање Читљивог кода**

Нећу вам досађивати дугачким говором о томе колико је важно документовати ваш код. Само знајте да се код пише једном, али се чита много пута, а најважнија публика за ваш код сте ви сами, шест месеци нако писања самог кода(нпр. Морате нешто да поправите у коду, али сте заборавили како код уопште функционише). Пајтон олакшава писање читљивог кода, зато то искористите, бићете ми захвални за шест месеци.

#### **1.3.1. Документациони стрингови**

Можете документовати Пајтон функцију тако што ћете јој доделити документациони стринг(скраћено docstring). У овом програму, функција approximate\_size() има свој docstring:

....
КОД на страни 39
...

Троструки наводници означавају стринг на више линија. Све између
почетног и крајњег наводника се третира као део једног стринга, укључујући фукцију return изјаву, водеће размаке(када би били одмах после наводника), и све остале карактере. Троструке наводнике можете користити било где, али ћете их најчешће користити када дефинишете docstring.
Троструки наводници су такође лак начин да дефинишемо стрингове са једноструким и двоструким наводницима који функционише слично као оператор qq/…/ у језику Perl 5

Све између троструких наводника је, као што смо рекли, docstring функције, који документује шта функција ради. Docstring, ако постоји, мора да буде прва ствар која ће бити дефинисана у функцији(то јест, у следећој линији након декларације функције).

Технички, ви не морате користити docstring у својој функцији, али бисте увек требали. То сте сигурно чули на сваком часу програмирања, ако сте програмирање икада похађали, али Пајтон вам даје додатни подстицај: docstring је доступан као атрибут функције, што углавном није пракса у осталим језицима.

Многи Пајтон IDE-ови користе docstring да би пружили контекст документацији, па када укуцате име функције, њен docstring се приказује као опис дате функције. Ово је наравно изузетно корисно, али само ако је написани docstring користан.

### **1.4 Претраживање модула када користите import**

Пре него што наставимо даље, требало би споменути путање претраживања модула(мисли се на модуле које увозите командом import). Када упишете команду за убацивање модула, Пајтон је претражује на више места. Односно, претражује га на свим местима дефинисаним у фајлу sys.path. Фајл је само листа, и лако је можете видети и модификовати преко стандардних метода листа(научићете више о листама у поглављу о изворним типовима података).

....
КОД на страни 41
...
Увожењем sys модула доступне су нам све његове функције и атрибути.
Sys.path је листа директоријума(ваша листа ће изгледати другачије, у зависности од оперативног система, верзије Пајтона коју покрећете и где вам је сам Пајтон инсталиран). Пајтон ће проћи кроз све директоријуме(овим редоследом) и тражити .py фајл којем је име подударно са оним што покушавате да увезете.
Заправо, лагао сам. Истина је мало компликованија, јер нису сви модули сачувани као .py фајлови. Неки модили су уграђени у сам Пајтон и они се понашају слично као обични модули, осим што њихов изворни код у Пајтону није доступан, зато што уопште нису написани у Пајтону(као и сам Пајтон, уграђени модули су написани у C-у)!
Можете додати нови директоријум у Пајтонову путању претраживања тако што ћете га додати у sys.path. Пајтон ће онда такође проверити и тај директоријум, сваки пут када увозите модул. Оваквим додавањем ово ће важити за све време рада Пајтон програма.
Користећи sys.path.insert(0, new\_path), убацили сте нови директоријум као прву ставку у sys.path листи, а самим ти и на почетак путање тражења. То је углавном баш оно што и желите, јер ако дође до појављивања више истих модула, Пајтон ће користити онај који је први у листи(тиме избегавате проблем да уместо вашег модула који је верзије за Пајтон 3, користите онај који сте добили уз Пајтон, а који може да буде погодан само за Пајтон 2).

### **1.5 Све је објекат**

У случају да нисте пропратили, управо сам рекао да Пајтон функције
имају атрибуте, и да су ти атрибути вама доступни током извршвања
програма. Функција, као и све остало у Пајтону, је објекат. Покрените
интерактивни Пајтон shell и напишите следеће:
....
КОД на страни 42
...

Прва линија увози humansize програм(који смо у овом поглављу правили) као модул – код који можете користити интерактивно, или правити већи Пајтон програм. Када једном увезете модул, можете позивати његове „public“(срп. јавне) функције, класе или атрибуте. Модули могу да приступе функционалности других модула, а то и ви такође можете у интерактивном Пајтон shell-у. Ово је изузетно битан концепт, којим ћемо се бавити више пута у овој књизи.
Када желите да користите функције дефинисане у увеженим модулима, морате да наведете име модула. То јест, не можете да напишете approximate\_size, него humansize.approximate\_size. Ако сте користили класе у Јави или сличним језицима, ово ће вам изгледати донекле познато.
Уместо обичног позивања функције, затражили сте атрибут функцијe, \_\_doc\_\_.

Import у Пајтону је сличан као команда require у језику Перл. Када увозите(импортујете) Пајтон модул, приступате његовим функцијама командом модул.име\_функције, а када затражите(require) Перл модуле, ви приступате његовим функцијама преко модул::име\_фунцкије.

#### **1.5.1. Шта је објекат**

 Све у Пајтону је објекат и све може имати атрибуте и методе. Све
 Функције имају већ уграђен атрибут \_\_doc\_\_, који враћа docstring
 Дефинисан у изворном коду функције. Sys модул је објекат који има
 (између осталог) атрибут који се зове path и тако даље.

 Ипак то нам не објашњава основно питање: шта је објекат? Различити
Програмски језици различито дефинишу појам „објекта“. У једнима то значи да сви објекти морају имати атрибуте и методе, у другима, то значи да су сви објекти „подкласљиви“ (енг. subclassable, за више детаља погледајте дефиницију). У Пајтону је дефиниција објеката лабавија. Неки објекти немају ни атрибуте ни методе, али могу да их имају. Нису сви објекти подкласљиви. Али све је објекат у смислу да их можемо доделити променљивој или их можемо проследити као аругмент у функцији.

Можда сте чули за појам „првокласни објекат“. У Пајтону, функције су провкласни објекти. То значи да можете проследити функцију као аругмент у другој функцији. Модули су такође првокласани објекти. Можете проследити цео модул као аругмент у функцији. Првокласни објекти су такође класе и класне инстанце(енг. instances – синоним објектима).

Ово је изузетно важно, па ћу вам поновити пар пута, ако до сад нисте запамтили: све у Пајтону је објекат. Стрингови су објекти. Листе су објекти. Функције су објекти. Класне инстанце(објекти) су објекти. Чак су и модули објекти.

###  **1.6 Увлачење кода**

Пајтон функције немају експлицитни почетак или крај и немају витичасте заграде ( { } ) да означе где функција почиње и где се завршава. Једини раздвајачи су две тачке (:) и увлачење самог кода.

....
КОД на страни 44
...

Блокови кода су дефинисани њиховим увлачењем. Под „блоком кода“ подразумева се на функције, if упите, for петље, while петље и тако даље. Увљачење започиње блок кода, а неувлачење га завршава. Нема никаквих заграда или кључних речи(као што је у Паскалу). Ово значи да је празан простор важан и мора да буде константан. У овом примеру код функције увучен је са четири размака. Не мора бити четири размака, али мора бити константан. Прва линија која није увучена представља крај функције.
У Пајтону упит if(ако) је праћен блоком кода. Ако је израз тачан, тј има вредност true(срп. тачно), увучени блок кода ће бити извршен, у супротном одрадиће се else(срп. друго - сваки други случај) упите (ако постоји). Приметите недостатак заграда око израза.
Ова линија је унутар if блока кода. Израз raise(срп. подигни), ће подићи изузетак(eng. exception) вресте ValueError, али само ако је величина мања од нуле.
Ово није крај функције. Потпуно празне линије се не рачунају. Оне могу да направе код читљивијим, али се не рачунају као раздвајачи блокова. Ова функција се наставља у следећој линији(ако буде увлачења).
For(спр. за) петља исто означава почетак блока кода. Блокови кода могу да садрже више линија, док год су они истом количином увучени. Ова for петља има три линије кода у себи. Нема других специјалних синтаксних ознака за вишелинијске блокове кода. Само увуците код и можете да наставите са куцањем.

Овакав принцип је сличан ономе у језику Фортран, али вама ово може изгледати нелогично док год се не навикнете и кренете да схватате предности оваквог писања кода. Главна предност је што сви Пајтон програми изгледају слично, јер је увлачење захтев језика, а не ствар вашег стила и укуса. Ово доста олакшава читање и схватање Пајтон кода других људи.

Пајтон користи увлачење и двотачку да раздвоји блокове кода. C++ i Јава користе тачку и зарез(;) и витичасте заграде да раздвоје блокове кода.

#### **1.7.1 „Хватање“ import грешака**

Један од Пајтонових уграђених изузетака је ImportError, који се
подиже када неуспешно покушате да увезете модул. Ово може да се
догоди из више разлога, али најједноставнији проблем је када модул
не постоји ни у једном директоријуму из листе за претрагу.
ImportError можете користити да бисте имали опционе функције у
вашем коду. На пример chardet модул пружа аутоматско отркивање
врсте кодирања знакова. Можда желите да ваш програм користи овај
овај модул ако он постоји, али и да можете елегантно да наставите
са извршавањем програма ако га корисник није инсталирао. То
можете да постигнете помоћу try … except (срп. пробај ... осим
ако) блока.

....
КОД на страни 47
...

Касније у коду, можете проверити постојање chardet модула
једноставном if упитом:

....
КОД на страни 47
...

Још једна уобичајна употреба ImportError изузетка је када два модула
имплементирају заједнички API, али је један пожељнији од другог
(можда је бржи, или користи мање меморије). Можете покушати да
увезете један модул, али да се вратите на други ако увоз буде
неуспешан. На пример, XML поглавље говори о два модула који
имплементирају исти API, који се зове ElementTree API. Први модул,
lxml, је модул који морате да сами скинете и иснталирате. Други,
xml.etree.ElementTree, је спорији, али је део стандарне Python 3
библиотеке (библиотека је скуп више модула.).

....
КОД на страни 48
...

На крају овог try…expect блока, имаћете увежен један модул који се
зове etree. С обзиром да оба модула имплементирају заједнички API,
остатак вашег кода неће морати да проверава који је модул увезао. И
због тога што је увежен модел увек са називом etree, остатак вашег
кода не мора да буде натрпан са if упитима које позивају модуле са
различитим именима.

### **1.8 Неповезане варијабле**

Погледајте још једном ову линију кода из approximate\_size() функције:

....
КОД на страни 48
...

Никад нисте декларисали варијаблу multiple, него сте јој само доделили
вредност. То је океј, зато што вам Пајтон то дозвољава. Оно што вам
Пајтон неће дозволити јесте референца на променљиву којој вредност
никада није додељена. Покушавајући то да урадите, подићи ћете
NameError изузетак.

....
КОД на страни 48
...

Захвалићете се Пајтоно на овоме једног дана.

### **1.9 Разлика између великих и малих слова је свуда битна**

Сва имена у Пајтону су тзв. case-sensitive(срп. разликују велика и мала
слова): имена променљивих, функција, класа, модула, изузетака итд.
Све што можете да get-ујете(узмете му вредност), set-ујете(мењате му
вредност), позовете га, увезете или подигнете је case-sensitive.
....
КОД на страни 49
...
    И тако даље.
 1.10 Покретање скрипти

 Пајтон модули су објекти и имају неколико корисних атрибута. Ово
 можете користити за једноставно тестирање модула дох их пишете,
 укључивањем посебног блока кода који се извшава када покренете
 Пајтон фајл. Погледете последњих пар линија humansize.py:

....
КОД на страни 50
...

 Као и C, Пајтон користи == за поређење и = за доделу вредности. За
 разлику од C-а, Пајтон не подржава доделу вредности у услову if-а,
 тако да нема шансе да случајно доделите вредност када мислите да
 поредите две вредности.

 Зашто је овај if упит специјалан? Па, модули су објекти и сви модули
 имају уграђен атрибут \_\_name\_\_(срп. име). Вредност \_\_name\_\_-а
 зависи од тога како користите модул. Ако сте га увезли, онда ће
 \_\_name\_\_ да има вредност имена фајла самог модула, наравно без
 путање или екстензије.

....
КОД на страни 50
...

Али такође можете да покренете модул директно као самостални
програм и у том случају \_\_name\_\_ ће имати специјалну вредност,
\_\_main\_\_(срп. главни). Ако је то случај, овај if упит ће имати вредност
true, и покренуће блок кода који припада if-у. У овом случају то је да испише две вредности

....
КОД на страни 51
...

И то је био ваш први Пајтон програм!

#### **1.11 Даље читање**

PEP 257: Docstring Conventions објашњава шта разликује добар docstring од лошег
Python Tutorial: Documentation такође говори о теми са прошлог линка.
PEP 8: Style Guide for Python Code дискутује о добром стилу увлачења
Python Reference Manual Објашњава шта значи рећи да је све у Пајтону објекат зато што неке особе и педантни људи воле да
дуго причају о таквим стварима.