Python快速學習第五天

第五天:抽象

1、    函數

檢測函數是否可調用:callable

>>> import math

>>> y=math.sqrt

>>> callable(y)

True

>>> x=1

>>> callable(x)

False

   注意:Python3.0不在支持callable,需要使用表達式hasattr(func,_call_call_)代替

   創建函數:def functionname(params):

>>>def fibs(num):

...     'Get fibonaqi sequnce! '

...     result=[0,1]

...     for i in range(num-2):

...            result.append(result[-2]+result[-1])

...     return result

...

>>>fibs(10)

[0, 1,1, 2, 3, 5, 8, 13, 21, 34]

 

用於def後面的'Getfibonaqi sequnce! '添加文檔字符串,相當於註釋#,使用help()可以查詢函數的文檔字符串

help(fibs)

Help on function fibs in module __main__:

 

fibs(num)

    Getfibonaqi sequnce!

...skipping...

Help on function fibs in module __main__:

 

fibs(num)

    Getfibonaqi sequnce!

 

 return後不加值,只表示函數的結束,而沒有返回值,這樣可以避免應該返回序列時,意外返回None

>>> def test():

...     print 'tanggao'

...     return

...     print 'tanggao isgood'

...

>>> x=test()

tanggao

>>> print x

None

 

2、   參數對外部變量影響

   函數內給參數賦值,不會改變外部變量的值,參數存儲在局部作用域中

>>> def try_to_change(n):

...     n=3

...

>>> t=4

>>> try_to_change(t)#雖然在函數內部重新賦值,但外部不變

>>> t

4

 

但是對於可改變的數據結構,如列表,參數的內部賦值會改變外部變量的值

   內部參數與外部變量指向同一個列表,所以會被修改

   若不想改變外部列表,可以傳進一個副本

>>> def change(n):

...    n[0]='tanggao'

...

>>> names=['hello','world']

>>> change(names)

>>> names

['tanggao', 'world']

>>>  #採用普通方法進行模擬 

...

>>> names=['hello','world']

>>> n=names

>>> n[0]='tanggao'

>>> names

['tanggao', 'world']

 

 

完整示例——存儲名字,並能用名字、中間名或姓來查找聯繫人

   若名字爲'MagusLie Hetland'存儲格式類似

   data = {

           'first':{ 'Magus': 'Magus Lie Hetland'},

           'middle':{'Lie': 'Magus Lie Hetland'},

           'last':{'Hetland': 'Magus Lie Hetland'}

       }

   注意insert(index,value)函數,在列表的索引位置插入值

Python代碼  

1.  >>> def init(data):  #data作爲存儲表,初始化  

2.      data['first'] = {}  

3.      data['middle'] = {}  

4.      data['last'] = {}  

5.    

6.  >>> def store(data, full_name): #存儲,將全名存儲到表中  

7.      names = full_name.split()  #將名字按空格(即first,middle,last)分開,返回列表,如'Ma Li He'返回['Ma', 'Li', 'He']  

8.      if len(names) == 2: names.insert(1, '')#若無中間名,則插入空來表示中間名['Mr', 'Zha']返回['Mr', '', 'Zha']  

9.      labels = 'first''middle''last'  #元組  

10.     for label, name in zip(labels, names):  #元組與序列間也可使用zip  

11.         people = lookup(data, label, name)  

12.         if people:  

13.             people.append(full_name)  

14.         else:  

15.             data[label][name] = [full_name] #當鍵不存在時,自動添加鍵值對,  

16.                                                                          #但如果輸出不存在鍵對應值,則報錯  

17.   

18. >>> def lookup(data, label, name): #查找,根據label查找是name的中間人  

19.     return data[label].get(name)  

20.   

21.               

22. >>> MyNames = {}  

23. >>> init(MyNames)  

24. >>> store(MyNames, 'Magnus Lie Hetland')  

25. >>> lookup(MyNames, 'middle''Lie')  

26. ['Magnus Lie Hetland']  

27. >>> store(MyNames, 'Robin Hood')  

28. >>> store(MyNames, 'Robin Locksley')  

29. >>> lookup(MyNames, 'first''Robin')  

30. ['Robin Hood''Robin Locksley']  

31. >>> store(MyNames, 'Mr. Gumby')  

32. >>> lookup(MyNames, 'middle''')  

33. ['Robin Hood''Robin Locksley''Mr. Gumby']  

 

   例2. 不可變的數字和可改變的參數

Python代碼  

1.  >>> def inc(x): return x + 1  

2.    

3.  >>> foo = 10  

4.  >>> inc(foo)  

5.  11  

6.  >>> foo #外部變量未發生變化  

7.  10  

8.  >>> foo = inc(foo) #將foo重新賦值  

