簡學Python第三章__函數式編程、遞歸、內置函數

Python第三章__函數式編程、遞歸、閉包

 

歡迎加入Linux_Python學習羣html

  羣號:478616847python

 

 

目錄:web

  • 函數式編程編程

  • 傳參與返回值數組

  • 遞歸閉包

  • 匿名函數
    ssh

  • 閉包
  • 高階函數ide

  • 內置函數函數式編程

 

在第三章,咱們引入新的概念函數,在以往的代碼編寫中咱們都是用的過程式編程,函數式編程的特色將過程式編程變成易於管理調用的小模塊,函數

讓重複的代碼能夠反覆的調用,大大減小代碼量,懶惰即美德

 

1、函數式編程

  建立函數

  一個函數式由關鍵字 def ,與函數名與括號冒號,和括號中的參數組成,當想要執行函數的時候只須要寫上函數名加括號便可

  格式:  def  function (parameter)  下面就建立一個函數

1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3 
4 #建立函數
5 def print_str():
6     print("Hello World")
7 
8 #調用函數
9 print_str()
第一個函數

  變量的做用域

  咱們看一個例子,在下面代碼中咱們先把變量 a=「haha」 而後在函數中把 a=「heihei」 最後執行這個函數,並輸出變量a的結果

  咱們發現爲何a不等於 "heihei",而是咱們以前賦值的 「haha」 這個現象咱們立刻揭祕

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 
 5 a = "haha"
 6 
 7 #建立函數
 8 def print_str():
 9     a = "heihei"
10     print("Hello World")
11 
12 #調用函數
13 print_str()
14 print("我是變量a:",a)
變量的做用域例一

  全局變量與局部變量

  很明顯變量的做用域就是變量在哪個範圍內生效,若是出了這個範圍則沒法使用

  全局變量:一般全局變量存活在腳本運行結束,而且全部的函數均可以訪問它

  局部變量:只能局部變量所在的函數內部調用,而且除非把局部變量聲明成全局變量不然,其餘函數均沒法調用,而且局部變量

  當所在的函數執行完成後就不存在了

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 
 5 a = "haha"
 6 
 7 #建立函數
 8 def print_str():
 9     a = "heihei"
10     print("我是局部變量a:",a)
11 
12 
13 #調用函數
14 print_str()
15 print("我是全局變量a:",a)
全局變量與局部變量

  global

  global就是能夠把局部變量變成全局變量的,若是被聲明的局部變量名與全局變量名同樣的話,那麼局部變量會覆蓋全局變量,切

  使用global聲明變量須要在變量以前聲明不然python會告訴你,你須要在 a 前面聲明

  報錯提示:SyntaxWarning: name 'a' is assigned to before global declaration global a

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 a = "haha"
 5 
 6 #建立函數
 7 def print_str():
 8     global a
 9     a = "heihei"
10     print("我是局部變量a:",a)
11 
12 #調用函數
13 print_str()
14 print("我是全局變量a:",a)
gloable

 

