python之函數


第一章 函數介紹

函數的好處:
1.減少代碼重復性 (冗余)
2.代碼可讀性高
3.將功能進行封裝(造工具)

def 關鍵字 ---定義函數

func 函數名 ---和變量規則一樣

()
聲明語句結束
def my_len():
    函數體

第二章 函數調用

my_len() 函數名 + ()

def my_len():
  a = "123dsb"
  count = 0
  for i in a:
      count += 1
  print(count)

my_len()  # 函數的調用

第三章 函數的返回值

def num():
    print(1)
    print(2)
    return  "123","321"  #返回的是元組
    print(3)

num()
print(num())

return 的內容返回給函數的調用

遇到return,此函數結束,return下面的代碼將不會在執行

return 返回多個內容的時候是元組,調用者可以直接使用解構獲取多個變量

return不能終止循環,只能終止函數

return沒寫返回值,或者干脆就沒寫return,返回的結果都是是None

第四章 函數的參數

參數,也就是函數括號里的內容 函數在調用的時候指定一個具體的變量的值 就是參數

def 函數名(參數):

    函數體

形參: 函數定義()里的參數

1. 可用位置參數  默認參數 混合參數

實參: 函數調用()里的就是實參

1. 位置參數 關鍵字參數  混合參數

傳參:將實參傳遞給形參的過程

位置傳參時:::::::::實參要與形參一一對應

1.位置參數

def yue(chat):    # chat  形參   

    print("拿出手機")   

    print("打開"+chat)   

    print("找個漂亮的妹子")   

    print("約不約")

yue("陌陌")     # "陌陌"在這里就是實參

2.默認參數

姓名,性別,年齡
def userinfo(name,age,sex="男"):  # 位置參數 > 默認參數
    print(name,sex,age)

count = 5
while count:
    name = input("name:")
    sex = input("sex(男性直接回車!):")
    age = input("age:")
    if sex == "女":
        userinfo(name,age,sex)
    else:
        userinfo(name, age)
    count -= 1

3.關鍵字參數

def func(a,c,b=1): # a,c位置參數 ,b=1 是默認參數
    print(a,b,c)

func(a=1,b=5,c=2) # a=1,b=5,c=2 是關鍵字參數

def func(a,b,c):
    print(a,b,c)
func(1,2,c=5) # 混合參數

第五章 三元運算符,枚舉

lst =[1,2,3]
def func(b):
    return "da" if len(b)>5 else "xiaoyu"
print(fun(lst))

變量 = 條件成立的結果 條件判斷 條件不成立 #####只適用於2個參數

def  dunc():
    lst =[11,22,33]
    dic={}
    for k,v in enumerate(lst,10):  從第十個開始 默認為0
        dic[k]=v
    return dic

第六章 形參的動態函數

1.*args(動態位置參數)

def func(a,b,*args):  #可以接收多個位置參數 可以解說多個 *在定義函數的時候叫做聚合
	print(a,b,args)  #返回的是元組
    #print(a,b,*args)    * 打散  
  
func(1,2,3,4,5)  

######位置參數>動態位置參數>默認參數
def func (*args,a=1,b=2) 

2.**kwargs(動態關鍵字參數)

def func(a,b,**kwargs):
    print(a,b,kwargs) #返回字典
    #print(a,b,*kwargs) #拿到的是key
  
func(1,2,c=1,d=2)
#1 2 {'c': 1, 'd': 2}
#1 2 c d

3.參數優先級

######位置參數>動態位置參數>默認參數>動態關鍵字參數
def func(a,b,*args,c=1,d=2,**kwargs):
    print(a,b,args,c,d,kwargs,)
func(1,2,5,4,6,c=3,d=4,e="123",f="22")
#1 2 (5, 4, 6) 3 4 {'e': '123', 'f': '22'}

4.萬能參數

#萬能傳參,可以接受所有的
def func(*args,**kwargs): 
    print(args,kwargs,)
