python核心編程--第十一章

1.1.2 返回值與函數類型

過程可理解爲函數,返回none

下面代碼可簡單理解函數返回值的概念:

>>> def hello():
            print "hello world!"
 
           
>>> res =hello()
hello world!
>>> print res
None
>>>type(res)
<type'NoneType'>
>>> res =hello
>>> res()
hello world!

另外,與其他大多數的語言一樣,python 裏的函數可以返回一個值或者對象。只是在返回一個容器對象的時候有點不同,看起來像是能返回多個對象。好比說,你不能拿着大量零散的商品離開百貨店,但是你可以將它們放在一個購物袋裏,然後帶着這個袋子從商店走出去,合理合法。

>>> def foo():
    return["xyz",1000000,-98.6]
 
>>> def bar():
    return"abc",[42,"python"], "guido"

foo()函數返回一個列表,bar()函數返回一個元組。由於元組語法上不需要一定帶上圓括號,所以讓人真的以爲可以返回多個對象。如果我們要恰當地給這個元組加上括號, bar()的定義看起來會是這樣:

>>> def bar():
    return("abc",[42,"python"], "guido")

當然,加上括號總是好的。我們可以這樣接收返回值:

>>> aTuple = bar()
>>> x, y, z = bar()
>>> (a, b, c) = bar()
>>> aTuple
('abc', [42, 'python'], 'guido')
>>> x
'abc'
>>> x, y, z
('abc', [42, 'python'], 'guido')
>>> (a, b, c)
('abc', [42, 'python'], 'guido')

11.2 調用函數

11.2.2 關鍵字參數

關鍵字參數的概念僅僅針對函數的調用。這種理念是讓調用者通過函數調用中的參數名字來區分參數。這樣規範允許參數缺失或者不按順序,因爲解釋器能通過給出的關鍵字來匹配參數的值。

例子如下:

>>> def foo(name = "", age = 0):
    print "name:%s andage:%d" % (name, age)
 
   
>>> foo(name="fzyz.abc",age=23)
name:fzyz.abc and age:23
>>> foo(age=23, name="fzyz.abc")
name:fzyz.abc and age:23
>>> foo(age=23)
name: and age:23

11.2.4 參數組

當然,你可以向函數中傳遞沒有顯式定義的參數,用元祖或字典即可。標準格式如下:

func(positional_args,keyword_args,*tuple_grp_nonkw_args, **dict_grp_kw_args)

我們來簡單看個例子:

from operator import add, sub
from random import randint, choice
ops = {"+":add, "-":sub}
MAXTRIES = 2
def doprob():
    op = choice("+-")
    nums = [randint(1,10) for i inrange(2)]
    nums.sort(reverse = True)
    ans = ops[op](*nums)
    pr = "%d %s %d =" %(nums[0], op, nums[1])
    oops = 0
    while True:
        try:
            if int(raw_input(pr)) ==ans:
                print"correct"
                break
            if oops == MAXTRIES:
                print"answer\n%s%d" % (pr, ans)
            else:
                print"incorrect... try again"
                oops += 1
        except (KeyboardInterrupt,EOFError, ValueError):
            print "invalid input...try again"
def main():
    while True:
        doprob()
        try:
            opt =raw_input("again?[y]").lower()
            if opt and  opt[0] == "n":
                break
        except (KeyboardInterrupt,EOFError):
            break
if __name__ == "__main__":
    main()


程序輸入輸出:

>>>
7 - 1 =6
correct
again?[y]y
9 - 5 =4
correct
again?[y]n
這個程序挺好玩的。

 

11.3 創建函數

函數是用def 語句來創建的,語法如下:

def function_name(arguments):

"function_documentation_string"

function_body_suite

標題行由def 關鍵字,函數的名字,以及參數的集合(如果有的話)組成。def 子句的剩餘部分包括了一個雖然可選但是強烈推薦的文檔字串,和必需的函數體。

Python中並沒有函數聲明和定義的區分,因爲通常將它們視爲一體。

 

11.3.5 內部/內嵌函數

在函數體內創建另外一個函數(對象)是完全合法的。這種函數叫做內部/內嵌函數。

>>> def foo():
    def bar():
         print "bar()called"
    print "foo() called"
    bar()
 
   
>>> foo()
foo() called
bar() called

當然,如果你想單獨訪問bar函數怎麼辦?對於函數來說,貌似訪問不了,你可以聲明一個類,然後把函數往類中堆疊即可。用類來訪問:
>>> class foo(object):
    def bar(self):
         print "bar()called"
 
        