2、傳參與返回值

  傳參

  函數用起來比較簡單也容易理解,可是參數的變化就比較多了,在函數括號內就是參數,參數能夠接收字符串,數字,也能夠接收字典和列表

  而且在調用的時候,咱們還能夠指定給哪一個參數賦什麼值

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 #建立函數
 5 def print_str(Name,Age,Aender):
 6     print('''
 7     Name:%s
 8     Age:%s
 9     Aender:%s
10     '''%(Name,Age,Aender))
11 
12 #用戶輸入
13 in_name = input("請輸入你的名字:")
14 in_age = input("請輸入你的年齡:")
15 in_aender = input("請輸入你的性別:")
16 
17 #固定位置傳參
18 print_str(in_name,in_age,in_aender)
19 print("----------------------------------")
20 
21 #不固定位置傳參
22 print_str(in_name,Aender=in_aender,Age=in_age)
傳參

  當咱們想要傳入列表或者字典時須要怎麼辦?

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 def print_str(lists):
 5     if type(lists) == list:
 6         print('''
 7         Name:%s
 8         Age:%s
 9         Aender:%s
10         '''%(lists[0],lists[1],lists[2]))
11     else:
12         print('''
13         Name:%s
14         Age:%s
15         Aender:%s
16         '''%(lists["name"],lists["age"],lists["aenber"]))
17 
18 #傳入列表
19 userlist = ["Ben","22","Man"]
20 print_str(userlist)
21 
22 print("----------------------------------")
23 #傳入字典
24 userdict = {"name":"Ben","age":"022","aender":"Man"}
25 print_str(userlist)
傳入字典或列表

  默認參數

  在函數中還能夠設置默認參數,默認參數的意思是這個參數你能夠傳值也能夠不傳值,當不傳值的時候這個參數就等於默認值

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 def print_str(lists,Country="China"):
 5     if type(lists) == list:
 6         print('''
 7         Name:%s
 8         Age:%s
 9         Aender:%s
10         country:%s
11         '''%(lists[0],lists[1],lists[2],Country))
12     else:
13         print('''
14         Name:%s
15         Age:%s
16         Aender:%s
17         country:%s
18         '''%(lists["name"],lists["age"],lists["aenber"],Country))
19 
20 #傳入列表
21 userlist = ["Ben","22","Man"]
22 print_str(userlist)
23 
24 print("----------------------------------")
25 #傳入字典
26 userdict = {"name":"Ben","age":"022","aender":"Man"}
27 print_str(userlist,"America")
默認參數

  非固定參數

  非固定參數的意義在於能夠接收任意個值,在你的函數不肯定用戶想傳入多少個值的時候使用,固然在調用有隻有非固定參數的函數的時候咱們能夠不傳參數。

  非固定參數分一個*和兩個*,*args會把傳入的參數變成元祖,**kwargs把傳入的參數變成字典,固然*ages能夠是別的名稱,可是在規範中最好使用*args,和**kwargs

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 def print_str(*args,**kwargs):
 5     print("我是*",args)
 6     print("我是**",kwargs)
 7 
 8 #傳入列表
 9 userlist = ["Ben","22","Man"]
10 print_str(userlist,"America")
11 print("----------------------------------")
12 #傳入字典
13 print_str(A = "1",B = "2")
非固定傳參

  既然形參能夠帶*和**,那麼實參也是能夠帶*和**,那麼*就是配合列表使用的,**就是配合字典的!

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 def print_str(*args,**kwargs):
 5     print("我是*",args)
 6     print("我是**",kwargs)
 7 
 8 #傳入列表
 9 userlist = ["Ben","22","Man"]
10 print_str(*userlist)
11 
12 print("----------------分隔符----------------")
13 
14 #傳入字典
15 userdict = {"name":"Ben","age":"022","gender":"Man"}
16 print_str(**userdict)
17 
18 解參
解參

  實參帶*就會把列表分解成   "Ben","22","Man" 一個一個單獨的元素傳入函數,而**會把字典分解成name="Ben",age="022",gender="Man"

  這種鍵值對傳入函數。

  

  形參與實參

  形參:

  變量只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元。所以,形參只在函數內部有效。函數調用結束返回主調用

  函數後則不能再使用該形參變量

  實參:

  能夠是常量、變量、表達式、函數等,不管實參是何種類型的量,在進行函數調用時,它們都必須有肯定的值,以便把這些值傳送給形參。所以

  應預先用賦值,輸入等辦法使參數得到肯定值

  

  注!當普通參數和默認參數和非固定參數結合使用的時候,要遵循一個順序,普通參數在默認參數前面,默認參數在非固定參數前面

  

  返回值

  在正常使用函數的時候,函數是能夠把函數內部處理的結果返回給函數調用者的,在沒有返回值得函數中會保留None傳給函數調用者,返回值能夠返回序列等

  在函數執行的時候遇到return函數會中止執行,並返回結果

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 #建立函數
 5 def print_str(Age):
 6     if int(Age) <= 30:
 7         return "你才%s啊!真年輕"%(Age)
 8     else:
 9         return "你都%s啦!老傢伙"%(Age)
10 
11 in_age = input("請輸入你的年齡:")
12 word = print_str(in_age)
13 print(word)
return

  

  嵌套函數

  在函數內部也能夠寫函數,這樣就是外層函數套着內側函數,這種形式稱之爲嵌套函數,同理由於做用域的關係嵌套函數只能內部調用

  return unction_2(stra)+"我是第二層\n" 就等於先 c = unction_2(stra) 而後 return c+"我是第二層\n"

1 def unction(stra):
2     def unction_2(stra_2):
3         return stra_2+"我是第三層\n"
4     return unction_2(stra)+"我是第二層\n"
5 
6 r_str = unction("")
7 print(r_str+"我是第一層")
嵌套函數

 

3、遞歸

  前面已經介紹了函數相關的知識,在函數中,函數能夠調用其餘的函數,而且函數還能夠調用自身,利用這種特性咱們能夠完成一些特定的

  操做,這種函數調用自身的形式就是遞歸

  def recursion() :
    return recursion()

  在遞歸中不能像上面兩行同樣一直調用自身,這樣一會程序就會崩潰,由於它永遠的在調用就跟while死循環同樣出不去,因此遞歸也須要進

  判斷給它出口

  例子:階乘

  什麼是階乘,階乘就是給一個天然數N,而後計算N的階乘那麼 N = 1x2x3x4....N ,這個就是階乘,咱們能夠把它到過來看,

  N = N x (n-1) x (n-2) x (n-3) ...... 1 一直乘到括號中的值等於1,既然知道了階乘是什麼,那麼咱們來寫一個程序實現它

1 def factorial(n):
2     for i in range(1,n):
3         n *= i
4     return n
5 c = factorial(4)
6 print(c)
階乘非遞歸版本

  剖析:上面的例子首先把n=4傳入進去,而後經過 for i in range(1,4)讓i分別等於1,2,3,而後進行 n*=i,咱們能夠看出這個for循環是循環3次的

  第一次(n = n*i) n = 4*1 ,此時n仍是等於4

  第二次(n = 4*i)  n = 4*2 此時n = 8 

  第三次(n = 8*i)  n = 8*3 此時n等於24

  此時for循環了3次因此結束了,經過return把n的結果返回,因此最終結果算出 4的階乘等於24

  遞歸版本

  下面看遞歸版本的階乘

1 def factorial(n) :
2     if n == 1:
3         return 1
4     else:
5         return n * factorial(n-1)
6 c = factorial(4)
7 print(c)
階乘遞歸版本

  剖析:

  首先c = factorial(4)開始執行函數,而後進行第一次判斷 n == 1,顯然第一層n不等於1,而後碰到return n * factorial(n-1),碰到return原本是要返回的,可是 factorial(n-1)

  有調用了factiorial這個函數,所以進入了第二層

  第二層由於上一層傳入的參數是n-1,因此第二層的n是等於3的,而後判斷,這一層的n也不等於1,而後又進入第三層

  第三層n等於2,而後判斷這一層的n還不等於1,而後又進入第四層

  

  到第四層的時候這時的 n就等於1,因此觸發了 return 1 再也不調用函數了,因此就開始返回

  返回第三層 return n * factorial(n-1) , 此時factorial(n-1) 就等於第四層return上去的1,因此第三層返回時就等於return n * 1(return 2 * 1),而且第三層n是等於2的

  返回第二層factorial(n-1)就等於第三層return上去的2,而且第二層n是等於3的,return 3 * 2

  返回第一層factorial(n-1)就等於第二層return上去的6,而且第一層n是等於4的,return 4 * 6

  到此爲止遞歸執行完畢,c就等於 4 * 6 c=24

   

   

4、匿名函數

  匿名函數也叫lambda函數,函數沒有具體的名稱。語法:function name=  lambda  args(多個參數用逗號隔開): Expression(表達式,表達式的結果就是返回值)

  先來看一個最簡單例子:

 1 #普通函數
 2 def func(arg1,arg2):
 3     return arg1-arg2
 4 
 5 #lambda函數
 6 func_2 = lambda arg1,arg2: arg1-arg2
 7 
 8 #傳參執行
 9 print(func(5,4))
