1. 程式人生 > >Python基礎筆記_Day07_函式引數傳遞、關鍵字引數、預設引數、匿名函式、裝飾器

Python基礎筆記_Day07_函式引數傳遞、關鍵字引數、預設引數、匿名函式、裝飾器

Day07_函式引數傳遞、關鍵字引數、預設引數、匿名函式、裝飾器

07.01_Python基礎語法(函式的引數的傳遞)(掌握)
07.02_Pythony語言基礎(關鍵字引數)(掌握)
07.03_Pythony語言基礎(預設引數/預設引數)(掌握)
07.04_Pythony語言基礎(不定長引數)(掌握)
07.05_Pythony語言基礎(匿名函式)(熟練)
07.06_Pythony語言基礎(匿名函式的應用場景)(熟練)
07.07_Pythony語言基礎(裝飾器的概述)(熟練)
07.08_Python語言基礎(裝飾器的應用場景)(掌握)
07.09_Python語言基礎(裝飾器的示例)(掌握)
07.10_Python語言基礎(作業)

07.01_Python語言基礎(函式的引數的傳遞)(掌握)

具體的細分:
可變物件和不可變物件(值傳遞,引用傳遞)

A: 不可變物件引數的傳遞

  • 不可變物件
    • 定義:表示該值不能發生變化
  • 不可變的資料型別
    • String tuple number(int,float,bool,complax)

"""
String
tuple
number
"""
def add(num):
    num = num + 10
    return num

d = 2
e = add(d)
print(d)#2
print(e)#12

def fun(num):
    print(id(num))
    num = 10
    print(id(num))
temp = 20
print(id(temp))
fun(temp)
print(temp)

