Python3.5基礎——函數的定義與使用python
一、函數學習框架閉包
二、函數的定義與格式app
(1)定義框架
(2)函數調用函數
注:函數名稱不能以數字開頭,建議函數名稱的開頭用小寫的字母學習
(3)函數有四種格式,分別是:無參數無返回值,有參數無返回值、無參數有返回值、有參數有返回值3d
#!/usr/bin/env python日誌
# -*- coding:utf-8 -*-對象
# Author:ZhengzhengLiublog
# 無參數無返回值
defhello():
# 函數體/方法體
print("hello world")
hello()
# 有參數無返回值
defadd(x, y):
print(x + y)
add(10,20)
# 無參數有返回值
defsleep():
return"sleep"
s = sleep()
print(s)
# print(sleep()) 等價於上面兩句
# 有參數有返回值
defsub(x, y):
returnx * y
res = sub(12,6)
print(res)
#運行結果
hello world
30
sleep
72
三、函數的參數
注:定義再函數體內的參數是形參,調用時傳入的參數是實參。
函數參數包括:位置參數、關鍵字參數和不定個數參數
(1)位置參數、關鍵字參數
示例代碼:
#位置參數
deftest(x,y,z):
print(x,y,z)
test(1,2,3)
#關鍵字參數
deftest1(x,y,z=10):
print(x,y,z)
test1(1,2,3)
test1(1,2)#關鍵字參數,z採用默認的參數值
test1(x=2,z=3,y=1)#調用時的關鍵字參數
#運行結果:
123
123
1210
213
(2)默認參數
注:帶有默認值參數的形參必須放在參數的最後面的位置。
(3)不定個數參數,用*args 和 **kwarg
總結:
(1)定義時 *的做用 將位置實參裝配成元組
定義時 **的做用 將關鍵字實參裝配成字典
(2)調用時 *做用 將元組或列表打散成位置參數進行參數傳遞
調用時 **做用 將字典打散成關鍵字參數進行參數傳遞
#不定個數參數
deftest2(x,y,z,*args):
print(x,y,z,args)
#定義時 *的做用 將位置實參裝配成元組
test2(1,2,3,4,6,7,8,9)
deftest3(x,y,z,**kwargs):
print(x,y,z,kwargs)
#定義時 **的做用 將關鍵字實參裝配成字典
test3(1,2,3,a=6,b=19,c=8)
defts(x,*args,**kwargs):
print(x,args,kwargs)
ts(1,2,3,a=6,b=19,c=8)
deftest4(x,y,z):
print(x,y,z)
x = [1,2,3]
y = {"x":1,"y":"hello","z":"你好"}
test4(*x)#調用時 *做用 將元組或列表打散成位置參數進行參數傳遞
test4(**y)#調用時 **做用 將字典打散成關鍵字參數進行參數傳遞
#運行結果:
123(4,6,7,8,9)
123{'b':19,'a':6,'c':8}
1(2,3) {'b':19,'a':6,'c':8}
123
1hello 你好
四、函數的傳值:基本類型傳值調用、非基本類型參數傳遞調用(強引用與弱引用)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#基本類型傳值調用
deftest(x):
print(x)
test(10)
#非基本類型參數傳遞調用
li = [1,2,3,4]
print(id(li))#打印傳遞前的地址
deftest1(x):
print(id(x))
x[0] =2#修改第一個參數爲2
print(x)
test1(li)#強引用(傳址調用,列表裏面的內容會進行修改)
#test1(list(li)) #弱引用(用list能夠消除強引用,不能修改列表裏的元素)
foriinli:
print(i)
#運行結果:(強引用傳址調用)
10
17741864
17741864
[2,2,3,4]
2
2
3
4
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#基本類型傳值調用
deftest(x):
print(x)
test(10)
#非基本類型參數傳遞調用
li = [1,2,3,4]
print(id(li))#打印傳遞前的地址
deftest1(x):
print(id(x))
x[0] =2#修改第一個參數爲2
print(x)
#test1(li) #強引用(傳址調用,列表裏面的內容會進行修改)
test1(list(li))#弱引用(用list能夠消除強引用,傳值調用,不能修改列表裏的元素)
foriinli:
print(i)
#運行結果:(弱引用,傳值調用)
10
18501544
18613272
[2,2,3,4]
1
2
3
4
#不可變對象——傳遞對象的值,修改值修改的是另外一個複製對象,不影響原來對象自己
defgetNum(a):
a =10
print("函數內變量a的值:",a)
a =8
getNum(a)
print("函數外變量a的值:",a)
#可變對象——傳遞對象自己,函數內部修改值會影響對象自己
list01 = [0,1,2,3]
defgetNum1(num):
num.append(4)
print(num)
print(id(num))
getNum1(list01)
print(list01)
print(id(list01))
#運行結果:
函數內變量a的值:10
函數外變量a的值:8
[0,1,2,3,4]
5908280
[0,1,2,3,4]
5908280
五、函數的返回值
示例代碼:
#多個返回值
defre(a,b):
a *=10
b *=10
returna,b
num = re(1,2)
print(type(num))#若是返回多個值,而且存在一個變量中,會以元組的形式保存
print(num)
#分別獲取多個返回值
re1,re2 = re(3,4)
print(type(re1))
print(re1,re2)
#運行結果:
(10,20)
30 40
簡單實例練習:
defoperation(a,b,opt):
ifopt =="+":
returna+b
elifopt =="-":
returna-b
elifopt =="*":
returna*b
elifopt =="/":
returna/b
else:
return"輸入有誤"
num1 = int(input("請輸入第一個字符:"))
num2 = int(input("請輸入第二個字符:"))
op = input("請輸入運算符:")
result = operation(num1,num2,op)
print(result)
#運行結果:
請輸入第一個字符:1
請輸入第二個字符:2
請輸入運算符:+
3
六、變量的做用域:全局變量與局部變量
在函數的內部,不能識別全局變量,想要在函數內部使用全局變量,須要關鍵字global,但不建議這樣使用,使用global具備污染性。
(1)局部變量
(2)全局變量
(3)當全局變量與局部變量同名時,優先使用局部變量
#全局變量與局部變量同名
a =10#全局變量
print("全局變量a:%d"%a)
deftest01():
a =20
print("test01中的a:%d"%a)
deftest02():
print("test02中的a:%d"%a)
test01()
test02()
#運行結果:
全局變量a:10
test01中的a:20
test02中的a:10
(4)修改全局變量
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
i =20
deftest():
#i += 10 #函數內部直接修改全局的值(錯誤)
globali#函數內部修改全局的值用global關鍵字
i +=10
print(i)#獲取全局變量的值
test()
#運行結果:
30
注:上邊代碼中,函數內修改不可變類型的全局變量,須要經過global關鍵字
總結:對不可變類型變量從新賦值,其實是從新建立一個不可變類型對象,並將原來的變量指向新建立的對象。
若是沒有其餘變量引用原有對象的話(即:引用計數爲0),原有對象就會被回收。
(5)可變類型的全局變量:函數內修改可變類型的全局變量,能夠不使用global關鍵字
#函數內修改可變類型的全局變量——直接修改,無需使用global關鍵字
a = [100,200,300]
print("可變類型全局變量a:",a)
print("可變類型全局變量a的地址:%d"%id(a))
deftest01():
a.append(400)
print("test01函數內修改可變類型全局變量a:",a)
print("test01函數內修改可變類型全局變量後a的地址:%d"%id(a))
deftest02():
print("test02函數內使用可變類型全局變量a:",a)
print("test02函數內使用可變類型全局變量a的地址:%d"%id(a))
test01()
test02()
#運行結果:
可變類型全局變量a: [100,200,300]
可變類型全局變量a的地址:18241896
test01函數內修改可變類型全局變量a: [100,200,300,400]
test01函數內修改可變類型全局變量後a的地址:18241896
test02函數內使用可變類型全局變量a: [100,200,300,400]
test02函數內使用可變類型全局變量a的地址:18241896
七、匿名函數
示例代碼:
#匿名函數——lambda
#語法:lambda arg1[,arg2...]:表達式 默認return
num =lambdaa,b:a+b
print(num(1,2))
#運行結果:
3
簡單應用(一):
#四則運算——利用lambda表達式
defoperation(a,b,opt):
re = opt(a,b)
returnre
num1 = int(input("請輸入第一個字符:"))
num2 = int(input("請輸入第二個字符:"))
result = operation(num1,num2,lambdaa,b:a+b)
print(result)
#運行結果:
請輸入第一個字符:2
請輸入第二個字符:3
5
簡單應用(二):
#列表中的字典元素進行排序——lambda表達式
students = [
{"name":"Joe","age":"18"},
{"name":"Tom","age":"20"},
{"name":"Susan","age":"16"}
]
students.sort(key=lambdax:x["name"])#對字典按照關鍵字name排序
print(students)
#運行結果:
[{'age':'18','name':'Joe'}, {'age':'16','name':'Susan'}, {'age':'20','name':'Tom'}]
八、遞歸函數
代碼示例:
#函數的嵌套
deftest1():
print("in test1...")
deftest2():
test1()
print("in test2...")
deftest3():
test2()
print("in test3...")
test3()
#運行結果:
intest1...
intest2...
intest3...
#遞歸函數
deffunc(n):
print("進入第%d層夢"%n)
ifn ==3:
print("進入潛意識區")
else:
func(n+1)
print("從第%d層夢中醒來"%n)
func(1)
#運行結果:
進入第1層夢
進入第2層夢
進入第3層夢
進入潛意識區
從第3層夢中醒來
從第2層夢中醒來
從第1層夢中醒來
應用:求階乘
#階乘——利用while
i =1
num =1
whilei <=4:
num = num*i
i+=1
print(num)
#階乘——利用遞歸
deffunc01(n):
ifn ==1:
return1
returnn*func01(n-1)
print(func01(4))
#運行結果:
24
24
利用遞歸實現階乘的原理過程:
九、經常使用內置函數
示例代碼:
#abs()——絕對值函數
num =-1
print(abs(num))
#sorted()——排序函數
list01 = [1,4,2,7,9,3]
print(sorted(list01))#由小到大排序
print(sorted(list01,reverse=True))#由大到小排序
#sum()——求和
print(sum(list01))
#round()——四捨五入,獲取指定位數的小數
print(round(3.1415926,2))
#pow()——乘方數(冪)
print(pow(2,3))
#isinstance——類型判斷
num1 =5
print(isinstance(num1,int))
#eval()——執行表達式或字符串做爲運算
print(eval("1+3"))
#exec()——執行Python語句
exec('print("Hello")')
#運行結果:
1
[1,2,3,4,7,9]
[9,7,4,3,2,1]
26
3.14
8
True
4
Hello
十、高階函數
示例代碼:
#經常使用高階函數
#map()
num1 = map(lambdax:x*2,[1,2,3,4,5])
print(num1)
foriinnum1:#遍歷map對象的內容
print(i,end=" ")
print()
#filter()
num2 = filter(lambdax:x%2==1,[1,2,3,4,5,6,7,8,9,10])
print(num2)
forjinnum2:#遍歷filter對象的內容
print(j,end=" ")
print()
#reduce()
from functool simport reduce
print(reduce(lambdax,y:x+y,[1,2,3,4],10))#10是起始值
#運行結果:
246810
13579
20
name = ["joe","jack","TOM","suSAN"]
age = [17,18,20,15]
sex = ["M","M","M","F"]
#案例一——格式化英文名。首字母大寫,其餘小寫
names = map(lambda t:t[0:1].upper()+t[1:].lower(),name)
for stu_name in names:
print(stu_name,end=" ")
print()
#案例二——將三個序列結合到一塊兒,造成一個集合
newStu = map(lambda n,a,s:(n,a,s),name,age,sex)
student = []
for tup in newStu:
student.append(tup)
print(student)
#案例三——過濾性別爲男的用戶
males = filter(lambda x:x[2] =="M",student)
man = []
for m in males:
man.append(m)
print(man)
#案例四——求性別爲男的用戶的平均年齡
from functools import reduce
man_count = len(man)
total_age = reduce(lambda x,y:x+y[1],man,0)
print("總年齡:",total_age)
print("平均年齡:%.2f"%(total_age/man_count))
#運行結果:
Joe Jack Tom Susan
[('joe',17,'M'), ('jack',18,'M'), ('TOM',20,'M'), ('suSAN',15,'F')]
[('joe',17,'M'), ('jack',18,'M'), ('TOM',20,'M')]
總年齡:55
平均年齡:18.33
十一、約瑟夫環
(1)一羣人圍在一塊兒坐成環狀(如:N)
(2)從某個編號開始報數(如:K)
(3)數到某數(如:M)的時候,此人出列,下一我的從新報數
(4)一直循環,直到全部人出列,約瑟夫環結束
約瑟夫環實現代碼:
#約瑟夫環問題
# n=9(總人數) m = 3(報數) k:索引
#k = (k+(m-1))%len(list)
deffunc(n,m):
#生成一個列表
people = list(range(1,n+1))
k =0#定義開始的索引
#開始循環報數
whilelen(people) >2:
k = (k+(m-1))%len(people)
print("kill:",people[k])
del(people[k])
print(k)
returnpeople
print(func(9,3))
#運行結果:
kill:3
2
kill:6
4
kill:9
6
kill:4
2
kill:8
4
kill:5
2
kill:2
1
[1,7]
十二、函數重載
在Python中,沒有函數重載,若非要使用函數重載,則後邊的同名函數會覆蓋掉前面的函數。
#函數重載
def test(x):
print(x)
def test(x,y):
print(x+y)
#test(1) #出錯
test(1,2)#覆蓋test(x)
#運行結果:
3
1三、函數的嵌套和閉包
(1)函數嵌套:在函數內部再定義新的函數
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#函數嵌套
def test():
def test1():
def test2():
print("hello")
return test2
return test1
res = test()#test函數返回值res是一個函數,等價於res ==> test1
re = res()#res() ==>test1() ,test1函數返回值re是一個函數,re==>test2
re()#re() ==> test2()
#運行結果:
hello
(2)閉包:內部函數能夠取到外部函數的局部變量
#閉包:內部函數能夠取到外部函數的局部變量
deftest(x):
deftest1(y):
deftest2(z):
print(x+y+z)
returntest2
returntest1
res = test(10)
re = res(20)
re(30)
#運行結果:
6
1四、裝飾器
(1)形象舉例:照片與相框
照片:被裝飾的對象,相框:裝飾對象。
裝飾做用:動態擴展裝飾,即:不會改變被裝飾的對象(照片)的內容,只是動態改變裝飾的對象(相框)。
(2)裝飾器修飾無參數的函數
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#裝飾器——日誌管理
def log(func):#log(func)==> func = delete(delete函數做爲實參傳入到func)
def warp():
print("logger strating...")
func()#運行delete
print("logger ending...")
return warp
@log #用log來裝飾delete,等價於delete = log(delete) = warp
defdelete():
print("deleting...")
delete()#執行warp
#運行結果:
logger strating...
deleting...
logger ending...
(3)裝飾器修飾有參數和返回值的函數
#裝飾器修飾有參數、有返回值的函數
deflog(func):#log(func)==> func = delete(delete函數做爲實參傳入到func)
defwarp(*args,**kwargs):
print("logger strating...")
res = func(*args,**kwargs)#運行delete
print(res)
print("logger ending...")
returnwarp
@log #用log來裝飾delete,等價於delete = log(delete) = warp
defdelete(name,age):
print("deleting...")
print(name,age)
return"delete success"
delete("liu",20)#執行warp
#運行結果:
logger strating...
deleting...
liu20
delete success
logger ending...
(4)裝飾器自身帶有參數
#裝飾器帶有參數
deflog(i):
defwarp1(func):
defwarp2(*args,**kwargs):
print("logger strating...")
ifi>0:
print("logging success...")
func(*args, **kwargs)
else:
print("logging failed...")
print("logger ending...")
returnwarp2
returnwarp1
@log(1)
defdelete():
print("deleting...")
delete()
#運行結果:
logger strating...
logging success...
deleting...
logger ending...
#裝飾器帶有參數
deflog(i):
defwarp1(func):
defwarp2(*args,**kwargs):
print("logger strating...")
ifi>0:
print("logging success...")
func(*args, **kwargs)
else:
print("logging failed...")
print("logger ending...")
returnwarp2
returnwarp1
@log(-1)
defdelete():
print("deleting...")
delete()
#logger strating...
logging failed...
logger ending...
1五、迭代器
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#迭代器——笛卡爾積
impor titer tools
x = range(1,6)
coml = itertools.combinations(x,3)#排列
coml2 = itertools.permutations(x,4)#組合
y = ["a","b","c"]
coml3 = itertools.product(x,y)#笛卡爾積
coml4 = itertools.chain(coml,coml2,coml3)
forhincoml4:
print(h)
運行結果:
(1,2,3)
(1,2,4)
(1,3,4)
(2,3,4)
(1,2,3,4)
(1,2,4,3)
(1,3,2,4)
(1,3,4,2)
(1,4,2,3)
(1,4,3,2)
(2,1,3,4)
(2,1,4,3)
(2,3,1,4)
(2,3,4,1)
(2,4,1,3)
(2,4,3,1)
(3,1,2,4)
(3,1,4,2)
(3,2,1,4)
(3,2,4,1)
(3,4,1,2)
(3,4,2,1)
(4,1,2,3)
(4,1,3,2)
(4,2,1,3)
(4,2,3,1)
(4,3,1,2)
(4,3,2,1)
(1,'a')
(1,'b')
(1,'c')
(2,'a')
(2,'b')
(2,'c')
(3,'a')
(3,'b')
(3,'c')
(4,'a')
(4,'b')
(4,'c')