25 август 2008

Първи стъпки в програмирането с Python. част 6. Драконът и Императора

Index:
1.Интродукция
2.В началото бе словото
3.Ю толкинг ту ми?
4.Ужаст и страхопаника
5.Императорът и дракона


6. Драконът и Императора

Императоре, време е да ви запозная с дракона. Днес ще говорим за функциите. Функционалното програмиране е един от най мощните похвати в програмирането, и ако се използва правилно може да доведе до много добри резултати. Властта ти над функциите не може да идва от прости заповеди както до сега. За да имаш власт над функциите трябва да ги разбираш дълбоко. Трябва да знаеш името на духът, за да имаш власт над него. Днес ще се опитам да ви обясня какъв е духът на функциите и как да го овладеете, не може със сила или с воля, трябва с разбиране и акъл!


В математиката функциите представляват зависимости между променливи. Да речем функцията f, е такава че за всяко x има число y което е равно на x+1. Или нещо такова, математиката не е толкова интересна нали :D При програмирането е донякъде същото. Имаме конструкции наречени функции, те приемат за вход някакви стойности и връщат някакъв резултат със тези стойности. Ето как изглежда една python функция:

def име на функция(параметри):
действия с параметрите


функции конструираме с def, това е съкратено от дефинирай, т.е. дефинирай функция с това име, с тези параметри, да извършва тези действия и да върне този резултат. Параметрите се слагат в скоби и са разделени от запетаи, отново имаме на края на главния ред двоеточие и отново следващите редове са отместени с 4 интервала(или 2 ако бачкате за гугъл, но НЕ и табове, много хора ще ви намразят ако ползвате табове). Ето една истинска функция:


def square(x):
return x*x


тази конструкция дефинира функцията square() която приема едно число x и връща като отговор x на квадрат. Ето как се ползва това в интерпретатора на python:


>>>def square(x):
... return x*x
...
>>>square(4)
16
>>>square(5)
25


Готино, а? Ето как викаме функциите, като слагаме параметрите им в скоби за да ги извикаме, трябва само да кажем името им и какво искаме от тях, малкото духче веднага ще дойде да ни свърши работата. Балък. Думата return се използва често във функциите, когато искате да ви върнат стойност, тук искаме функцията да върне стойност x*x, ако го нямаше и просто бяхме написали x*x вместо return x*x, функцията нямаше да върне нищо. Резултатът може да се съхранява в променливи:


>>>x=square(4)
>>>x
16
>>>x=square(x)
>>>x
256


Тук виждате как на х присвоихме резултатът върнат от square, х не е равно на square, a на резултатът му. Ето как може да направите x да е равно на square


>>> x=square
>>> x(4)
16


Когато присвоим на x името square, ние не го присвояваме, а само го караме да сочи съм същия обект(функцията) Променливите в python само сочат към обекти, а не ги съхраняват в себе си, за разлика от C++ да речем, където променливите съхраняват обекти. а square е просто променлива сочеща функция. Важно е да отбележим и че х-ът вътре в square е различен от x-а извън него. Ето какво имам предвид:


>>>def square(x):
... return x*x
...
>>>x=square(4)
>>>x=square(x)

Първия х във дефиницията на функцията е локален, той е само за самата функция, втория х на който присвояваме square(4) и по късно даваме като аргумент на square е глобален х. Представете си че всичко в def е отделна програма с отделни имена и променливи и отделен код, тя е напълно изолирана от външния свят, освен със входа си в скобите и изхода си от return, това се нарича пространство от имена(namespace). Българския термин е среда, глобалната среда е мястото където живее втория х, а локалната за square среда съдържа първия х.


>>>def square(y):
... return y*y
...
>>>x=square(4)
>>>x=square(x)


това е същото като горното, можем също така да напишем:


>>>def square(x):
... return x*x
...
>>>y=square(4)
>>>y=square(y)


същото като горните 2, ето още един пример:


>>>def square(y):
... return y*y
...
>>>y=square(4)
>>>y=square(y)


няма значение, двете променливи са различни неща. Това е важно да се знае. Да разгледаме следния пример:

>>> y=1
>>> def pp(x):
... return x+y
...
>>> pp(2)
3
>>>


Тук имаме глобалното име y което е равно на 1, също така имаме и функцията pp, която приема едно число и добавя y към него. Тази функция не е особено добре написана. Всеки може да промени y и цялата функция ще започне да прави глупости. По добър вариант ще е да се напише така:


>>> y=1
>>> def pp(x,z):
... return x+z
...
>>> pp(2,y)
3
>>>


Така функцията pp има два параметъра, и ги събира, когато я викаме първия е 2 а втория е y. Сега е по добре написано именно защото ако някой промери y, функцията пак ще си има предвидим изход, просто променяш параметъра и. Сега може да използваш pp и с други числа, да речем pp(2,5) ще върне 7, преди това беше невъзможно.

Във функциите може да слагаме всички други конструкции които сме разглеждали, включително и други функции. Ето една която принтира всички елементи на редица(списък, низ, наредена n-торка)


>>> def printlist(list):
... for x in list:
... print x
...
>>> printlist('hello')
h
e
l
l
o
>>> printlist([1,2,3,4,5])
1
2
3
4
5



Може да ползвате while,if и общо взето всичко друго във функциите, и како казах и други функции. Ето един интересен пример:


>>> def makeadder(num):
... def adder(x):
... return x+num
... return adder
...
>>> addr2=makeadder(2)
>>> addr2(4)
6


Функцията makeadder приема число за аргумент и връща друга функция която приема друго число за аргумент и прибавя старото към него, искаме да създадем функцията adder2 която да добавя 2 към някакво число? Можем да използваме def, но защо като вече имаме makeadder и той е създаден специално да прави подобни функции. Това се нарича процедура от висок ред, т.е. функция която приема друга функция като аргумент, или връща такава като резултат, видяхме втория тип, да видим още подобни:

>>> list=[1,2,3,4,5]
>>> map(square,list)
[1, 4, 9, 16, 25]
>>>


Функцията map() е вградена в Python, тя приема някаква функция и някаква последователност като аргументи и прилага тази функция към всеки елемент от последователността, и връща нова последователност със новите елементи, в случая приложи square към list и върна нов списък.

Остава да видим още една малка подробност за функциите. Анонимните функции. Това са функции без имена(очевидно). Те се създават с конструктора lambda, защо ламбда? Защото на клавиатурите ни няма гръцки букви, ето защо! Ако имаше щяхме да използваме оная буква дето мяза на Л от гръцката азбука вместо цялата дума lambda. Ето как се ползва ламбда:

square=lambda x: x*x


Тук на променливата square просто задаваме стойност функция, която приема един аргумент, и връща квадратът му. Синтаксисът е малко по различен. Lambda-та е спорен въпрос в python, и не е толкова мощна колкото def-функциите, защото не може да има повече от един ред, и не може да има синтактични конструкции като for, while, print, или if. Това я прави малко кастрирана, но в някой случаи е досат полезно нещо. Вече сме запознати с по голямата част от езика, остава да поразгледаме класовете(нещо което няма да задълбочавам) и след това ще почна със обикновени трикчета които съм посъбрал за езика, с които могат да се правят готини работи, ще ви давам примери и програми от които да се учите на основите, но общо взето по голямата част от синтаксиса го знаете вече. Сега остава да си купите някоя дебела книжка(или да си изтеглите, като мен) и да си я прочетете, все пак това е блог, не шибана енциклопедия, не може да научите език от блог.

Няма коментари: