日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

装饰器 闭包 生成器 迭代器

發布時間:2025/3/15 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 装饰器 闭包 生成器 迭代器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2018-02-21? 16:15:56

定義:本質是函數,(裝飾其他函數)為其他函數增加附加功能

裝飾器原則

  • 不能修改被裝飾函數的源代碼
  • 不能修改被裝飾函數的調用方式
  • 說白了,就是被裝飾函數不知道裝飾器的存在

    ?

    裝飾器的知識儲備

    函數即變量

    高階函數

    把一個函數名當作實參傳給另外一個函數

    def ball():
    # print('I am ball')
    # # return 15
    # def text11(hh):
    # hh()
    # text11(ball)
    # (函數后面有括號是這個函數本身和return,text11(ball())不符合高階函數 沒有括號是內存地址)

    ???????

    ?

    返回值可以是函數名

    ?

    嵌套函數

    ?

    ?裝飾器本質上是一個python函數,他可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,裝飾器的返回值是一個函數對象. 經常用于有切面需求的場景,比如:插入日志,性能測試,事物處理,緩存,權限校驗等場景. 裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量與函數功能本身無關的雷同代碼并繼續使用.?? 裝飾器就是為已經存在的對象添加額外的功能

    ?

    @符號是裝時器的語法糖,在定義函數時使用,避免再一次賦值操作

    1起源

    我們想在login中輸入調試信息,我們可以這樣做

    def login():
    print('in login')
    def printdebug(fun):
    print('enter the login')
    fun()
    print('exit the login')
    printdebug(login)

    ?2讓代碼變得優美一點

    def login():
    print('in login')
    def printdebug(fun):
    def a():
    print('enter the login')
    fun()
    print('exit the login')
    return a
    debug_login = printdebug(login)
    debug_login()

    3 讓代碼變得更加優美(python提供了@u語法糖符號)

    def printdebug(fun):
    def a():
    print('enter the login')
    fun()
    print('exit the login')
    return a
    @printdebug
    def login():
    print('in login')
    login()

    4.加上參數

    1)被裝飾函數加參數

    python會將login的參數直接傳給函數a. 我們可以在函數a中使用user變量

    def printdebug(fun):
    def a(user):
    print('enter the login in ')
    fun(user)
    print('exit the login')
    return a
    @printdebug
    def login(user):
    print('in login'+ user)

    4.2裝飾器本身有參數(為了接受傳來的參數,需要在原本的printdebug函數上面添加一個函數來接收參數)

    def printdebug_level(level):
      def printdebug(fun):
        def a(user):
          print('enter the login, and debug level is %s'%level)
          fun(user)
           print('exit the login')
        return a
      return printdebug
    @printdebug_level('it')
    def login(user):
      print('in login %s'%user)
    login('dsaf')
    5 裝飾有返回值的函數(在裝飾器中,將被裝飾函數賦給一個變量,然后返回這個變量)

    def printdebug_level(level):
    def printdebug(fun):
    def a(user):
    print('enter the login, and debug level is %s'%level)
    fun(user)
    retuu = fun(user)
    print('exit the login')
    return retuu
    return a
    return printdebug
    @printdebug_level('it')
    def login(user):
    print('in login %s'%user)
    return '555'
    res = login('dsaf')
    print('my name is %s'%res)

    ?

    閉包

    如果一個函數定義在另一個函數的作用域內,并且引用了外層函數的變量,稱為閉包
    def outter():
    name = 'slz'
    def inner():
    print(name)
    return inner
    res = outter()
    res()
    print(res.__closure__) 如果res是閉包的話,會返回一個由cell對象組成的元組對象
    print(res.__closure__[0].cell_contents) cell_contents屬性是閉包中的自由變量

    列表生成器
    將列表中的每個值加一
    a = [i+1 for i in range(10)]
    print(a)

    生成器
    通過列表生成器,我們直接創建了一個列表.但是受到內存限制,列表容量肯定是有限是的.
    而且,創建一個包含100萬個元素的列表,不僅占用很大的存儲空間,如果我們僅僅訪問前面的幾個元素,那后面的大多數元素占用的空間就白白浪費了
    所以,如果列表和i元素可以按照某種算法推算出來,那我們是否可以在循環的過程中不斷推算出后續的元素呢?
    這樣就不必創建完整的list,從而節省大量的空間
    在python中,這種一邊循環一邊計算的機制,稱為生成器: generator
    要創建一個generator,有很多種方法,第一種很簡單,只要把列表生成式的[]改為()
    b = (i+1 for i in range(10))
    print(b)

    那么我們如何把b的值打印出來呢

    b = (i+1 for i in range(10))
    print(b)
    for n in b:
    print(n)

    定義generator的另一種方法,如果一個函數定義中包含yield關鍵字,那么這個函數就不在是一個普通函數,而是一個generator

    def fib(max):n,a,b = 0,0,1while n < max:#print(b) yield b a,b = b,a+b n += 1 return 'done'
    還是通過循環來調用
    for i in fib(19):
    print(i)

    可迭代對象

    就是可以用for循環的
    for a in 'abc':
    print(a)
    一類是集合數據類型,list,tuple,dict,set,str
    一類是generator,包括生成器
    測試某個數據是否可迭代
    1,
    就是上面的可以直接作用于for循環的統稱為可迭代對象: Iterable
    >>> from collections import Iterable >>> isinstance([], Iterable) True >>> isinstance({}, Iterable) True >>> isinstance('abc', Iterable) True >>> isinstance((x for x in range(10)), Iterable) True >>> isinstance(100, Iterable) False

    2 for i in 100:
    print(i)
    迭代器
    *可以被next()函數調用并不斷返回下一個值的對象稱為迭代器:Iterator

    可以使用isinstance()判斷一個對象是否是Iterator對象:

    1 2 3 4 5 6 7 8 9 >>> from collections import Iterator >>> isinstance((x for x in range(10)), Iterator) True >>> isinstance([], Iterator) False >>> isinstance({}, Iterator) False >>> isinstance('abc', Iterator) False
    通過上面的表可以看到list,dict,str雖然是Iterable,但不是Iterator

    這是因為Python的Iterator對象表示的是一個數據流,Iterator對象可以被next()函數調用并不斷返回下一個數據,直到沒有數據時拋出StopIteration錯誤。可以把這個數據流看做是一個有序序列,但我們卻不能提前知道序列的長度,只能不斷通過next()函數實現按需計算下一個數據,所以Iterator的計算是惰性的,只有在需要返回下一個數據時它才會計算。

    Iterator甚至可以表示一個無限大的數據流,例如全體自然數。而使用list是永遠不可能存儲全體自然數的。

    Iterator是只有需要返回下一步運算的時候才會計算

    ?

    ?小結

    凡是可作用于for循環的對象都是Iterable類型;

    凡是可作用于next()函數的對象都是Iterator類型,它們表示一個惰性計算的序列;

    集合數據類型如list、dict、str等是Iterable但不是Iterator,不過可以通過iter()函數獲得一個Iterator對象。

    Python的for循環本質上就是通過不斷調用next()函數實現的,例如:

    1 2 for x in [1, 2, 3, 4, 5]: ????pass

    實際上完全等價于:

    # 首先獲得Iterator對象: it = iter([1, 2, 3, 4, 5]) # 循環: while True: try: # 獲得下一個值: x = next(it) except StopIteration: # 遇到StopIteration就退出循環 break

    轉載于:https://www.cnblogs.com/sunlizhao/p/8457446.html

    總結

    以上是生活随笔為你收集整理的装饰器 闭包 生成器 迭代器的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。