func(1,2,5,4,6,a=1,b=2,c=3)
#(1, 2, 5, 4, 6) {'a': 1, 'b': 2, 'c': 3}
字典和列表打散傳入
func(*[1,2,3,4],*[12,2,2,2,2,2],**{1:2,2:3})

5.形參的第四章傳參方式,僅限關鍵字參數

# 
def fun(a,*args,sex="男",c,**kwargs):
    print(a)
    print(args)
    print(sex)
    print(c)
    print(kwargs)
fun(1,3,2,c=4,name="zbb")

第七章 函數的注釋

def func1(user,password):
    """
    密碼加密
    :param user: 用戶名 str
    :param password: 密碼 str
    :return: 加密的密碼 MD5
    """
    print(user,password)

print(func1.__doc__)

print(func1.__name__)

第八章 名稱空間

1.名稱空間分類:

  1. 全局空間--> 我們直接在py文件中, 函數外聲明的變量都屬於全局命名空間
  2. 局部空間--> 在函數中聲明的變量會放在局部命名空間
  3. 內置空間--> 存放python解釋器為我們提供的名字, list, tuple, str, int這些都是內置命名空間

2.加載順序

內置 > 全局空間 >局部空間

取值順序

局部空間 > 全局空間 >內置

都沒有就報錯

3,作用域

作用域就是作用范圍, 按照生效范圍來看分為 全局作用域 和 局部作用域

  1. 全局作用域: 全局命名空間 + 內置命名空間
  2. 局部作用域: 局部命名空間

第九章 函數的嵌套

不管在什么位置,只要是函數名+() 就是在調用此函數

函數調用執行后,函數體中開辟的空間就自動銷毀了

def func():
    print(1)
    def f1():
        print(2)
    return f1()
print(func())


1.函數互相引用

def func():
    a = 1
    foo()
    print(a)

def foo():
    b = 2
    print(b)
func()

2.global

作用1:在局部作用域中可以更改全局作用域的變量

a=1
def func():
    global a  # 聲明修改全局變量的值
    a += 1    
func()
print(a)

global在局部作用域也可以聲明一個全局變量。

def func():
    global a
    a = 3
func()
print(a)

3.nonlocal

nonlocal是python3x新加的功能,與global用法差不多,就是在局部作用域如果想對父級作用域的變量進行改變時,需要用到nonlocal,當然這個用的不是很多,了解即可。

def add_b():
    b = 42
    def do_global():
        b = 10
        print(b)
        def dd_nonlocal():
            nonlocal b
            b = b + 20
            print(b)
        dd_nonlocal()
        print(b)
    do_global()
    print(b)
add_b()

nonlocal :在外層的函數中,修改局部空間的變量值.完全不涉及全局變量,
只修改離它最近的一層,最近的一層沒有變量繼續向上找,直到找到最外層函數

第十章函數名的使用

函數名是一個變量, 但它是一個特殊的變量, 與括號配合可以執行函數的變量

1.函數名的內存地址

def func():   
    print("呵呵")
print(func)

結果: <function func at 0x1101e4ea0>

2.函數名可以直接賦值給其他變量

def func():   
    print("呵呵")
    print(func)
a = func    # 把函數當成一個值賦值給另一個變量

a()     # 函數調用 func()

3.函數名可以當做容器類的元素

def func1():   
    print("呵呵")
def func2():   
    print("呵呵")
def func3():   
    print("呵呵")
def func4():  
     print("呵呵")

lst = [func1, func2, func3]
for i in lst:  
     i()

4.函數名可以當做函數的參數

def func():   
    print("吃了么")
def func2(fn):   
    print("我是func2")   
    fn()    # 執行傳遞過來的fn   
    print("我是func2")
func2(func)     # 把函數func當成參數傳遞給func2的參數fn

5.函數名可以當做函數的返回值

def func_1():   
    print("這里是函數1")   
    def func_2():       
        print("這里是函數2")   
    print("這里是函數1")   
    return func_2
fn = func_1()  
# 執行函數1.  函數1返回的是函數2, 這時fn指向的就是上面函數2
fn()    # 執行func_2函數