10 print(func_2(5,4))
匿名函數

  有認識,這個匿名函數和普通函數沒有什麼區別麼,其實匿名函數就像三元運算同樣,而且可以用lambda函數有幾大優點

  一、在一些不會再別的地方調用的函數,咱們可使用匿名函數,而且這樣簡化了代碼,看起來更加整潔。

  二、lambda函數將會搭配一些內置函數來使用(下面會涉及到)

 

5、閉包

  在上面的示例中知道了函數能夠調用函數自己,這種形式稱之爲遞歸,那麼還能夠將函數做爲參數返回,這種形式就稱之爲閉包

  閉包最大的好處就是即用即調,閉包對於安裝計算,隱藏狀態,以及在函數對象和做用域中隨意地切換是頗有用的!

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 def func(rate):
 4     count = [0]
 5     def add_func(arg):
 6         count[0] +=1
 7         print("第%s次調用"%count[0])
 8         arg = arg - arg*rate
 9         return arg
10     return add_func
11 
12 closure = func(0.03)
13 print(closure(1000))
14 print(closure(1100))
15 print(closure(1200))
閉包示例

  例子中作了一個減去手續費後返回餘額的功能,首先執行了func函數,將利率封裝了進去,而後,func函數把它內部的函數進行了進行了返回

  要知道當函數不加括號的時候是不執行的!,因此此時closoure就是 add_func 函數的內存地址,當想要使用這個功能的時候,直接把closoure加括號

  並傳入值便可執行。而且能夠看到的是在全局做用域中執行,隨時能夠切換到局部做用域。

 

6、高階函數

  函數能夠用來當作返回值,能夠用調用本身自己,高階函數就是函數的參數把另外一個函數做爲參數,這種函數就稱之爲高階函數。

 1 def func_1(num):
 2     return num+1
 3 
 4 def func_2(num):
 5     return num-1
 6 
 7 def func_main(num,func):
 8     #  能夠簡寫成return func(num)
 9     results = func(num)
10     return results
11 
12 results = func_main(10,func_1)
13 print(results)
14 print(func_main(10,func_2))
高階函數

  編寫高階函數,就是讓函數的參數可以接收別的函數。

  