9.  >>> foo  

10. 11  

 

   使用列表外部變量foo改變了

Python代碼  

1.  >>> def inc(x): x[0] = x[0] + 1  

2.    

3.  >>> foo = [10]  

4.  >>> inc(foo)  

5.  >>> foo  

6.  [11]  

 

3. 關鍵字參數和默認值

   位置:是指根據參數的對應位置傳參,如def a(a,b,c):,調用a(1,2,3),1傳給a,2傳給b,3傳給c,這樣參數位置容易記混。

   關鍵字參數,適用於大規模程序,清晰

Python代碼  

1.  >>> def hello(name, greeting):  

2.      print '%s, %s!' %(greeting, name)  

3.    

4.        

5.  >>> hello('sun''Hello')  #位置參數  

6.  Hello, sun!  

7.  >>> hello(name = 'Sun', greeting = 'Hello')  #關鍵字參數  

8.  Hello, Sun!  

9.  >>> hello(greeting = 'Hello', name = 'Sun'#關鍵字參數,不必關心位置  

10. Hello, Sun!  

 

   默認值

Python代碼  

1.  >>> def hello(name = 'world', greeting = 'Hello'):  

2.      print '%s, %s!' %(greeting, name)  

3.    

4.        

5.  >>> hello()  

6.  Hello, world!  

7.  >>> hello('Sun')  

8.  Hello, Sun!  

9.  >>> hello(greeting = 'Hi')  

10. Hi, world!  

 

   位置參數與關鍵字參數混用,將位置參數放在前面。儘量避免這麼用,容易引起混亂。

Python代碼  

1.  >>> def hello(name, greeting = 'Hello', punc = '!'):  

2.      print '%s, %s%s' %(greeting, name, punc)  

3.    

4.        

5.  >>> hello('Sun')  

6.  Hello, Sun!  

7.  >>> hello('Sun''Hi')  

8.  Hi, Sun!  

9.  >>> hello('Sun', punc = '..')  

10. Hello, Sun..  

11. >>> hello()   #因爲name是必須要有,若有默認值,則可沒有  

12.   

13. Traceback (most recent call last):  

14.   File "<pyshell#385>", line 1, in <module>  

15.     hello()  

16. TypeError: hello() takes at least 1 argument (0 given)  

17. >>>   

 

4. 收集參數——在定義時使用*或**,用來收集參數,允許使用不定數量的參數

   *:收集其餘的位置參數並作爲元組 返回

Python代碼  

1.  >>> def print_params2(title, *params):  

2.      print title  

3.      print params  

4.    

5.        

6.  >>> print_params2('Param:', 1, 2, 3)  

7.  Param:  

8.  (1, 2, 3)  #以元組形式返回  

9.  >>> print_params2('Param:'#不提供收集元素時,返回空元組  

10. Param:  

11. ()  

12. >>> print_params2('Param:', 1)   

13. Param:  

14. (1,) #只有一個元素時,仍爲元組  

 

   **:收集其餘的關鍵字參數並作爲字典 返回,可與其他混用

Python代碼  

1.  >>> def print_params3(x, y, z = 3, *pospar, **keypar):  

2.      print x, y, z  

3.      print pospar  

4.      print keypar  

5.    

6.        

7.  >>> print_params3(1,2,3,4,5,6,7, fool = 1, bar = 2)  

8.  1 2 3  

9.  (4, 5, 6, 7)  

10. {'fool': 1, 'bar': 2}  

11. >>> print_params3(1,2)  

12. 1 2 3  

13. ()  

14. {}  

 

5. 收集參數的翻轉過程——在調用時使用*或**,將參數分配到定義的參數中,用於字典或列表分割時

   用於列表

Python代碼  

1.  >>> def add(x,y): return x + y  

2.    

3.  >>> params = (1,2)  

4.  >>> add(*params)  

5.  3  

 

   用於字典

Python代碼  

1.  >>> def hello(name, greeting):  

2.      print '%s, %s!' %(greeting, name)  

3.    

4.        

5.  >>> params = {'name''Sir Robin''greeting''Welcome'}  

6.  >>> hello(**params)  

7.  Welcome, Sir Robin!  

8.    

9.     

 

   參數使用實例

Python代碼  

1.  #模擬步長大於0的range()  

2.  >>> interval(10)  

3.  start = 0 stop = 10 step =  1  

4.  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]  

5.  >>> def interval(start, stop=None, step=1):  

6.      'Imitates range() for step > 0'  

7.      if stop is None: #若未給stop指定值  

8.          start, stop = 0, start #多個賦值,0賦值給start,start的值賦值給stop  

9.      result = []  

10.     i = start  

11.     while i < stop:  

12.         result.append(i)  

13.         i += step  

14.     return result  

15.   

16. #  

17. >>> def story(**kwds):  

18.     return '%(job)s called %(name)s.' %kwds  

19.   

20. >>> def power(x, y ,*others):  

21.     if others:  

22.         print 'Received redundant parameters:',others  

23.     return pow(x,y)  

24.   

25. #使用  

26. >>> params = {'job':'language','name':'python'}  

27. >>> print story(**params) #調用時分割字典,定義中收集  

28. language called python.  

29. >>> del params['job']  

30. >>> print story(job='test', **params)  

31.   

32. >>> power(2,3,'test')  

33. Received redundant parameters: test  

34.   

35. >>> params = (5,) * 2 #即(5,5)  

36. >>> power(*params) #先分割,在賦給x,y  

37. 3125  

 

6.作用域

   x = 1, 將名字x引用到值1上,類似字典

   內建函數vars()返回這個字典

Python代碼  

1.  >>> x = 1  

2.  >>> scope = vars()  

3.  >>> scope['x']  

4.  1  

5.  >>> scope['x'] += 1 #一般情況下,vars()返回的字典不能修改  

6.  >>> x  

7.  2  

 

   局部變量,全局變量

   函數內部訪問全局變量,慎用!

Python代碼  

1.  >>> def com(para): print para + external  

2.    

3.  >>> external = 'external'  

4.  >>> com('param ')  

5.  param external  

 

   若全局變量與局部變量名字相同,會被局部變量覆蓋,可使用global()類似vars(),獲得全局變量的字典

Python代碼  

1.  >>> def com(para): print para + globals()['para']  

2.    

3.  >>> para = 'berry'  

4.  >>> com('test ')  

5.  test berry  

 

   重綁定全局變量,將變量引用到其他新值——函數內部聲明全局變量

Python代碼  

1.  >>> x = 1  

2.  >>> def change_global():  

3.      global x  

4.      x = x + 1  

5.    

6.        

7.  >>> change_global()  

8.  >>> x  

9.  2  

 

   嵌套作用域——函數中定義函數,例如閉包

   外部作用域中的變量一般不能被改變,但是用閉包,每次調用外層函數,內部函數都會被重新綁定,也即外部作用域factor每次都有一個新值

Python代碼  

1.  >>> def multiplier(factor):  

2.      def multiplyByFactor(number):  

3.          return number * factor  

4.      return multiplyByFactor  #返回一個函數,這時並未調用  

5.    

6.  >>> double = multiplier(2)  #double是一個函數  

7.  >>> double   #double是一個函數  

8.  <function multiplyByFactor at 0x0214C6F0>  

9.  >>> double(5)  #調用multiplyByFactor(number)  

10. 10  

11. >>> multiplier(2)(5) #效果同上  

12. 10  

 

   7. 遞歸——每調用一個函數,都會創建一個新的命名空間,意味着當函數調用自身時,實際上調用的是兩個不同的函數

    階乘

Python代碼  

1.  >>> def factorial(n):  

2.      if n == 1:  

3.          return 1  

4.      else:  

5.          return n * factorial(n-1)  

6.    

7.  >>> factorial(5)  

8.  120  

    冪

Python代碼  

1.  >>> def power(x, n):  

2.      if n == 0:  

3.          return 1  

4.      else:  

5.          return x * power(x, n - 1)  

6.    

7.        

8.  >>> power(2,3)  

9.  8  

 

   遞歸實例——二元搜索

   前提:排好序

   若上下限相同,則那就是數字所在位置,返回;

   否則,找到兩者的中間,查找數字是在左側還是右側,繼續查找數字所在的那半部分。

Python代碼  

1.  >>> def search(sequence, number, lower = 0, upper = None):  

2.      if upper is None: upper = len(sequence) - 1  

3.      if lower == upper:  

4.          assert number == sequence[upper]  

5.          return upper  

6.      else:  

7.          middle = (lower + upper) // 2  

8.          if number > sequence[middle]:  

9.              return search(sequence, number, middle + 1, upper)  

10.         else:  

11.             return search(sequence, number, lower, middle)  

12.   

13.           

14. >>> seq = [34, 67, 8, 123, 4, 100, 95]  

15. >>> seq.sort()  

16. >>> seq  

17. [4, 8, 34, 67, 95, 100, 123]  

18. >>> search(seq, 34)  

19. 2  

 

總結:

元組輸出格式化,直接使用鍵,而不需要加引號

Python代碼  

1.  >>> d = {'a':1, 'b':2}  

2.  >>> print '%(a)s corresponds to %(b)s.' %d #注意a有括號,無引號  

3.  1 corresponds to 2.  

 

發佈了160 篇原創文章 · 獲贊 584 · 訪問量 90萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章