6.函數形參可變類型的坑

def extendList(val,list=[]):
    list.append(val)
    return list
print('list1=%s'% extendList(10))
print('list2=%s'% extendList(123,[]))
print('list3=%s'% extendList('a'))
#一步一步的執行,結果可想
#list1=[10]   
#list2=[123]
#list3=[10, 'a']

def extendList(val,list=[]):
    list.append(val)
    return list

list1 = extendList(10)  #執行了
list2 = extendList(123,[])#執行了
list3 = extendList('a')#執行了

print('list1=%s'%list1)
print('list2=%s'%list2)
print('list3=%s'%list3)


#是先執行完所有的 才打印
list1=[10, 'a']
list2=[123]
list3=[10, 'a']

第十一章 f-string字符串格式化

f-strings 是python3.6開始加入標准庫的格式化輸出新的寫法,這個格式化輸出比之前的%s 或者 format 效率高並且更加簡化

1.舉例用法

s= f"我是{'張'}"  #填充字符串
print(s)

# s1 =f"你好{s}" #填充變量
# print(s1)


# s1 = f"{12+13}" #填充計算公式
# print(s1)
# a=10
# b=20
# s1 =f"{a if a>b else b}"  #填充表達式
# print(s1)


print(f"{{73}}")  # {73}
print(f"{{{73}}}")  # {73}
print(f"{{{{73}}}}")  # {{73}}
m = 21
# ! , : { } ;這些標點不能出現在{} 這里面。
# print(f'{;12}')  # 報錯
# 所以使用lambda 表達式會出現一些問題。
# 解決方式:可將lambda嵌套在圓括號里面解決此問題。
x = 5
print(f'{(lambda x: x*2) (x)}')  # 10

第十二章 迭代器

1.什么叫迭代?

迭代就是一個重復的過程,每次重復都是基於上一次的結果而來

我們接觸到的可迭代對象有

str list tuple dic set range 文件句柄等,int,bool這些不能稱為可迭代對象

2.查看對象內部方法

查看是否有str.iter__

s1 = 'alex'
print(dir(s1))
#['__add__', '__class__', ' '__iter__', '__le_,.......]
print('__iter__' in dir(s1))  # True

3.優缺點

優點:

1. 使用靈活

  1. 可以直觀的查看里面的數據

缺點:

1.占用內存。

2.可迭代對象不能迭代取值(除去索引,key以外)

2.什么叫迭代器

在python中,內部含有__Iter__方法並且含有__next__方法的對象就是迭代器