"""

總結:
在python中,對於不可變物件,呼叫自身的任意函式,並不會改變物件自身的內容

B: 可變物件

  • 定義:
    • 值發生改變
  • 可變物件的資料型別有哪些?
    • list dict set

"""
list
dict
set
"""
#以列表為例
def change(num):
    num.append(1)
d = [0]

change(d)
print(d)

def fun(list):
    list[0] = 100

li = [1,2,3,4,5]
fun(li)
print(li)


a = 10
b = 10
b = 40
print(id(a),id(b))

c = 20
d = 30
print(id(c),id(d))

d = c
print(id(c),id(d))

總結:
在python中,對於可變物件,呼叫自身的任意函式,可能改變物件自身的內容,id不會改變

07.02_Pythony語言基礎(關鍵字引數)(掌握)

Python允許函式呼叫時引數順序和定義時不一致

def myPrint(str,age):
    print(str,age)

myPrint("zhangsan","18")
myPrint(age = 18,str = "張三")

#案例2:

   #關鍵字引數: **kw
def person(name,age,**kw):
    print("name:",name,"age:",age,"other:",kw)

person("zhangsan","12")
person("zhangsan",12,city = "北京")
person("張三",15,gender = "M",job = "engineer")

07.03_Pythony語言基礎(預設引數/預設引數)(掌握)

概述:
python為了簡化函式的呼叫,提供預設引數機制,呼叫函式時,預設引數的值如果沒有傳入,則會被認為是預設值

#定義一個函式
def printInfo(name,age = 35):
    print("name:",name)
    print("age:",age)

printInfo("張三")
printInfo(name = "張三")
printInfo(age = 18,name = "haha")

def pow(x ,n = 2):
    r = 1
    while n > 0:
        r *= x
        n -= 1
    return r   

p = pow(2)
print(p)

def printInfo1(name,sex = "nam",age = 35):
    print(name,sex,age)
    
printInfo1("張三","男")

注意:

#帶有預設值的引數一定要位於引數列表的最後面
#必選引數必須在前面
#設定何種引數為預設值,一般將引數值變化較小的設定為預設引數

07.04_Pythony語言基礎(不定長引數)(掌握)

概述:
一個函式能夠處理比當初宣告時更多的引數稱為不定長引數,宣告時一般不會命名

  • 格式:
    • def function(args,*args,**kwargs):

def function(args,*args,**kwargs):
加了一個*號的變數args會存放所有未命名的變數引數,相當於  元組
加了**號,存放所有命名的變數引數,相當於表示式  key  =  value   kwargs為字典

print("-" * 20)

# 經典方式
def fun(a, b, *args, **kwargs):
    print("a= ", a)
    print("b= ", b)
    print("args= ", args)
    print("kwargs= ", kwargs)
    print("*" * 30)
    for key, value in kwargs.items():
        print(key, "=", value)


fun(1, 2, 3, 4, 5, 6, 6, 8, 9, m=6, n=7, p=8)

# 另一種方式
c = (3, 4, 5)
d = {"m": 6, "n": 7, "p": 8}
print("_" * 50)
fun(1, 2, *c, **d)
print("_" * 50)
# 再一種方式
fun(1, 2, c, d)


def fun1(*args, **kwargs):
    print(args)
    print(kwargs)

# fun1(1, 2, 3, 4, m=5)

執行輸出結果:

--------------------
a=  1
b=  2
args=  (3, 4, 5, 6, 6, 8, 9)
kwargs=  {'m': 6, 'n': 7, 'p': 8}
******************************
m = 6
n = 7
p = 8
__________________________________________________
a=  1
b=  2
args=  (3, 4, 5)
kwargs=  {'m': 6, 'n': 7, 'p': 8}
******************************
m = 6
n = 7
p = 8
__________________________________________________
a=  1
b=  2
args=  ((3, 4, 5), {'m': 6, 'n': 7, 'p': 8})
kwargs=  {}
******************************

07.05_Python語言基礎(匿名函式)(掌握)

匿名函式概述

  • 定義:
    • 不使用def這樣語句來定義函式
    • 使用lambda來建立一個匿名函式
  • 原則:
    • 用lambda關鍵字能夠建立小型匿名函式,可以省略用def宣告函式的標準步驟
  • 格式:
    • lambda[args1,args2…]:expression

匿名函式的基本定義

a = 1
sum = lambda args1,args2:args1 + args2
print(sum(10,20))

特點:

1.lambda只是一個表示式,比函式def宣告簡單
2.lambda的主體也是一個表示式,而不是程式碼塊,只能在lambda表示式中封裝簡單的邏輯
3.lambda函式有總計的名稱空間,能訪問自由引數列表以外或者全域性名稱空間的引數
4.lambda函式能夠接受任何數量的引數,只能返回一個表示式的值

07.06_Pythony語言基礎(匿名函式的應用場景)(熟悉)

  • 作為自定義函式的引數進行傳遞
    • 類似呼叫函式中傳入的實參
  • 匿名函式的應用場景(作為自定義函式的引數進行傳遞)

def fun(a,b,opt):
    print(a)
    print(b)
    print(opt(10,20))
fun(1,2,lambda x,y:x + y)
  • 作為內建函式的引數
    • 字典儲存姓名和年齡的資料,把字典內的元素按照姓名或年齡排序

stus = [
{"name": "張三", "age": 18}, 
{"name": "李四", "age": 35}, 
{"name": "王五", "age": 22}]
stus.sort(key=lambda x: x["age"])
print(stus)

07.07_Pythony語言基礎(裝飾器的概述)(熟悉)

  • 裝飾器的基本格式

    • @函式名
  • 定義:是一個閉包,把一個函式當作引數,

    • python裝飾器就是用於拓展原來函式功能的一種函式,這個函式的特殊之處在於它的返回值也是一個函式,
    • 使用python裝飾器的好處就是在不用更改原函式的程式碼前提下給函式增加新的功能。
    • 一般而言,我們要想拓展原來函式程式碼,最直接的辦法就是侵入程式碼裡面修改,
      例如:

import time
def func():
    print("hello")
    time.sleep(1)
    print("world")

這是我們最原始的的一個函式,然後我們試圖記錄下這個函式執行的總時間,那最簡單的做法就是:
#原始侵入,篡改原函式
import time
def func():
    startTime = time.time()

    print("hello")
    time.sleep(1)
    print("world")
    endTime = time.time()

    msecs = (endTime - startTime)*1000
    print("time is %d ms" %msecs)


但是如果你的Boss在公司裡面和你說:“小祁,這段程式碼是我們公司的核心程式碼,
你不能直接去改我們的核心程式碼。”那該怎麼辦呢,我們仿照裝飾器先自己試著寫一下:
#避免直接侵入原函式修改,但是生效需要再次執行函式
import time

def deco(func):
    startTime = time.time()
    func()
    endTime = time.time()
    msecs = (endTime - startTime)*1000
    print("time is %d ms" %msecs)


def func():
    print("hello")
    time.sleep(1)
    print("world")

if __name__ == '__main__':
    f = func
    deco(f)#只有把func()或者f()作為引數執行,新加入功能才會生效
    print("f.__name__ is",f.__name__)#f的name就是func()
    print()
    #func()

這裡我們定義了一個函式deco,它的引數是一個函式,然後給這個函式嵌入了計時功能。
然後你可以拍著胸脯對老闆說,看吧,不用動你原來的程式碼,我照樣拓展了它的函式功能。 
然後你的老闆有對你說:“小祁,我們公司核心程式碼區域有一千萬個func()函式,從func01()
到func1kw(),按你的方案,想要拓展這一千萬個函式功能,就是要執行一千萬次deco()函式,
這可不行呀,我心疼我的機器。” 
好了,你終於受夠你老闆了,準備辭職了,然後你無意間聽到了裝飾器這個神器,
突然發現能滿足你老闆的要求了。 
我們先實現一個最簡陋的裝飾器,不使用任何語法糖和高階語法,看看裝飾器最原始的面貌

#既不需要侵入,也不需要函式重複執行
import time

def deco(func):
    def wrapper():
        startTime = time.time()
        func()
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
    return wrapper


@deco
def func():
    print("hello")
    time.sleep(1)
    print("world")

if __name__ == '__main__':
    f = func #這裡f被賦值為func,執行f()就是執行func()
    f()


這裡的deco函式就是最原始的裝飾器,它的引數是一個函式,然後返回值也是一個函式。
其中作為引數的這個函式func()就在返回函式wrapper()的內部執行。
然後在函式func()前面加上@deco,func()函式就相當於被注入了計時功能,現在只要呼叫func(),
它就已經變身為“新的功能更所以這裡裝飾器就像一個注入符號多”的函數了。 
:有了它,拓展了原來函式的功能既不需要侵入函式內更改程式碼,
也不需要重複執行原函式。


#帶有引數的裝飾器
import time
def deco(func):
    def wrapper(a,b):
        startTime = time.time()
        func(a,b)
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
    return wrapper


@deco
def func(a,b):
    print("hello,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b))

if __name__ == '__main__':
    f = func
    f(3,4)
    #func()

然後你滿足了Boss的要求後,Boss又說:“小祁,我讓你拓展的函式好多可是有引數的呀,
有的引數還是個數不定的那種,你的裝飾器搞的定不?”然後你嘿嘿一笑,深藏功與名!


#帶有不定引數的裝飾器
import time

def deco(func):
    def wrapper(*args, **kwargs):
        startTime = time.time()
        func(*args, **kwargs)
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
    return wrapper


@deco
def func(a,b):
    print("hello,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b))

@deco
def func2(a,b,c):
    print("hello,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b+c))


if __name__ == '__main__':
    f = func
    func2(3,4,5)
    f(3,4)
    #func()

07.08_Python語言基礎(裝飾器的應用場景)(掌握)

1.引入日誌
2.函式的執行時間統計
3.執行函式前的預備處理
4.函式執行後的清理工作
5.許可權的校驗
6.快取

07.09_Python語言基礎(裝飾器的示例)(掌握)

from time import ctime, sleep
無引數的函式

def timeFun(func):
    def wrapped():
        print("%s called at %s" % (func.__name__, ctime()))
        func()

    return wrapped


@timeFun
def foo():
    print("i am foo")


# foo()
# sleep(2)
# foo()

f = timeFun(foo)
f()

#被裝飾的函式有引數

def timeFun(func):
    def wrapped(a, b):
        print("%s called at %s" % (func.__name__, ctime()))
        func(a, b)

    return wrapped


@timeFun
def foo(a, b):
    print(a + b)


foo(3, 5)

sleep(2)
foo(2, 4)


# 3.被修飾的函式有不定長引數
def timeFun(func):
    def wrapped(*args, **kwargs):
        print("%s called at %s" % (func.__name__, ctime()))
        func(*args, **kwargs)

    return wrapped


@timeFun
def foo(a, b, c):
    print(a + b + c)


foo(3, 5, 7)

#裝飾器中的return
def timeFun(func):
    def wrapped():
        print("%s called at %s" % (func.__name__, ctime()))
        func()
    return wrapped
@timeFun
def foo():
    print("i am foo")
@timeFun
def getInfo():
    return "---haha----"


foo()
print(getInfo())

07.10_Python語言基礎(作業)

1.用函式編寫計算器,要求可以計算多個值的加減乘除
多個值的加減乘除,應當使用不定長引數,
可以設定關鍵字引數的**kwargs部分表達符號

2.編寫“商品管理系統”,要求如下:
必須使用自定義函式,完成對程式的模組化
學生資訊至少包含:商品、日期、物流碼,除此以外可以適當新增
必須完成的功能:新增、刪除、修改、查詢(單個查詢/顯示所有)、退出