欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Python中的三器一閉

 更新時間:2023年05月04日 11:09:53   作者:以山河作禮。  
這篇文章主要介紹了詳解Python中的三器一閉,Python中的三器一閉是指迭代器、裝飾器、生成器和閉包,需要的朋友可以參考下

迭代器

什么是迭代

迭代是重復(fù)反饋過程的活動,其目的通常是為了逼近所需目標(biāo)或結(jié)果。每一次對過程的重復(fù)稱為一次“迭代”,而每一次迭代得到的結(jié)果會作為下一次迭代的初始值。

在python中,迭代是訪問集合元素的一種方式。對list、tuple、str等類型的數(shù)據(jù)使用for…in…的循環(huán)語法從其中依次拿到數(shù)據(jù)進(jìn)行使用,我們把這樣的過程稱為遍歷,也叫迭代。

什么是可迭代對象

一個對象如果實(shí)現(xiàn)了__iter__方法(魔法方法),那么我們稱這個對象是可迭代對象。

或者可以這樣理解,只要是可以通過for…in…的形式進(jìn)行遍歷的,那么這個數(shù)據(jù)類型就是可以迭代的。

判斷數(shù)據(jù)是否可迭代

python中要判斷一個對象是否是可迭代的,可以用collections模塊中的Iterable來進(jìn)行判斷。isinstance函數(shù)會返回True或False來表明對象是(True)或者不是(False)可迭代對象。

from collections.abc import Iterable
print(isinstance(["abc"], Iterable))
print(isinstance([100], Iterable))

在這里插入圖片描述

什么是迭代器

迭代器的作用是用來訪問容器(用來保存元素的數(shù)據(jù)結(jié)構(gòu))中的元素,所以使用迭代器,我們就可以訪問容器中里面的元素。

迭代器是一個可以記住遍歷的位置的對象。迭代器對象從第一個元素開始訪問,直到所有的元素被訪問完結(jié)束。迭代器只能往前不會后退。

迭代器的本質(zhì)

我們可以通過iter()函數(shù)獲取這些可迭代對象的迭代器。然后我們可以對獲取到的迭代器不斷使用next()函數(shù)來獲取下一條數(shù)據(jù)。

使用迭代器取數(shù)據(jù)

from collections.abc import Iterator
nums = [3, 6, 8]  # 可迭代對象
nums = iter(nums)  # 創(chuàng)建了迭代器
print("nums", isinstance(nums, Iterator))  # 判斷是否是迭代器
# 取出迭代器的數(shù)據(jù)
num1 = next(nums)
print(num1)
num1 = next(nums)
print(num1)
num1 = next(nums)
print(num1)

在這里插入圖片描述

若迭代的次數(shù)超過了可迭代對象的長度, 就會報StopIteration異常。

自定義迭代器

使用__iter__和__next__方法自定義迭代器

只要在類中,定義__iter__方法,那么這個類創(chuàng)建出來的對象一定是可迭代對象

如果類中實(shí)現(xiàn)了__iter__方法和__next__方法的對象,就是迭代器。

當(dāng)我們調(diào)用iter()函數(shù)提取一個可迭代對象的 迭代器時,實(shí)際上會自動調(diào)用這個對象的__iter__方法,并且這個方法返回迭代器。

# 使用迭代器完成學(xué)生管理系統(tǒng)
class StuSystem(object):
    """
    學(xué)生管理系統(tǒng)
    """
    def __init__(self):
        self.stus = []
        self.current_num = 0
    def add(self):
        """
        添加一個新的學(xué)生
        :return:
        """
        name = input("請輸入新學(xué)生的姓名:")
        tel = input("請輸入新學(xué)生的手機(jī)號:")
        address = input("請輸入新學(xué)生的住址:")
        new_stu = dict()
        new_stu["name"] = name
        new_stu["tel"] = tel
        new_stu["address"] = address
        self.stus.append(new_stu)
    def __iter__(self):
        return self
    def __next__(self):
        if self.current_num < len(self.stus):
            ret = self.stus[self.current_num]
            self.current_num += 1
            return ret
        else:
            self.current_num = 0
            raise StopIteration
# 創(chuàng)建對象
stu = StuSystem()
# 添加信息
stu.add()
stu.add()
stu.add()
stus = [x for x in stu]
print(stus)

在這里插入圖片描述

凡是可作用于for循環(huán)的對象都是Iterable 類型; 凡是可作用于 next() 函數(shù)的對象都是Iterator 類型; 集合數(shù)據(jù)類型如list 、dict、str等是 Iterable但不是Iterator,不過可以通過 iter()函數(shù)獲得一個Iterator對象。

生成器

一邊循環(huán)一邊計算的機(jī)制,稱為生成器(generator)

在Python中,使用了yield的函數(shù)被稱為生成器。跟普通函數(shù)不同的是,生成器是一個返回迭代器的函數(shù),只能用于迭代操作。生成器函數(shù)一般是通過for循環(huán)調(diào)用,for循環(huán)自帶next方法。

創(chuàng)建生產(chǎn)器的方法

1.將列表推導(dǎo)式的[]改為()
2.在函數(shù)中使用yield關(guān)鍵字,函數(shù)就變成了一個generator

使用生成器完成斐波那契數(shù)列

def fib_generator():
    num1 = 1
    num2 = 1
    while True:
        temp_num = num1
        num1, num2 = num2, num1+num2
        # return temp_num  # 方式1代碼
        yield temp_num
# 方式1代碼(方式1不能夠生成1,1,2,3,5...斐波那契數(shù)列)
# print(fib_generator())
# print(fib_generator())
# print(fib_generator())
# print(fib_generator())
# 方式2代碼(可以生成斐波那契數(shù)列)
fib = fib_generator()
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))

在這里插入圖片描述

關(guān)鍵字yield

yield是一個類似return的關(guān)鍵字。當(dāng)我們調(diào)用這個函數(shù)的時候并不是返回計算的結(jié)果。而是返回一個生成器。只有迭代這個生成器的時候才會計算結(jié)果。

next和send

next()方法: 在調(diào)用生成器運(yùn)行的過程中,每次遇到 yield ,函數(shù)返回當(dāng)前的值,并且會暫停并保存當(dāng)前所有的運(yùn)行信息, 并在下一次執(zhí)行 next() 方法時從當(dāng)前位置繼續(xù)運(yùn)行。

send()方法: 先理解個概念【休眠】:意思就是暫時保留先不進(jìn)行,等待需要時再進(jìn)行。作用與next()作用相似 區(qū)別:
1.send(value)可以傳遞value給yield,即:我們可以指定yield返回啥就返回啥,
2.next()不能傳遞特定的值,只能傳遞None進(jìn)去。

def genterator_test():
    while True:
        print("--1-")
        num = yield 100
        print("--2--", "num=", num)
g = genterator_test()
print(g.send(None))
print(g.send(11))
print(g.send(22))

在這里插入圖片描述

生成器的特點(diǎn): 存儲的是生成數(shù)據(jù)的方式(即算法),而不是存儲生成的數(shù)據(jù),因此節(jié)約內(nèi)存。

裝飾器

裝飾器是給現(xiàn)有的模塊增添新的小功能,可以對原函數(shù)進(jìn)行功能擴(kuò)展,而且還不需要修改原函數(shù)的內(nèi)容,也不需要修改原函數(shù)的調(diào)用。

裝飾器的功能

裝飾器的實(shí)現(xiàn)是由閉包支撐的; 裝飾器本質(zhì)上是?個python函數(shù),它可以在讓其他函數(shù)在不需要做任何代碼的變動的前提下增加額外的功能; 裝飾器的返回值也是?個函數(shù)的對象,它經(jīng)常用于有切面需求的場景,實(shí)現(xiàn)路由傳參,flask的路由傳參依賴于裝飾器,瀏覽器通過url訪問到裝飾器的路由,從而訪問視圖函數(shù)獲得返回的HTML頁面;

定義裝飾器

def check_login(func):
    def inner():
        # 驗(yàn)證1
        # 驗(yàn)證2
        # 驗(yàn)證3
        func()
    return inner
@check_login
def f1():
    print('f1')
def check_login(func):
    def inner():
        # 驗(yàn)證1
        if "admin" != input("請輸入用戶名:"):
            return "用戶名不正確"
        # 驗(yàn)證2
        if "123456" != input("請輸入密碼:"):
            return "密碼不正確"
        # 驗(yàn)證3
        if "7788" != input("請輸入手機(jī)短信驗(yàn)證碼:"):
            return "驗(yàn)證碼不正確"
        func()
    return inner
@check_login
def f1():
    print('f1')
f1()  # 調(diào)用f1函數(shù)

閉包

什么是閉包

如果在一個內(nèi)部函數(shù)里,對在外部作用域(但不是在全局作用域)的變量進(jìn)行引用,那么內(nèi)部函數(shù)就被認(rèn)為是閉包(closure).

# 定義函數(shù)可以理解為:
# 定義了一個全局變量,其變量名字是函數(shù)的名字,即test
# 這個test變量指向了一個代碼塊,這個代碼塊是函數(shù)
# 其實(shí)就是說test保存了一個代碼塊的地址,即引用
def test():
    print("--- in test func----")
test()  # 這是調(diào)用函數(shù)
ret = test # 用另外一個變量 復(fù)制了 test這個引用,導(dǎo)致ret變量也指向那個 函數(shù)代碼塊
# 下面輸出的2個地址信息是相同的
print(id(ret))
print(id(test))
# 通過引用調(diào)用函數(shù)
ret()

函數(shù)、匿名函數(shù)、閉包、對象 當(dāng)做實(shí)參時的區(qū)別

匿名函數(shù)能夠完成基本的簡單功能,,,傳遞是這個函數(shù)的引用 只有功能
普通函數(shù)能夠完成較為復(fù)雜的功能,,,傳遞是這個函數(shù)的引用 只有功能
閉包能夠?qū)⑤^為復(fù)雜的功能,,,傳遞是這個閉包中的函數(shù)以及數(shù)據(jù),因此傳遞是功能+數(shù)據(jù)
對象能夠完成最為復(fù)雜的功能,,,傳遞是很多數(shù)據(jù)+很多功能,因此傳遞是功能+數(shù)據(jù)

到此這篇關(guān)于詳解Python中的三器一閉的文章就介紹到這了,更多相關(guān)Python三器一閉內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論