>>> foo().bar()
bar() called

11.3.6 *函數(與方法)裝飾器

裝飾器背後的主要動機源自python 面向對象編程。裝飾器是在函數調用之上的修飾。這些修飾僅是當聲明一個函數或者方法的時候,纔會應用的額外調用。

裝飾器的語法以@開頭,接着是裝飾器函數的名字和可選的參數。緊跟着裝飾器聲明的是被修飾的函數,和裝飾函數的可選參數。裝飾器看起來會是這樣:

@decorator(dec_opt_args)

def func2Bdecorated(func_opt_args):

:

 

爲什麼會產生裝飾器呢?我們來看看靜態方法的實現:

class MyClass(object):

def staticFoo():

:

staticFoo = staticmethod(staticFoo)

在這個類的聲明中,我們定義了叫staticFoo()的方法。現在因爲打算讓它成爲靜態方法,我們省去它的self 參數,self 參數在標準的類方法中是必需的。接着用staticmethod()內建函數來將這個函數“轉化“爲靜態方法,但是在defstaticFoo()後跟着staticFoo = staticmethod (sta- ticFoo)顯得有多麼的臃腫。使用裝飾器,你現在可以用如下代碼替換掉上面的:

class MyClass(object):

@staticmethod

def staticFoo():

此外,裝飾器可以如函數調用一樣“堆疊“起來,這裏有一個更加普遍的例子,使用了多個裝飾器:

@deco2

@deco1

def func(arg1, arg2, ...): pass

這和創建一個組合函數是等價的。

def func(arg1, arg2, ...): pass

func = deco2(deco1(func))

我們來舉個簡單的裝飾器例子:

class MyClass(object):
    @staticmethod
    def the_static_method(x):
        print x
 
MyClass.the_static_method(2)
我原本想寫個複雜的裝飾器程序的,結果寫了半天沒寫出來,我去,我想把裝飾器弄到類裏面來個函數嵌套函數的調用,

有參數和無參數的裝飾器

沒有參數的情況:

@deco

def foo(): pass

....非常的直接

foo = deco(foo)

跟着是無參函數(如上面所見)組成。然而,帶參數的裝飾器decomaker()

@decomaker(deco_args)

def foo(): pass

. . .

需要自己返回以函數作爲參數的裝飾器。換句話說,decomaker()用deco_args 做了些事並返回

函數對象,而該函數對象正是以foo 作爲其參數的裝飾器。簡單的說來:

foo = decomaker(deco_args)(foo)

 

自己寫不出例子,那麼我們來看看書本上的例子吧(真的很想通過裝飾器來完成函數調用函數的舉例,不過總是出錯,我去。。。)

這個裝飾器(以及閉包)示範表明裝飾器僅僅是用來“裝飾“(或者修飾)函數的包裝,返回一個修改後的函數對象,將其重新賦值原來的標識符,並永久失去對原始函數對象的訪問。

from time import ctime, sleep
def tsfunc(func):
    def wrappedFunc():
        print "[%s] %s()called" % (ctime(), func.__name__)
        return func
    return wrappedFunc
@tsfunc
def foo():
    pass
foo()
for i in range(2):
    sleep(1)
foo()

程序輸出:
>>>
[Fri Jun 14 20:16:00 2013] foo() called
[Fri Jun 14 20:16:01 2013] foo() called
[Fri Jun 14 20:16:02 2013] foo() called

這段程序很簡單,當時我一直在想,如何複雜了foo,並且在裝飾器函數中對foo進行復雜的操作。

 

11.4 傳遞函數

一個將函數作爲參數傳遞,並在函數體內調用這些函數,更加實際的例子。這個腳本用傳入的轉換函數簡單將一個序列的數轉化爲相同的類型。特別地,test()函數傳入一個內建函數int(),long(), 或者float()來執行轉換。

def convert(func, seq):
    return [func(eachNum) foreachNum in seq]
myseq = (123, 45.67, -6.2e8, 9999999999L)
print convert(int, myseq)
print convert(long, myseq)
print convert(float, myseq)

程序輸出:
>>>
[123, 45, -620000000, 9999999999L]
[123L, 45L, -620000000L, 9999999999L]
[123.0, 45.67, -620000000.0, 9999999999.0]

我們來弄個默認參數的例子:
from urllib import urlretrieve
def firstNonBlank(lines):
    for eachLine in lines:
        if not eachLine.strip():
            continue
        else:
            return eachLine