7、內置函數

  內置函數就是python中內置的一些方法,內置函數官方介紹請猛戳這裏

  

  內置函數使用方法示例,詳細介紹請參考

  1 # !/usr/bin/env python
  2 # -*- coding:utf-8 -*-
  3 
  4 #返回數字的絕對值。 參數能夠是整數或浮點數。 若是參數是複數,則返回其大小。
  5 print(abs(-1.11))
  6 
  7 #傳入一個可被循環的元素,若是這個元素中有一個爲False則都爲假
  8 # 0 空值 False 都爲假
  9 print(all([1,2,3]))
 10 
 11 #與all相反,只有一個爲真,則爲真;
 12 print(any([0,2,False]))
 13 
 14 #這個函數跟repr()函數同樣,返回一個可打印的對象字符串方式表示。當遇到非ASCII碼時
 15 #就會輸出\x,\u或\U等字符來表示。與Python 2版本里的repr()是等效的函數。
 16 print(ascii("dsads"),ascii(66),ascii('b\23'))
 17 
 18 #將十進制轉換爲二進制;
 19 print(bin(10))
 20 
 21 #返回布爾值,即True或False之一,若是參數爲false或省略,則返回False; 不然返回True。
 22 print(bool(1))
 23 
 24 #根據傳入的參數建立一個新的字節數組
 25 #若是傳入字符串必須給出編碼
 26 print(bytearray('你好','utf-8'))
 27 #當source參數是一個可迭代對象,那麼這個對象中的元素必須符合大於0 小於256
 28 print(bytearray([256,1,2]))
 29 
 30 #返回一個的「bytes」對象,返回bytes類型
 31 bytes('中文','utf-8')
 32 
 33 #檢查對象是否能夠被調用
 34 def func():
 35     pass
 36 print(callable(func))
 37 
 38 #返回整數所對應的Unicode字符,chr(97)返回字符串'a',而chr(8364)返回字符串'€'。
 39 print(chr(126))
 40 
 41 #是用來指定一個類的方法爲類方法,類方法能夠不實例化直接調用
 42 class A:
 43     @classmethod
 44     def B(cls,arg1,):
 45         print(arg1)
 46 A.B(1)
 47 A().B(1)
 48 
 49 #將源編譯爲代碼或者AST對象。代碼對象可以經過exec語句來執行或者eval()進行求值。
 50 #源能夠是正常字符串,字節字符串或AST對象。
 51 expr = "5+5-1"
 52 obj = compile(expr,"","eval")
 53 print(eval(obj))
 54 
 55 #返回值爲real + imag * j的複數或者轉化一個字符串或數爲複數。若是第一個參數爲字符串,則不須要指定第二個參數。
 56 print(complex(1, 2))
 57 print(complex(1))
 58 print(complex("1+2j"))
 59 
 60 
 61 
 62 # 參數是一個對象和一個字符串。 該字符串必須是對象屬性之一的名稱。
 63 class A:
 64     def a1(self):
 65         print("a1")
 66     def a2(self):
 67         print("a2")
 68 
 69 obj = A
 70 print(dir(obj))
 71 delattr(obj, "a1")
 72 print(dir(obj))
 73 
 74 #dir 返回對象中的方法
 75 strs="aaa"
 76 print(dir(strs))
 77 
 78 #返回兩個數值的商和餘數
 79 print(divmod(7,3))
 80 
 81 #用於遍歷序列中的元素以及它們的下標
 82 print(enumerate([1,2,3]))#返回的是可迭代的對象
 83 for i,j in enumerate(('A','B','C')):
 84     print(i,j)
 85 
 86 #將字符串str當成有效的表達式來求值並返回計算結果。
 87 print(eval("1+2+3"))
 88 print(eval("False or True"))
 89 
 90 #字符串str當成動態語句塊執行並返回結果
 91 exec('a=1+2+3')
 92 print(a)
 93 
 94 #使用指定方法(方法,函數),過濾可迭代對象的元素
 95 def add(arg):
 96     return arg > 3
 97 
 98 for i in filter(add,[1,2,3,4,5]):
 99     print(i)