f = open('file',encoding='utf-8', mode='w')
print('__iter__' in dir("123"))  # True
print('__next__' in dir("123")  # False

1.可迭代對象如何轉化成迭代器:

l1 = [1, 2, 3, 4, 5, 6]
obj = l1.__iter__()
# <list_iterator object at 0x000002057FE1A3C8>
# 或
obj = iter(l1)
print(obj)
# <list_iterator object at 0x102cc67f0>

2.迭代器取值

可迭代對象是不可以一直迭代取值的(除去用索引,切片以及Key),但是轉化成迭代器就可以了,迭代器是利用__next__()進行取值:

l1 = [1, 2, 3,]
obj = l1.__iter__()  # 或者 iter(l1)
# print(obj)  # <list_iterator object at 0x000002057FE1A3C8>
ret = obj.__next__()  
print(ret)  #1
ret = obj.__next__()
print(ret)  #2

3.while模擬for的內部循環機制:

#這是假的
s = "121234"
count = len(s)
new_s=iter(s)
while count:
    print(next(new_s))
    count -=1

#異常捕獲,不會報錯
s = "1234"
new_s=iter(s)
while True:
    try:
        print(next(new_s))
    except StopIteration:
        break


#不寫下面的        
    except Exception:
        print("是萬能的")
        break

4.優點缺點

優點:

  1. 節省內存。 惰性機制
  2. 迭代器在內存中相當於只占一個數據的空間:因為每次取值都上一條數據會在內存釋放,加載當前的此條數據。

缺點:

  1. 一次性的
  2. 不能直觀的查看里面的數據。
  3. 取值時不走回頭路,只能一直向下取值。
l1 = [1, 2, 3, 4, 5, 6]
obj = iter(l1)

for i in range(2):
    print(next(obj))  # 1,2

for i in range(2):
    print(next(obj))  #3,4


5.總結

應用:當你的數據量過大,大到足以撐爆你的內存或者你以節省內存為首選因素時,將數據集設置為迭代器是一個不錯的選擇。

第十二章 遞歸

  1. 自己調用自己
  2. 有明確的終止條件

滿足以上條件才是遞歸

遞:

​ 一直執行到結束條件

def func():
    print(123)
    func()

func()

第十三章 生成器

**生成器的本質就是迭代器 **

迭代器都是(內置的)

Python給你提供的已經寫好的工具或者通過數據轉化得來的,(比如文件句柄,iter([1,2,3])。

生成器是需要我們自己用python代碼構建的工具。

1.生成器的創建方式

在python中有三種方式來創建生成器:

  1. 通過生成器函數
  2. 通過生成器推導式
  3. python內置函數或者模塊提供(其實1,3兩種本質上差不多,都是通過函數的形式生成,只不過1是自己寫的生成器函數,3是python提供的生成器函數而已

2.生成器函數

def func():
    print(11)
    return 22
ret = func()
print(ret)
# 運行結果:
11
22

將函數中的return換成yield,這樣func就不是函數了,而是一個生成器函數

def func():
    print(11)
    yield 22
print(func()) #產生生成器
#yield 也是返回

def func():
    print(11)
    yield 22

a=func()  #只是產生了生成器
print(a.__next__())  #這才是調用
#11
# 22

yield會記錄執行位置

一個 yield 對應一個__next__()

next超過yield數量,就會報錯,與迭代器一樣。

def func():
    # print(11)
    yield 22
    yield   44

a=func()
print(a.__next__())
print(a.__next__())

def  zz():
    if 3>2:
        yield 11
    if 2<3:
        yield 22
    yield  33

a=zz()
print(a.__next__())
print(a.__next__())
print(a.__next__())

3.yield與return的區別:

return 可以寫多個但是只執行一次,占用內存。

yield可以寫多個執行多次,非常的節省內存,而且還可以保留上次的位置。

yield 可以將循環 臨時暫停

4.yield from

在把可迭代對象中的每一個數據作為生成器的結果挨個返回

# 對比yield 與 yield from 
def func():
    lst = ['衛龍','老冰棍','北冰洋','牛羊配']
    yield lst
g = func()
print(g)
print(next(g))  # 只是返回一個列表
​
def func():
    lst = ['衛龍','老冰棍','北冰洋','牛羊配']
    yield from lst
g = func()
print(g)
# 他會將這個可迭代對象(列表)的每個元素當成迭代器的每個結果進行返回。
print(next(g))
print(next(g))
print(next(g))
print(next(g))
'''
yield from ['衛龍','老冰棍','北冰洋','牛羊配'] 
等同於:
    yield '衛龍'
    yield '老冰棍'
    yield '北冰洋'
    yield '牛羊配'

小坑

返回的結果是將第一個列表的元素全部返回后,在返回第二個列表

def func():
    lst1 = ['衛龍', '老冰棍', '北冰洋', '牛羊配']
    lst2 = ['饅頭', '花卷', '豆包', '大餅']
    yield from lst1
    yield from lst2


g = func()
for i in g:
    print(i)

# 在函數中將return改寫成yield就是一個生成器
# yield 會記錄執行位置
# return 和 yield 都是返回,
# return 可以寫多個,但是只執行一次,yield可以寫多個,還可以返回多次
# 一個__next__() 對應 一個yield
# 生成器可以使用for循環獲取值
# yield from -- 將可迭代對象元素逐個返回
# 在函數的內部 yield 能將for循環和while循環進行臨時暫停

第十四章 推導式

1.列表推導式

1.循環模式:[變量(加工的變量) for 變量 in iterable]

2.篩選模式: [變量(加工的變量) for 變量 in iterable if 條件]

li = []
for i in range(10):
    li.append(i)
print(li)  

循環模式

#升級版本推導式  
print([i  for i in range(20)])

篩選模式

print([i  for i in range(20) if i  %2 == 0])

2.生成器表達式

循環模式

g = (i for i  in range(20))
print(next(g))
print(next(g))

print(list((i for i in range(20))) #轉變為列表

篩選模式

g = (i for i  in range(20) if i %2 ==1)
for i in g:
    print(i)

3.字典推導式

print({i:i+1 for i in range(10)})
print({i:i+1 for i in range(10) if i % 2 == 0})
#{鍵:值 for循環 加工條件}

4.集合推導式

print({i for i in range(10)})
print({i for i in range(10) if i % 2 == 0})

第十五章 內置函數一(了解)

eval:執行字符串類型的代碼,並返回最終結果。千萬不能使用

eval('2 + 2')  # 4

exec:執行字符串類型的代碼。 千萬不能使用

for i in [1,2,3]:
    print(i)
'''
exec(s)   
1
2
3

hash:獲取一個對象(可哈希對象:int,str,Bool,tuple)的哈希值。

print(hash(12322))
print(hash('123'))
print(hash('arg'))
print(hash('alex'))
print(hash(True))
print(hash(False))
print(hash((1,2,3)))
#判斷時候哈希

help:函數用於查看函數或模塊用途的詳細說明。

print(help(list))
print(help(str.split))

callable:函數用於檢查一個對象是否是可調用的。如果返回True,仍然可能調用失敗;但如果返回False,調用對象ojbect絕對不會成功。

name = 'alex'
def func():
    pass
print(callable(name))  # False
print(callable(func))  # True

int:函數用於將一個字符串或數字轉換為整型。

print(int())  # 0
print(int('12'))  # 12
print(int(3.6))  # 3
print(int('0100',base=2))  # 將2進制的 0100 轉化成十進制。結果為 4

float:函數用於將整數和字符串轉換成浮點數。

complex:函數用於創建一個值為 real + imag * j 的復數或者轉化一個字符串或數為復數。如果第一個參數為字符串,則不需要指定第二個參數。。

print(float(3))  # 3.0
print(complex(1,2))  # (1+2j)

bin:將十進制轉換成二進制並返回。

oct:將十進制轉化成八進制字符串並返回。

hex:將十進制轉化成十六進制字符串並返回。

print(bin(10),type(bin(10)))  # 0b1010 <class 'str'>
print(oct(10),type(oct(10)))  # 0o12 <class 'str'>
print(hex(10),type(hex(10)))  # 0xa <class 'str'>

divmod:計算除數與被除數的結果,返回一個包含商和余數的元組(a // b, a % b)。

round:保留浮點數的小數位數,默認保留整數。

pow:求xy次冪。(三個參數為xy的結果對z取余)

print(divmod(7,2))  # (3, 1)
print(round(7/3,2))  # 2.33
print(round(7/3))  # 2
print(round(3.32567,3))  # 3.326
print(pow(2,3))  # 兩個參數為2**3次冪
print(pow(2,3,3))  # 三個參數為2**3次冪,對3取余。

bytes:用於不同編碼之間的轉化。

# s = '你好'
# bs = s.encode('utf-8')
# print(bs)
# s1 = bs.decode('utf-8')
# print(s1)
# bs = bytes(s,encoding='utf-8')
# print(bs)
# b = '你好'.encode('gbk')
# b1 = b.decode('gbk')
# print(b1.encode('utf-8'))

ord:輸入字符找當前字符編碼的位置

chr:輸入當前編碼的位置數字找出其對應的字符

# ord 輸入字符找該字符編碼的位置
# print(ord('a'))
# print(ord('中'))

# chr 輸入位置數字找出其對應的字符
# print(chr(97))
# print(chr(20013))

repr:返回一個對象的string形式(原形畢露)。

# %r  原封不動的寫出來
# name = 'taibai'
# print('我叫%r'%name)

# repr 原形畢露
print(repr('{"name":"alex"}'))
print('{"name":"alex"}')

all:可迭代對象中,全都是True才是True

any:可迭代對象中,有一個True 就是True

# all  可迭代對象中,全都是True才是True
# any  可迭代對象中,有一個True 就是True
# print(all([1,2,True,0]))
# print(any([1,'',0]))

print(globals()) 查看全局的變量

print(nonlobals()) 查看局部的

第十六章 內置函數二

高階函數:內置函數中還可以套函數的函數

常見高階函數:sorted()、filter()、map()、max()、min()、reduce()

1.abs() #絕對值

返回的都是正數

2.enumerate --枚舉

可迭代對象","序號的起始值" # 默認的起始值是0

lst =[1,2,3,4,5]

print([ i  for i in enumerate(lst)])
#[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)] 

print(dict([i for i in enumerate(range(20),1)]))

3.max 求最大值

print(max("123")) #可以列表等

4.min 最小值

print(min("123"))

5.sum 求和

print(sum([1,2,3,10],100))

6.print()

#更換鏈接符
print(1,2,3,4,sep="*")
#1*2*3*4

print(1,end='\t')
print(1,end="")
print(1)
#1	11

#項文件中添加
print(12345,file=open("1.txt","w",encoding="utf-8"))

print(dict(key=1,a="alex")) #字典的一種寫法

7.zip() 拉鏈

按照最少的進行合並

lst1 =[1,2,3,4,5]
lst2=['a',"w","q","a","b","qwe"]
print(list(zip(lst1,lst2)))
print(dict(list(zip(lst1,lst2))))  #面試題

第十七章 匿名函數

1.匿名函數

lambda 是一行函數

形參可以不寫

返回值必須要寫

f=lambda x,y:x+y
print(f(1,2))
print(f.__name__) #查看函數的名字
# lambda #關鍵字 ---定義函數  就是函數名
# x,y   形參
# x+y  返回值   只能返回一個數據類型

一行調用

print((lambda x,y:x+y)(1,2))

lst =list((lambda i:i*i for i in range(6)))
print(lst[2](3))

lst =list((lambda :i*i for i in range(6)))
print(lst[2]())

第十八章 重要內置函數

1.format

print(format(13,">20"))  #右對齊
print(format(13,"<20"))  #左對齊
print(format(13,"^0"))  #左對齊

print(format(13,"b"))  #2
print(format(13,"d"))  #10
print(format(13,"o"))   #8
print(format(13,"x"))  #16

2.filter過濾

lst =[1,2,3,4,5]
def fun(s):
    return s>3

print(list(filter(fun,lst)))
#fun  過濾條件  lst迭代對象
print(list(filter(lambda x:x,lst)))

3.map()對象映射

print(list(map(lambda x:x+1,[1,2,3,4])))
#對可迭代對象中每個元素進行加工

4.翻轉

lst = [1,2,3,4,5]
lst.reverse()
print(lst)

lst1 = list(reversed(lst))
print(lst)
print(lst1)

5.排序sorted

升序

lst = [1,23,34,4,5,213,123,41,12,32,1]
print(sorted(lst))   # 升序
print(lst)

降序

lst = [1,23,34,4,5,213,123,41,12,32,1]
print(sorted(lst,reverse=True))  # 降序

key

dic = {"key":1,"key1":2,"key3":56}
print(sorted(dic,key=lambda x:dic[x],reverse=True))  # key是指定排序規則

print(max([1,2,-33,4,5],key=abs))  # 按照絕對值的大小,返回此序列最小值

6.累計算reduce

累計算

from functools import reduce
# reduce 累計算
print(reduce(lambda x,y:x-y,[1,2,3,4,5]))

第十九章 閉包

1.在嵌套函數中,使用非全局變量 且不是本層的 就是閉包

閉包的作用,保證數據的安全性

例子:

def func():
    a = 1
    def f1():
        def foo():
            print(a)
        return foo
    return f1
# ret = func()
# a = ret()
# a()

func()()()

def func():
    avg_lst = []  # 自由變量
    def foo(pirce):
        avg_lst.append(pirce)
        avg = sum(avg_lst) / len(avg_lst)
        return avg
    return foo
ret = func()

print(ret(150000))
print(ret(160000))
print(ret(170000))
print(ret(150000))
print(ret(180000))
print(ret.__closure__)  #判斷是否是閉包

閉包的作用:
1.  保證數據的安全性
2.  裝飾器

了解:
print(ret.__code__.co_freevars)  # 獲取的是自由變量
print(ret.__code__.co_varnames)  # 獲取的是局部變量

第二十章 裝飾器

作用在不修改源碼及調用方式前提下額外增加一些功能

1.開放原則

1.對擴展是開放的 : 增加新功能

2.對修改是封閉的(修改已經實現的功能)

版本一

測試此函數的執行效率

3.語法

語法糖 -- 甜語法糖必須放在被裝飾的函數正上方

標准版(裝飾器):
def func(a):  #a是要被裝飾的函數名
    def foo(*args,**kwargs):
        "裝飾之前的操作"
        ret = a(*args,**kwargs)
        "裝飾之后的操作"
        return ret
    return foo
@func
def f1(*args,**kwargs):
    print(f"這是一個{args}")
    return "我可以返回了"
f1(1,2,3,34,4,5)

版本low

import  time
def times(fu):
    def  inner():
        start_time=time.time()
        fu()
        print(time.time() - start_time)
    return inner

def foo():
    time.sleep(3)
    print(12324)

foo = times(foo)
foo()

版本高級

# 高級
import time
def wrapper(f):
    def inner(*args,**kwargs):
        "被裝飾前"
        start_time = time.time()
        f(*args,**kwargs) # func("alex")
        print(time.time() - start_time)
        "被裝飾后"
    return inner  # 切記不要加括號

@wrapper  # foo = wrapper(foo)
def foo(*args,**kwargs):
    print(f"這是{args}函數")
    time.sleep(3) #模擬網絡延時
# foo = wrapper(foo)
foo("al","su")

第二十一章 帶參數的裝飾器

裝飾器其實就是一個閉包函數,再說簡單點就是兩層的函數

舉例

./

def auth(argv):
    def wrapper(func):
        def inner(*args,**kwargs):
            func(*args,**kwargs)
        return inner
    return wrapper

login_dic={
    "flag":False,
    "username":None
}

def auth(argv):
    def wrapper(func):
        def inner(*args,**kwargs):
            if login_dic["flag"]:
                func(*args,**kwargs)
            else:
                if argv == "QQ":
                    print("歡迎登陸QQ")
                    user = input("username")
                    pwd = input("password")
                    if user == "zbb" and pwd=="zbb123":
                        login_dic["flag"] =True
                        login_dic["username"]=user
                        func(*args,**kwargs)
                    else:
                        print("用戶名,密碼")
        return inner
    return wrapper

@auth("QQ")
def foo():
    print("qq登錄")

# wrapper = auth("QQ")
# foo = wrapper(foo)
foo()

第二十二章 多個裝飾器裝飾一個參數

def wrapper1(func):
    def inner1(*args,**kwargs):
        print(1)
        func(*args,**kwargs)
        print(11)
    return inner1

def wrapper2(func):  # func == foo
    def inner2(*args,**kwargs):
        func(*args, **kwargs)
        print(22)
    return inner2

def wrapper3(func):
    def inner3(*args,**kwargs):
        print(3)
        func(*args, **kwargs)
        print(33)
    return inner3
@wrapper1  # 1 11
@wrapper3  # 3 33
@wrapper2  #  8 22

def foo():
    print(8)

# foo = wrapper2(foo)  # foo == inner2
# foo = wrapper3(foo)  # inner3 = wrapper3(inner2)
# foo = wrapper1(foo)  # inner1 = wrapper1(inner3)
foo()   



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM