6.6.2 Генератор правила плурала

Хајде
да се вратимо на plural5.py и хајде да видимо како ова верзија plural() функције заправо ради.

def
rules(rules\_filename):

with open(rules\_filename, encoding='utf-8') as pattern\_file:

for line in pattern\_file:

pattern, search, replace = line.split(None, 3) ①

yield build\_match\_and\_apply\_functions(pattern, search, replace)②

def plural(noun,
rules\_filename='plural5-rules.txt'):

for matches\_rule, apply\_rule in rules(rules\_filename): ③

if matches\_rule(noun):

return apply\_rule(noun)

raise ValueError('no matching rule for {0}'.format(noun))

1.       Овде нема магије. Запамтите
да линије датотеке са правилима имају три вредности одвојене размаком, зато
користите line.split(None, 3) да добијете три колоне и
да их доделите трима локалним променљивима.

2.       А онда додате. Шта ли то
додајете? Две функције са својим старим пријатељем, build\_match\_and\_apply\_functions(), која је идентична
претходним примерима. Другим речима, rules() је генератор који
избацује, слаже и примењује функције *на команду*

3.       Пошто је функција rules()
генератор, можете је користити директно у for петљи. Позваћете rules() функцију која ће онда
отворити фајл са узорцима, прочитаће прву линију, димаички изградити
одговарајућу функцију и применити ту функцију из узорака са те линије и додаће
динамички направљену функцију. Следећи пут када прођете кроз for петљу наставићете тамо где сте завршили у
rules() (која је била у средини for line in
pattern\_file
петље). Последње што ће да уради је да прочита следећи ред у датотеци (која је
и даље отворена), динамички направи још један спој и примени функцију на основу
узорака у тој линији у датотеци и да дода две функције.

Шта сте стекли током фазе? Време покретанја. У фази 4 када сте
увезели plural4 модул, прочитаће целокупну датотеку са обрасцима и саставиће
листу свих могућих правила, пре него што сте уопште могли да размислите о
позиву функције plural(). Са генераторима можете све лако радити: читате прво
правило и креирате функцијама и испробајте их, а ако то успије, никада не
прочитате остатак датотеке или створите било коју другу функцијu.

Шта сте изгубили? Преформансе! Сваки пут када позовете plural()
функцију, rules() генератор почиње испочетка – што значи да
поново отвара датотеку са узорцима и чита их испочетка линију по линију.

Шта ако бисте могли да имате најбоље од оба света: минималне
трошкове покретања (не извршава ни један код на import) и максималне преформансе
(немојте да правите исте функције изнова и изнова).О, да, и даље желите да
сачувате правила у одвојеној датотеци (зато што је код код, а подаци су
подаци), док год не морате да читате исту линију два пута.

Да бисте урадили то мораћете да напправите свој сопствени итератор, али пре него што урадите то морате да
научите о Python класама.

**6.7 Даље читање**

 ·
СТР. 255: Једноствани генератори

·
Разумевање Python-ове „with“ изјаве

·
Закључци у Python-у

·
Фибоначијеви бројеви

·
Енглеске неправилне именице у плуралу

== **ПОГЛАВЉЕ**
7. Класе и итератори **==**

*❝ East is East, and West is West, and never the twain shall meet. ❞*

*—*
Rudyard Kipling

**7.1**
Заронимо

 Итератори
су „тајни састојак“ Python-а 3. Они су свуда, у
основи свега, увек, само ван

видокруга.
Разумевања су само једноставан облик итератора. генератори су само једноставан
облик итератора. Функција која призива вредности је фини, компактни начин
прављења итератора без брављења итератора. Показаћемо Вам шта мислимо тиме.

Сећате
се Фибоначијевог генератора? Ево га итератор направљен од нуле:

class
Fib:

'''iterator that yields numbers in the Fibonacci sequence'''

def \_\_init\_\_(self, max):

self.max = max

def
\_\_iter\_\_(self):

self.a = 0

self.b = 1

return self

def
\_\_next\_\_(self):

fib = self.a

if fib > self.max:

raise StopIteration

self.a,
self.b = self.b, self.a + self.b

return fib

Хајде
да гледамо то линију по линију.

class Fib:

Class (класа)? Шта је класа?