100 
101 #浮點型
102 print(float(11))
103 
104 #格式化顯示 更多方法請參考官方說明
105 print('{:,.2f}'.format(111111))
106 
107 #根據傳入的參數建立一個新的不可變集合
108 a = frozenset([1,2,3,4,5])
109 print(a)
110 
111 #獲取對象的屬性值
112 class A():
113     def __init__(self,):
114         self.name = "123"
115 b = A()
116 print(getattr(b,'name'))
117 
118 #返回當前做用域內的全局變量和其值組成的字典
119 print(globals())
120 
121 #檢查對象是否含有屬性
122 class A():
123     def __init__(self,):
124         self.name = "123"
125 b = A()
126 print(hasattr(b,'name'))
127 
128 #哈希值計算
129 #在當前環境中是惟一的
130 print(hash('Hello'))
131 
132 #help幫助
133 def funcs(args):
134     """
135     Function description
136     :param args: args = list
137     :return:
138     """
139     pass
140 print(help(funcs))
141 
142 #轉換16進制
143 print(hex(44))
144 
145 #顯示對象的標識符
146 print(id("123"))
147 
148 #input標準輸入
149 s = input("user name:")
150 print(s)
151 
152 #int返回整數
153 print(int(1.2))
154 print(int("2"))
155 
156 #判斷對象是不是類或者類型元組中任意類元素的實例
157 print(isinstance("1",int))
158 print(isinstance(1.1,(int,float)))
159 
160 
161 #判斷類是不是另一個類或者類型元組中任意類元素的子類
162 print(dir(str))
163 print(issubclass(bytearray,str))
164 print(issubclass(bool,int))
165 
166 #根據傳入的參數建立一個新的可迭代對象
167 a = iter('12345')
168 print(next(a))
169 print(next(a))
170 
171 #返回對象的長度len
172 a = [1,2,3,4]
173 
174 #轉換列表
175 print(list("abcd"))
176 
177 #返回當前做用域內的局部變量和其值組成的字典
178 def A():
179     print(locals())
180     s = 1
181     print(locals())
182 A()
183 
184 #使用指定方法去做用傳入的每一個可迭代對象的元素,生成新的可迭代對象
185 def add(x):
186     return x+100
187 lists = [1,2,3,4]
188 for i in map(add,lists):
189     print(i)
190 
191 #max:返回最大值
192 print(max(1,2,3))
193 print(max([1,2,3,4]))
194 
195 #在進行切片並賦值數據時,不須要從新copy原列表數據,能夠直接映射原數據內存;
196 s = memoryview(b'abcd')
197 print(s[1])
198 
199 #返回最小值
200 print(min(1,2,3))
201 print(min([2,3]))
202 
203 #返回可迭代對象中的下一個元素值
204 a = iter('1234')
205 print(next(a))
206 
207 #建立一個新的object對象(新式類)
208 class B(object):
209     pass
210 
211 #轉化成8進制數字符串
212 print(oct(10))
213 
214 #open文件操做
215 file = open('test.txt',encoding="utf-8")
216 
217 #ord:返回Unicode字符對應的整數
218 print(ord("A"))
219 
220 #冪運算
221 
222 print(pow(2,3))
223 
224 #標準輸出
225 print()
226 
227 #property:標示屬性的裝飾器
228 #類中使用具體方法請百度,或者等待後續更新
229 property
230 
231 #range:根據傳入的參數建立一個新的range對象
232 range(10)
233 range(1,10)
234 
235 """repr()函數獲得的字符串一般能夠用來從新得到該對象,repr()的輸入對python比較友好。
236 一般狀況下obj==eval(repr(obj))這個等式是成立的。"""
237 obj='Python'
238 print(eval(repr(obj)))
239 
240 
241 #翻轉序列
242 a = reversed([1,2,3,4,5])
243 print(list(a))
244 
245 #round:對浮點數進行四捨五入求值
246 print(round(1.5))
247 
248 #set 轉換成集合
249 print(set([1,2,3]))
250 
251 #setattr:設置對象的屬性值
252 class A():
253     def __init__(self,age):
254         self.age = age
255 s = A(11)
256 print(s.age)
257 setattr(s,'age',22)
258 print(s.age)
259 
260 #根據傳入的參數建立一個新的切片對象
261 c1 = slice(3)
262 c2 = slice(2,4)
263 c3 = slice(0,5,2)
264 s = [1,2,3,4,5,6]
265 print(s[c1])
266 print(s[c2])
267 print(s[c3])
268 
269 
270 #排序,返回一個新的列表默認按字符ascii碼排序
271 a = [4,3,2,1,7]
272 print(sorted(a))
273 
274 #標示方法爲靜態方法的裝飾器
275 class B(object):
276     def __init__(self,age):
277         self.age = age
278 
279     @staticmethod
280     def hello(args):
281         print(args)
282 
283 B.hello("Hello World")
284 
285 #字符串類型
286 print(str(123))
287 
288 #求和
289 print(sum([1,2,3,4]))
290 
291 #根據傳入的參數建立一個新的子類和父類關係的代理對象
292 class A(object):
293     def __init__(self):
294         print("我是 A Clase")
295 
296 class B(A):
297     def __init__(self):
298         print("我是 B Class")
299         super().__init__()
300 b = B()
301 
302 #元祖
303 tuple([1,2,3,4])
304 
305 
306 #type 返回對象的類型
307 print(type([1]))
308 print(type("1"))
309 
310 #返回當前做用域內的局部變量和其值組成的字典,或者返回對象的屬性列表
311 def func():
312     print(vars())
313     s = 1
314     print(vars())
315 func()
316 
317 #聚合傳入的每一個迭代器中相同位置的元素,返回一個新的元組類型迭代器
318 list1 = [1,2,3]
319 list2 = ["A","B","C","D"]
320 print(zip(list1,list2))
321 for i in zip(list1,list2):
322     print(i)
323 
324 #__import__:動態導入模塊
325 __import__
內置方法

 

 

 

 

 

做者:北京小遠
出處:http://www.cnblogs.com/bj-xy/ 本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。

相關文章
相關標籤/搜索