@函數的定義
以下是簡單的規則:
函數代碼塊以 def 關鍵詞開頭,後接函數標識符名稱和圓括號 ()。
任何傳入參數和自變量必須放在圓括號中間,圓括號之間可以用於定義參數。
函數的第一行語句可以選擇性地使用文檔字符串—用於存放函數說明。函數內容以冒號起始,並且縮進。return [表達式] 結束函數,選擇性地返回一個值給調用方。不帶表達式的return相當於返回 None。
基本格式:
def 函數名(參數):
函數體
return 返回值
@函數的參數
- 必需參數
必需參數須以正確的順序傳入函數。調用時的數量必須和聲明時的一樣。
調用 printme() 函數,你必須傳入一個參數,不然會出現語法錯誤: - 關鍵字參數
關鍵字參數和函數調用關係緊密,函數調用使用關鍵字參數來確定傳入的參數值。
使用關鍵字參數允許函數調用時參數的順序與聲明時不一致,因爲 Python 解釋器能夠用參數名匹配參數值。
以下實例在函數 printme() 調用時使用參數名:
#可寫函數說明
def printme( str ):
"打印任何傳入的字符串"
print (str)
return
#調用printme函數
printme( str = "關鍵字參數")
以下實例中演示了函數參數的使用不需要使用指定順序:
#可寫函數說明
def printinfo( name, age ):
"打印任何傳入的字符串"
print ("名字: ", name)
print ("年齡: ", age)
return
#調用printinfo函數
printinfo( age=50, name="runoob" )
- 默認參數
調用函數時,如果沒有傳遞參數,則會使用默認參數。以下實例中如果沒有傳入 age 參數,則使用默認值:
def printinfo( name, age = 35 ):
"打印任何傳入的字符串"
print ("名字: ", name)
print ("年齡: ", age)
return
#調用printinfo函數
printinfo( age=50, name="runoob" )
print ("------------------------")
printinfo( name="runoob" )
運行結果:
名字: runoob
年齡: 50
------------------------
名字: runoob
年齡: 35
- 不定長參數
你可能需要一個函數能處理比當初聲明時更多的參數。這些參數叫做不定長參數,和上述 2 種參數不同,聲明時不會命名。python自定義函數中有兩種不定長參數,第一種是*args,在傳入額外的參數時可以不用指明參數名,直接傳入參數值即可。第二種是**kargs,這種類型返回的是字典,傳入時需要指定參數名。
加了一個星號 * 不定長參數會以元組(tuple)的形式導入,存放所有未命名的變量參數。加了兩個星號 ** 的參數會以字典的形式導入,存放已命名的變量參數。
實例1:
#使用不定長參數傳固定值,注意,b、c可省略,a不可省略
def fuzhi(a, *b, **c):
print(a)
print(b)
print(c)
fuzhi(1,25,3,69,58,48,58)
運行結果:
1
(25, 3, 69, 58, 48, 58)
{}
實例2:
def fuzhi(a, *b, **c):
print(a)
print(b)
print(c)
fuzhi(1,25,3,69,58,48,58,name='lly',age=18,she='yrr')
運行結果:
1
(25, 3, 69, 58, 48, 58)
{'name': 'lly', 'age': 18, 'she': 'yrr'}
@匿名函數
python 使用 lambda 來創建匿名函數。
所謂匿名,意即不再使用 def 語句這樣標準的形式定義一個函數。
lambda 只是一個表達式,函數體比 def 簡單很多。
lambda的主體是一個表達式,而不是一個代碼塊。僅僅能在lambda表達式中封裝有限的邏輯進去。
lambda 函數擁有自己的命名空間,且不能訪問自己參數列表之外或全局命名空間裏的參數。
雖然lambda函數看起來只能寫一行,卻不等同於C或C++的內聯函數,後者的目的是調用小函數時不佔用棧內存從而增加運行效率。
語法:
lambda [arg1 [,arg2,…argn]]:expression
實例1:
# 可寫函數說明
sum = lambda arg1, arg2: arg1 + arg2
# 調用sum函數
print ("相加後的值爲 : ", sum( 10, 20 ))
print ("相加後的值爲 : ", sum( 20, 20 ))
運行:
相加後的值爲 : 30
相加後的值爲 : 40
實例2:
# 匿名函數:簡化函數定義
# 格式: lambda 參數1,參數2,。。:運算
s = lambda a, b: a + b
print(s(4, 4))
def func(x, y, func):
print(x, y)
print(func)
s = func(x, y)
print(s)
# 調用func
func(1, 2, lambda x, y: x + y)
list2=[{'a':13,'b':56},{'a':40,'b':49},{'a':50,'b':1}]
m=max(list2,key=lambda x:x['b']+x['a'])
print(m)
運行結果:
8
1 2
<function <lambda> at 0x00000228306BBB70>
3
{'a': 40, 'b': 49}
實例2:
# map
list1 = [1, 2, 4, 7, 8, 9, 6, 3]
result = map(lambda x: x + 2, list1)
print(list(result))
func = lambda x: x if x % 2 == 0 else x + 1
result = func(5)
print(result)
result = map(lambda x: x if x % 2 == 0 else x + 1, list1)
print(list(result))
# reduce(): 對列表中的元素進行加減乘除運算
from functools import reduce
tuple1 = (3, 4, 5, 6, 7, 8)
result = reduce(lambda x, y: x + y, tuple1)
print(result)
tuple2 = (4,)
result = reduce(lambda x, y: x + y, tuple2, 10)
print(result)
# 動手測試減法
list2 = [12, 3, 5, 56, 4, 23, 14, 19, 10, 9]
result = filter(lambda x: x > 10, list2)
print(list(result))
運行結果:
[3, 4, 6, 9, 10, 11, 8, 5]
6
[2, 2, 4, 8, 8, 10, 6, 4]
33
14
[12, 56, 23, 14, 19]
@閉包
閉包是函數式編程的一個重要的語法結構,函數式編程是一種編程範式 (而面向過程編程和麪向對象編程也都是編程範式)。在面向過程編程中,我們見到過函數(function);在面向對象編程中,我們見過對象(object)。函數和對象的根本目的是以某種邏輯方式組織代碼,並提高代碼的可重複使用性(reusability)。閉包也是一種組織代碼的結構,它同樣提高了代碼的可重複使用性。
不同編程語言實現閉包的方式是不同的,python中閉包從表現形式上看,如果在一個內部函數裏,對在外部作用域(但不是在全局作用域)的變量進行引用,那麼內部函數就被認爲是閉包(closure)。
例如:
def func(a, b):
c = 10
def inner_func():
s = a + b + c
print('相加後的結果是', s)
return inner_func
# 調用func
ifunc = func(6, 9)
ifunc1 = func(2, 8)
print(ifunc)
print(ifunc1)
ifunc()
ifunc1()
運行結果:
<function func.<locals>.inner_func at 0x000001A7FE08B840>
<function func.<locals>.inner_func at 0x000001A7FE08BBF8>
相加後的結果是 25
相加後的結果是 20
@裝飾器
裝飾器實際上就是爲了給某程序增添功能,但該程序已經上線或已經被使用,那麼就不能大批量的修改源代碼,這樣是不科學的也是不現實的,因爲就產生了裝飾器。
實例1:
import time
def decorate(func):
print('------------第一層--------------')
def wrapper(*args, **kwargs):
print('正在校驗中---------------')
time.sleep(2)
print('校驗完畢------------------')
func(*args, **kwargs)
print('###########下一步就是return了###############')
return wrapper
@decorate
def f1(n):
print('---------------f1----------------', n)
@decorate
def f2(name, age):
print('---------------f2----------------', name, age)
運行結果:
------------第一層--------------
###########下一步就是return了###############
------------第一層--------------
###########下一步就是return了###############
實例2:
import time
def decorate(func):
print('------------第一層--------------')
def wrapper(*args, **kwargs):
print('正在校驗中---------------')
time.sleep(2)
print('校驗完畢------------------')
func(*args, **kwargs)
print('###########下一步就是return了###############')
return wrapper
@decorate
def f1(n):
print('---------------f1----------------', n)
@decorate
def f2(name, age):
print('---------------f2----------------', name, age)
f1(4)
print(f1)
f2('lly', 18)
print(f2)
@decorate
def f3(student, clazz='1905'):
print('{}的學生如下: '.format(clazz))
for stu in student:
print(stu)
students = ['lly', 'llg', 'ffrf', 'yrr']
f3(students)
print(f3)
運行結果:
------------第一層--------------
###########下一步就是return了###############
------------第一層--------------
###########下一步就是return了###############
正在校驗中---------------
校驗完畢------------------
---------------f1---------------- 4
<function decorate.<locals>.wrapper at 0x000001C8F77ABAE8>
正在校驗中---------------
校驗完畢------------------
---------------f2---------------- lly 18
<function decorate.<locals>.wrapper at 0x000001C8F77ABD08>
------------第一層--------------
###########下一步就是return了###############
正在校驗中---------------
校驗完畢------------------
1905的學生如下:
lly
llg
ffrf
yrr
<function decorate.<locals>.wrapper at 0x000001C8F77ABE18>
注意:當有兩個裝飾器時,函數優先加載最近的裝飾器。