python基礎之 裝飾器,內置函數

1.閉包回顧html

在學習裝飾器以前,能夠先複習一下什麼是閉包?
  在嵌套函數內部的函數可使用外部變量(非全局變量)叫作閉包!
def wrapper():
    money =10
    def inner(num):
        nonlocal money
        money +=num
        print(money)
    print(inner.__closure__)  #不返回none的話就是閉包
    return inner
wrapper()(100)
裝飾器的本質就是閉包

 2.裝飾器python

裝飾器本質上就是一個python函數,他可讓其餘函數在不須要作任何代碼變更的前提下,增長額外的功能,裝飾器的返回值也是一個函數對象。
裝飾器的應用場景:好比插入日誌,性能測試,事務處理,緩存等等場景。
#簡單的裝飾器
def func():
    print('嘻嘻更健康')
def timmer(f):
    def inner():
        start_time = time.time()
        time.sleep(0.1)
        f()
        end_time = time.time()
        print('----> 執行效率%s' % (end_time - start_time))
    return inner
func = timmer(func)  # inner
func() # inner()
這是最簡單的裝飾器,裝飾任何函數,只須要加一句func = timmer(func)

 3.裝飾器語法糖緩存

import time
def timer(func):
    def inner():
        start = time.time()
        func()
        print(time.time() - start)
    return inner

@timer  等價於func1 = timer(func1),@timer會先拿到下面函數的名字,而後把拿到名字的函數傳給timer裝飾器函數 def func1():
    print('in func1')
func1()
def timer(func):
    def inner(a):
        start = time.time()
        func(a)
        print(time.time() - start)
    return inner

@timer
def func1(a):
    print(a)

func1(1)
裝飾器——帶參數的裝飾器
import time
def timer(func):
    def inner(*args,**kwargs):
        start = time.time()
        re = func(*args,**kwargs)
        print(time.time() - start)
        return re
    return inner

@timer   #==> func1 = timer(func1)
def func1(a,b):
    print('in func1')

@timer   #==> func2 = timer(func2)
def func2(a):
    print('in func2 and get a:%s'%(a))
    return 'fun2 over'

func1('aaaaaa','bbbbbb')
print(func2('aaaaaa'))
裝飾器——hold帶參數的裝飾器

上面的裝飾器已經很是完美了,可是有咱們正常狀況下查看函數信息的方法在此處都會失效:閉包

from functools import wraps
def deco(func):
    @wraps(func) #加在最內層函數正上方,顯示被裝飾的函數
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper
@deco
def index():
    '''哈哈哈哈'''
    print('from index')

print(index.__doc__)   #顯示被裝飾函數的註釋
print(index.__name__)  #顯示被裝飾的函數名

4.開放封閉原則app

開放對擴展代碼--->新添加的功能
封閉修改源代碼--->不要修改源代碼
改變了人家調用方式---->不能改變其原有的調用方式

5.帶參數的裝飾器ide

假如你有成千上萬個函數使用了一個裝飾器,如今你想把這些裝飾器都取消掉,你要怎麼作?
一個一個的取消掉? 沒日沒夜忙活3天。。。
過兩天你領導想通了,再讓你加上。。。

def outer(flag):
    def timer(func):
        def inner(*args,**kwargs):
            if flag:
                print('''執行函數以前要作的''')
            re = func(*args,**kwargs)
            if flag:
                print('''執行函數以後要作的''')
            return re
        return inner
    return timer

@outer(False)
def func():
    print(111)

func()

6.多個裝飾器裝飾一個函數函數

def wrapper1(func):
    def inner():
        print('wrapper1 ,before func')
        func()
        print('wrapper1 ,after func')
        print('wrapper1.inner',id(inner))
    return inner
def wrapper2(func):
    def inner():
        print('wrapper2 ,before func')
        func()
        print('func',id(func))
        print('wrapper2 ,after func')
        print('wrapper2.inner',id(inner))
    return inner
@wrapper2   # wrapper1.inner = wrapper2(wrapper1.inner) == wrapper2.inner
@wrapper1   # f = wrapper1(f)===>f =wrapper1.inner
def f():
    print('in f')
f()
print(id(f))

#裝飾器是函數最上面的裝飾器開始調用,可是執行是從上面的裝飾器開始執行的
#嵌套裝飾器的返回值,返回給上一層

wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper1.inner 189913016
func 189913016
wrapper2 ,after func
wrapper2.inner 189913560
189913560

多層嵌套裝飾器的返回值(函數對象),返回給上一層,意義是:給裝飾器在加上一個裝飾器

 

7.裝飾器執行流程及原理,做用post

裝飾器的組成:
  1.閉包 2.語法糖
裝飾器的做用:
  1.裝飾器本質上是一個高級Python函數,經過給別的函數添加@標識的形式實現對函數的裝飾
  2.它可讓其餘函數在不須要作任何代碼變更的前提下增長額外功能,裝飾器的返回值也是一個函數對象。它常常用於有切面需求的場景,好比:插入日誌、性能測試、事務處理、緩存、權限校驗等場景。
   裝飾器是解決這類問題的絕佳設計,有了裝飾器,咱們就能夠抽離出大量與函數功能自己無關的雷同代碼並繼續重用。  
裝飾器的原理:就是利用閉包函數來實現,閉包函數的原理就是包含內層函數的return和外層環境變量

8.高級內置函數性能

***#高級函數默認已經幫咱們作了一次for循環的過程****
lambda:
    是匿名函數,不須要定義,直接調用,能夠配合其餘高級函數一塊兒使用
    lambda x:x>3  第一個是參數,第二個是返回值(能夠作filter的過濾條件)

sorted:
    排序,sorted([1,3,4,2,7,6]) 默認是升序排序,加上reverse=True是降序,
    sorted(li,key=func)能夠有兩個參數,第一個參數必須是可迭代對象,第二個參數key是指定的排序規則,能夠是函數,也能夠是表達式
    sorted配合lambda
    li =['你好啦啦啦啦','我很好','你們都好']
    print(sorted(li,key=lambda x:len(x)))

filter:
    是過濾函數,filter(func,li),第一個參數是一個函數的內存地址,第二個參數是可迭代對象,和sorted正好相反
    filter配合lambda
    li = [1,3,6,2,5,4,8,11,23,45,14] #排除小於5的並排序
    print(sorted(filter(lambda x:x>5,li)))# 既然是過濾函數,就得有過濾條件,正好lambda的第二個參數是返回值,就能夠以其爲過濾條件

map/reduce
map:
    map(func,li)函數接收兩個參數,一個是函數,一個是Iterable,
    map將傳入的函數依次做用到序列的每一個元素,並把結果做爲新的Iterator返回。
    map映射函數, 這裏面的map(lambda x:x*x,ls) ,第一個lambda x:x*x是map的第一個參數函數內存地址,第二個ls是可迭代對象,和filter是同樣的位置傳參數li111 = [1,2,3,4]
    
    map應用
    1.將li111 = [1,2,3,4]快速轉成str
        print(list(map(str,li111)))  #將int快速轉成str

    2.
        ls= [1,2,3,4,5]
        print(list(map(lambda x:x*x,ls)))
reduce:(感受有點像遞歸函數)
   reduce把一個函數做用在一個序列[x1, x2, x3, ...]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素作累積計算 第一個參數是函數的內存地址,第二個參數是可迭代對象第一個參數是函數的內存地址,第二個參數是可迭代對象 他調用的方法中必需要兩個參數,第一個參數一直使用return出來的值,第二個參數是循環可迭代對選對象的元素
from functools import reduce li111 = [1,2,3,4] def func23(x,y): return x*10 +y print(reduce(func23,li111))

zip:函數是python代碼中很是經常使用的一個操做。
   其以可迭代對象爲輸入參數,將可迭代對象裏元素分別取出再組合成一個個元組,返回一個列表。
   a = ['name', 'age', 'sex']
   b = ['alex', 35, 'Male']
   print(dict(zip(a,b)))

什麼狀況須要加list()函數轉化一下?
    map()傳入的第一個參數是f,即函數對象自己。因爲結果r是一個Iterator,Iterator是惰性序列,所以經過list()函數讓它把整個序列都計算出來並返回一個list。
 

9.內置函數學習

https://docs.python.org/zh-cn/3.7/library/functions.html

文章:https://www.cnblogs.com/eric_yi/p/7255455.html
文章:https://www.cnblogs.com/cicaday/p/python-decorator.html
文章:https://yiyibooks.cn/xx/python_352/library/index.html

返回系列

裝飾器牛逼

相關文章
相關標籤/搜索