生成器,迭代器,裝飾器


生成器 (generator)

  • 概念

    • 在Python中, 一邊循環一邊計算的機制, 稱為生成器: generator 創建生成器: G = ( x*2 for x in range(5)) 可以通過 next(生成器) 函數獲得生成器的下一個返回值 沒有更多的元素時, 拋出 StopIteration 的異常 生成器也可以使for 循環,因為生成器也是可迭代對象
  • 生成器的生成方式1:

    list2 = [x for x in range(10)] print(type(list2)) # 得到一個生成器對象 g = (x*2 for x in range(10)) print(type(g)) # 打印生成器生成的第一個數字 print(next(g)) print(next(g)) print(next(g)) 一共10個數字,打印超出報StopIteration異常 
    • 應用: 求斐波那契數列的第n個數
    def fibo(n):
    a,b=1,1
    i = 3
    while i <= n:
        if i == 1 or i == 2:
            return 1
        else:
            a,b = b,a+b
            i += 1
    else:
        print(b)

     

  • 生成器的生成方式2(包含yield關鍵字的函數):

    def getNum():
         for i in range(10):
            yield i

     

  • 生成器中元素的訪問方式:

    • 1.next()
    • 2.g.__next()
    • 3.g.send('發送的參數')
    def gen():
        print('a')
        count = yield 1
        print ('--->',count)
        print ('b')
        yield 2
    #注意打印結果
    g = gen()
    next(g)
    g.send('123')
    next(g)

     

  • 其他使用場景:(攜程,實現兩個任務的交替調用)

def save():
    while True:
        yield
        print ('save')
def draw():
    while True:
        yield
        print ('draw')

g1 = save()
g2 = draw()
while True:
    next(g1)
    next(g2)

 

迭代器 (Iterator)

  • 概念: 擁有__iter__方法和__next__方法的對象就是迭代器
    • 迭代
      • 迭代是訪問集合元素的一種方式,可以將某個數據集內的數據“一個挨着一個的取出來”,就叫做迭代
    • 可迭代協議
      • 協議就是互相規定好的。可迭代協議的定義非常簡單,就是內部實現了 __iter__方法。
    • 迭代器協議
      • 迭代器協議:必須擁有__iter__方法和__next__方法
    • 可以通過dir(對象)查看是否實現了__iter__,__next__等方法來判斷對象是否為迭代器
    • 也可以使用 isinstance(Iterator)來判斷
    • 練習:
      • 查看__iter__()的返回值
      • 查看__iter__()包含的方法
      • 分別查看迭代器與列表的方法
  • for循環的本質
    • 通過__iter__()獲取該對象的一個迭代器對象
    • 通過__next__()函數,依次獲取下一個元素

閉包

  • 什么是閉包?
    • 在 python 中創建一個閉包一般有 3 個要求:
      • 1.閉包函數必須有內嵌函數。
      • 2.內嵌函數必須要引用外層函數的變量。
      • 3.閉包函數返回內嵌函數的地址(函數名稱)
  • 創建一個閉包函數:
def funcOut():
    name = 'Jery'
    def funcIn():
        print(name)
    return funcIn
f = funcOut()
f()

 

  • 判斷是否為閉包函數
def funcOut():
    name = 'abc'
    def funcIn():
        print(name)
        pass
    #如果打印None,則不是閉包函數
    print(funcIn.__closure__)
    return funcIn
f=funcOut()
f()

 

裝飾器

  • 裝飾器的本質:(閉包函數)
  • 裝飾器的作用:
    • 在不修改原函數及其調用方式的情況下對原函數功能進行擴展
  • 裝飾器的使用:
    • 需求:為現有功能fun1增加日志功能
    • 傳統方案解決
    • 使用閉包解決
    def outfunc(func):
        def infunc():
            writeLog()
            func()
        return infunc
    def fun1():
        print("使用功能1")
    def fun2():
        print("使用功能2")
    
    # 注意名字的問題,需要分析
    fun1 = outfunc(fun1)
    # 裝飾器(閉包)
    fun1()
    使用裝飾器(語法糖)解決
    def outfunc(func):
        def infunc():
            writeLog()
            func()
        return infunc
    @outfunc
    def fun1():
        print("使用功能1")
    @outfunc
    def fun2():
        print("使用功能2")
    
    fun1()
    fun2()

     

  • 多個裝飾器的使用
def add1(fc):
    print("add1正在裝飾")
    def wrapped():
        return ""+fc()+""
    return wrapped
def add2(fc):
    print("add2正在裝飾")
    def wrapped():
        return '*'+fc()+'*'
    return wrapped
#看到這個,開始進行裝飾,而不是等到調用時
@add1
@add2
def test1():
    return '金陵十三釵'
print(test1())

 

  • 對有參數的函數進行裝飾
def func(fn):
    print("func")
    def func_in(aa, bb):
        print("func_in1")
        fn(aa,bb)
        print("func_in2")
    return func_in
@func
def test(a, b):
    print("a=%d,b=%d" % (a, b))
# 裝飾器裝飾之后,這不是直接調用test方法,而是調用func_in方法
test(1,2)

 

  • 通用裝飾器的使用
def func(fn):
    # 需要有參數,*args,**kwargs
    def func_in(*args,**kwargs):
        print("記錄日志")
        print('訪問方法:'+fn.__name__)
        # 需要有參數,*args,**kwargs
        xx = fn(*args,**kwargs)
        # 需要有返回值
        return xx
    return func_in

 

 # 待裝飾函數:無參數,無返回值
@func
def test1():
    print("test1")
test1()
@func
def test2():
    return "Hello"
print(test2())
@func
def test3(a):
    print('a=%d'%a)
test3(1)

 

類方法靜態方法

  • 靜態方法:
    • 1.格式:在方法上面添加 @staticmethod
    • 2.參數:靜態方法可以有參數也可以無參數
    • 3.應用場景:一般用於和類對象以及實例對象無關的代碼。
    • 4.使用方式: 類名.類方法名(或者對象名.類方法名)
    • 使用示例: 比如:學生管理系統的展示主菜單
  • 類方法:
    • 無需實例化,可以通過類直接調用的方法,但是方法的第一個參數接收的一定是類本身
    • 1.在方法上面添加@classmethod
    • 2.方法的參數為 cls 也可以是其他名稱,但是一般默認為 cls
    • 3.cls 指向 類對象(也就是 Goods)
    • 4.應用場景:當一個方法中只涉及到靜態屬性的時候可以使用類方法(類方法用來修改類屬 性)。
    • 5.使用 可以是 對象名.類方法名。或者是 類名.類方法名
    • 使用示例:
      • 修改所有商品的折扣
      class Goods():
      discount = 1
      def __init__(self,price,name):
          self.name = name
          self.price = price
      def price_discount(self):
          return self.price * Goods.discount
      @classmethod
      def change_discount(cls,new_discount):
          cls.discount = new_discount

       


免責聲明!

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



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