各種類型函數講解以及裝飾器

@函數的定義

以下是簡單的規則:
函數代碼塊以 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>

注意:當有兩個裝飾器時,函數優先加載最近的裝飾器。

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