def firstLast(webpage):
    f = open(webpage)
    lines = f.readlines()
    f.close()
    print firstNonBlank(lines),
    lines.reverse()
    print firstNonBlank(lines)
 
def download(url="http://www.baidu.com", process = firstLast):
    try:
        retval = urlretrieve(url)[0]
    except IOError:
        retval = None
    if retval:
        process(retval)
if __name__ == "__main__":
download()


程序就是把百度的首頁用HTML的格式輸出。

 

看得有點頭暈腦脹的,不過繼續看啦。公司居然斷網了,瞬間無語。。。。

原本休息的時候還可以寫郵件的,結果一切白談。。。。

 

11.6 可變長度的參數

11.6.1 非關鍵字可變長參數(元祖)

當函數被調用的時候,所有的形參(必須的和默認的)都將值賦給了在函數聲明中相對應的局部變量。剩下的非關鍵字參數按順序插入到一個元組中便於訪問。

def fun(value1, value2 = "hello", *args):
    print value1,
    print value2,
    for item in args:
        print item,
fun("123","world","1","2","3")
程序輸出:
>>>
123 world 1 2 3
但是默認參數貌似沒使用成功,先繼續往下看,看默認參數如何和元祖結合使用的。

往下看的時候才知道,如果要用到默認參數的話,必須傳遞的是字典而不是元祖。請看下面的例子:

def fun(value1, value2 = "hello", **args):
    print value1
    print value2
    for item in args.keys():
        print "key is: %s andvalue is:%s" % (item, str(args[item]))
fun("123",value2 = "world", a = 1,b = 2, c = 3)

程序輸出:
>>>
123
world
key is: a and value is:1
key is: c and value is:3
key is: b and value is:2

這裏有點要注意到是,不能寫成這樣:

fun("123",value2 = "world", "a" =1,"b" = 2, "c" = 3)

想想就知道了,”a” = 1本身就是一個錯誤的表達式。

 

關鍵字和非關鍵字可變長參數都有可能用在同一個函數中,只要關鍵字字典是最後一個參數並且非關鍵字元組先於它之前出現。

我去,這好複雜,複雜的表達式能少用就儘量少用。

11.6.3 調用帶有可變長參數對象函數

函數式編程舉例

def testit(func, *nkwargs, **kwargs):
    try:
        retval = func(*nkwargs,**kwargs)
        result = (True, retval)
    except Exception, diag:
        result = (False, str(diag))
    return result
def test():
    funcs = (int, long, float)
    vals = (1234, 12.34,"1234", "12.34")
    for eachFunc in funcs:
        print "-" * 20
        for eachVal in vals:
            retval =testit(eachFunc, eachVal)
            if retval[0]:
                print"%s(%s)=" % (eachFunc.__name__,eachVal), retval[1]
            else:
                print "%s(%s) =failed:" % (eachFunc.__name__, eachVal), retval[1]
 
if __name__ == "__main__":
test()
程序輸出:
>>>
--------------------
int(1234)= 1234
int(12.34)= 12
int(1234)= 1234
int(12.34) = failed: invalid literal for int() with base 10: '12.34'
--------------------
long(1234)= 1234
long(12.34)= 12
long(1234)= 1234
long(12.34) = failed: invalid literal for long() with base 10: '12.34'
--------------------
float(1234)= 1234.0
float(12.34)= 12.34
float(1234)= 1234.0
float(12.34)= 12.34

這例子特別好,現在開始對單元測試有點了解了。

11.7 函數式編程

來進入傳說中的函數式編程,函數式編程是LISP的核心知識,其實在python中並不太重要,因爲python可以用一些技巧來達到函數式編程的效果,比如列表推導式。

11.7.1 匿名函數與lambda

python 允許用lambda 關鍵字創造匿名函數。匿名是因爲不需要以標準的方式來聲明,比如說,使用def 語句。(除非賦值給一個局部變量,這樣的對象也不會在任何的名字空間內創建名字.)然而,作爲函數,它們也能有參數。一個完整的lambda“語句”代表了一個表達式,這個表達式的定義體必須和聲明放在同一行。我們現在來演示下匿名函數的語法:

lambda [arg1[, arg2,... argN]]: expression

參數是可選的,如果使用的參數話,參數通常也是表達式的一部分。

>>> true = lambda : True
>>> true
<function <lambda> at 0x020C41F0>
>>> true()
True

你只要把lambda整個表達式看成一個函數調用即可。
>>> (lambda x, y = 2: x + y)(2,3)
5

當然,不要在lambda中編寫複雜的表達式,如果這樣,你倒不如直接寫個函數得了。

 

11.7.2 內建函數apply(), filter(), map(), reduce()

apply(func[, nkw][,kw])

用可選的參數來調用func,nkw 爲非關鍵字參數,kw 關鍵字參數;返回值是函數調用的返回值。

filter(func, seq)

調用一個布爾函數func來迭代遍歷每個seq 中的元素; 返回一個使func 返回值爲ture 的元素的序列。

map(func,seq1[,seq2...])

將函數func 作用於給定序列(s)的每個元素,並用一個列表來提供返回值;如果func 爲None, func 表現爲一個身份函數,返回一個含有每個序列中元素集合的n 個元組的列表。

reduce(func, seq[,init])

將二元函數作用於seq 序列的元素,每次攜帶一對(先前的結果以及下一個序列元素),連續的將現有的結果和下次給值作用在獲得的隨後的結果上,最後減少我們的序列爲一個單一的返回值;如果初始值init 給定,第一個比較會是init 和第一個序列元素而不是序列的頭兩個元素。

 

Filter的使用:

def func(num):
    return num > 5
seq = [1,2,3,4,5,6,7,8,9,10]
print filter(func, seq)
程序輸出:
>>>
[6, 7, 8, 9, 10]

其實可以直接用列表推導式來代替filter:
[item for item in seq if item> 5]

Map的使用:
>>> map(lambda x,y:x + y, [1,3,5],[2,4,6])
[3, 7, 11]
>>> map(lambda x,y:(x+y, x-y), [1,3,5],[2,4,6])
[(3, -1), (7, -1), (11, -1)]
>>> map(None,[1,3,5],[2,4,6])
[(1, 2), (3, 4), (5, 6)]
這貌似用列表推導式無法辦到,在多餘兩個參數迭代的情況下。

 

Reduce的使用:

reduce(func, [1, 2,3]) = func(func(1, 2), 3)

所以,可以用reduce輕而易舉的進行列表的累加和計算:

>>> reduce(lambda x,y:x + y, range(5))
10

11.7.3 偏函數應用

剛纔看了一下,剛開始覺得神奇,但是突然想起,這不是LISP裏面lambda最簡單的應用嗎?我同樣可以用lambda來完成書上的例子:

>>> fun1 = lambda x:x + 1
>>> fun1(4)
5
>>> fun1 = lambda x:int(x, base=2)
>>>fun1("10010")
18

但是,我們還是得簡單的看看這個偏函數的一個使用方法吧。

偏函數應用GUI

from functools import partial
import Tkinter
root = Tkinter.Tk()
MyButton =partial(Tkinter.Button, root, fg="white",bg="blue")
b1 =MyButton(text="button 1")
b2 =MyButton(text="button 2")
qb = MyButton(text="quit",bg="red",command=root.quit)
b1.pack()
b2.pack()
qb.pack(fill=Tkinter.X,expand=True)
root.title("PFAs!")
root.mainloop()

程序效果:

其實這裏偏函數的作用就是將一個函數封裝起來,當作參數傳遞罷了。


11.8 變量作用域

11.8.1 全局變量與局部變量

“聲明適用的程序的範圍被稱爲了聲明的作用域。在一個過程中,如果名字在過程的聲明之內,它的出現即爲過程的局部變量;否則的話,出現即爲非局部的“

全局變量的一個特徵是除非被刪除掉,否則它們的存活到腳本運行結束,且對於所有的函數,他們的值都是可以被訪問的,然而局部變量,就像它們存放的棧,暫時地存在,僅僅只依賴於定義它們的函數現階段是否處於活動。當一個函數調用出現時,其局部變量就進入聲明它們的作用域。在那一刻,一個新的局部變量名爲那個對象創建了,一旦函數完成,框架被釋放,變量將會離開作用域。

當我們需要在函數內用到全局變量的時候,可以用關鍵字global。

11.8.4 閉包

根本就不知道閉包是什麼東東,我去,看例子最重要,從例子中進行理解。

def counter(start_at = 0):
    count = [start_at]
    def incr():
        count[0] += 1
        return count[0]
return incr

程序輸出:
>>> count =counter(5)
>>> count()
6
>>> count()
7
>>> count2 =counter(100)
>>> count2()
101
>>> count()
8

突然明白,閉包也不過是局部函數調用全局函數的一種方法而已。其實用類的思想完全可以代替的。

 

我們來做做練習吧:

11-3 函數。在這個練習中,我們將實現max()和min()內建函數。
(a) 寫分別帶兩個元素返回一個較大和較小元素,簡單的max2()核min2()函數。他們應該可以用任意的python 對象運作。舉例來說,max2(4,8)和min2(4,8)會各自每次返回8 和4。
(b) 創建使用了在a 部分中的解來重構max()和min()的新函數my_max()和my_min().這些函數分別返回非空隊列中一個最大和最小值。它們也能帶一個參數集合作爲輸入。用數字和字符串來測試你的解。

a)

def max2(num1, num2):
    return num1 if num1 > num2 else num2
def min2(num1, num2):
    return num1 if num1 < num2 else num2
print max2(4,8)
print min2(4,8)
程序輸出:
>>> 
8
4
b)
def max2(num1, num2):
    return num1 if num1 > num2 else num2
def min2(num1, num2):
    return num1 if num1 < num2 else num2
def my_max(*args):
    return reduce(max2, args)
def my_min(*args):
    return reduce(min2, args)
print my_max(1,2,3,4,5,6,7,8)
print my_min(1,2,3,4,5,6,7,8)
程序輸出:
>>> 
8
1

11–4. 返回值。給你在5-13 的解創建一個補充函數。創建一個帶以分爲單位的總時間以及返回一個以小時和分爲單位的等價的總時間。 
"""將小時:分鐘形式直接表示爲分鐘格式"""  
def TranHourToMinute(strTime):  
    num = []  
    num = strTime.split(":")  
    return int(num[0]) * 60 + int(num[1])
def TranMinuteToHour(strTime):
    hour,minute = divmod(strTime, 60)
    return str(hour)+":"+str(minute)
if __name__ == "__main__":  
    while True:  
        strTime = raw_input("please enter the time,like 12:12(q to quit):")  
        if strTime.lower() == "q":  
            break  
        print "the time is:%d minutes" % (TranHourToMinute(strTime))
        print "the same time is: %s" % (TranMinuteToHour(TranHourToMinute(strTime)))
程序輸入輸出:
>>> 
please enter the time,like 12:12(q to quit):12:12
the time is:732 minutes
the same time is: 12:12
please enter the time,like 12:12(q to quit):q

11–6. 變長參數。下一個稱爲printf()的函數。有一個值參數,格式字符串。剩下的就是根據格式化字符串上的值,要顯示在標準輸出上的可變參數,格式化字符串中的值允許特別的字符串格式操作指示符,如%d, %f, etc。提示:解是很瑣碎的----無需實現字符串操作符功能性,但你需要顯示用字符串格式化操作(%) 
這道題做出來很難,用python實現printf。

先放着


11–7. 用map() 進行函數式編程。給定一對同一大小的列表, 如[1 , 2 , 3] 和['abc','def','ghi',....],將兩個標歸併爲一個由每個列表元素組成的元組的單一的表,以使我們的結果看起來像這樣:{[(1, 'abc'), (2, 'def'), (3, 'ghi'), ...}.(雖然這問題在本質上和第六章的一個問題相似,那時兩個解沒有直接的聯繫)然後創建用zip 內建函數創建另一個解。

>>> map(lambda x, y:(x, y),[1,2,3],["abc","def","ghi"])
[(1, 'abc'), (2, 'def'), (3, 'ghi')]
>>> zip([1,2,3],["abc","def","ghi"])
[(1, 'abc'), (2, 'def'), (3, 'ghi')]

11–9. 用reduce()進行函數式編程。複習11.7.2 部分,闡述如何用reduce()數字集合的累加的代碼。修改它,創建一個叫average()的函數來計算每個數字集合的簡單的平均值。 
def average(*args):
    return reduce(lambda x, y: x + y, args) / len(args)
print average(1,2,3,4,5)
程序輸出:
>>> 
3

11–10.用filter()進行函數式編程。在unix 文件系統中,在每個文件夾或者目錄中都有兩個特別的文件:'.'表示現在的目錄,'..'表示父目錄。給出上面的知識,看下os.listdir()函數的文檔並描述這段代碼做了什麼:files = filter(lambda x: x and x[0] != '.', os. listdir(folder)) 
將文件過濾出來。


11–11.用map()進行函數式編程。寫一個使用文件名以及通過除去每行中所有排頭和最尾的空白來“清潔“文件。在原始文件中讀取然後寫入一個新的文件,創建一個新的或者覆蓋掉已存在的。給你的用戶一個選擇來決定執行哪一個。將你的解轉換成使用列表解析。

這裏直接用strip方法最簡單,如果非要用map來進行過濾的話,需要自己編寫類似strip的一個函數。

def strip(strTemp):
    return strTemp.strip()
while True:
    fileName = raw_input("please enter the fileName(q to quit):")
    if fileName.lower() == "q":
        break
    choice = raw_input("n to new file, or c to cover file:")
    if choice.lower() == "n":
        newFileName = raw_input("please enter the new file name:")
        with open(newFileName,"w") as fobj:
            with open(fileName) as fobjold:
                lines = fobjold.readlines()
                for line in map(strip, lines):
                    fobj.write(repr(line))
                    fobj.write("\n")
    else:
        with open(fileName) as fobjold:
            lines = fobjold.readlines()
        with open(fileName,"w") as fobjold:
            for line in map(strip, lines):
                fobjold.write(repr(line))
                fobjold.write("\n")
看了一下文件,結果正確。



11–12. 傳遞函數。給在這章中描述的testit()函數寫一個姊妹函數。timeit()會帶一個函數對象(和參數一起)以及計算出用了多少時間來執行這個函數,而不是測試執行時的錯誤。返回下面的狀態:函數返回值,消耗的時間。你可以用time.clock()或者time.time(),無論哪一個給你提供了較高的精度。(一般的共識是在POSIX 上用time.time(),在win32 系統上用time.clock())注意:timeit()函數與timeit 模塊不相關(在python2.3 中引入)

import time
def timeit(fun, *args):
    time1 = time.clock()
    for i in range(10000000):
        fun(*args)
    time2 = time.clock()
    return time2 - time1
def fun(*args):
    return reduce(lambda x, y:x + y, args)
if __name__ == "__main__":
    usingTime = timeit(fun, 1,2,3,4,5,6,7,8,9,10)
    print "using time is: %d" % usingTime
程序輸出:
>>> 
using time is: 19

11–13.使用reduce()進行函數式編程以及遞歸。在第8 張中,我們看到N 的階乘或者N!作爲從1 到N 所有數字的乘積。 
(a) 用一分鐘寫一個帶x,y 並返回他們乘積的名爲mult(x,y)的簡單小巧的函數。 
(b)用你在a 中創建mult()函數以及reduce 來計算階乘。 
(c)徹底拋棄掉mult()的使用,用lamda 表達式替代。 
(d)在這章中,我們描繪了一個遞歸解決方案來找到N!用你在上面問題中完成的timeit()函數,並給三個版本階乘函數計時(迭代的,reduce()以及遞歸) 
import time
def mult(x, y):
    return x * y
def fac1(n):
    return reduce(mult, range(1,n))
def fac2(n):
    return reduce(lambda x, y: x * y, range(1,n))

def timeit(fun, *args):
    time1 = time.clock()
    for i in range(1000000):
        fun(*args)
    time2 = time.clock()
    return time2 - time1
print timeit(fac1, 10)
print timeit(fac2, 10)
程序輸出:
>>> 
2.41728863642
2.46803054498


11–14. 遞歸。我們也來看下在第八章中的Fibonacci 數字。重寫你先前計算Fibonacci 數字的解(練習8-9)以便你可以使用遞歸。 
def fib(num):  
    a,b = 1,1  
    while num - 1:  
        a,b = b,a + b  
        num -= 1  
    return a

def new_fib(num, a = 1, b = 1):
    if num - 1:
        a,b = b,a+b
        return new_fib(num - 1, a, b)
    else:
        return a
print new_fib(8)
print fib(8)
不過這裏遞歸用的好醜,但是也不知道該怎麼弄好就是了。


11–15.遞歸。從寫練習6-5 的解,用遞歸向後打印一個字符串。用遞歸向前以及向後打印一個字符串。

def printLeft(strTemp):
    if strTemp:
        print strTemp[0],
        return printLeft(strTemp[1:])
def printRight(strTemp):
    if strTemp:
        print strTemp[-1],
        return printRight(strTemp[:-1])
printLeft("hello world!")
print 
printRight("hello world!")
程序輸出:
>>> 
h e l l o   w o r l d !
! d l r o w   o l l e h


11–17.定義 
(a) 描述偏函數應用和currying 之間的區別。 
(b) 偏函數應用和閉包之間有什麼區別? 
(c) 最後,迭代器和生成器是怎麼區別開的? 

個人感覺,偏函數就是lambda罷了。

然後迭代器和生成器的區別就是一個運行時候很順利,一個運行時候會一卡一卡的。

PS:異常那章先放在,看得煩躁。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章