溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

python學(xué)習(xí)之高級特性

發(fā)布時間:2020-07-23 21:08:43 來源:網(wǎng)絡(luò) 閱讀:162 作者:霍金181 欄目:編程語言

一、生成式
1、定義

生成式就是一個用來快速生成特定語法形式的表達式。
列表生成式:用來快速生成列表
字典生成式:用來快速生成字典
集合生成式:用來快速生成集合
2、語法格式

(1)普通的語法格式:[exp for iter_var in iterable]
(2)帶過濾功能語法格式: [exp for iter_var in iterable if_exp]
(3)循環(huán)嵌套語法格式: [exp for iter_var_A in iterable_A for iter_var_B in iterable_B]

01_列表生成式.py

#需求: 生成100個1~50之間的隨機數(shù)值。

import random
def use_list_expression(count=100, start=0, end=50):
    """第一種: 使用列表生成式實現(xiàn)需求"""
    return  [random.randint(start, end) for count in range(count)]

def use_loop(count=100, start=0, end=50):
    """第二種: 使用for循環(huán)與傳統(tǒng)的方式實現(xiàn)需求"""
    nums = []
    for count in range(count):
        num = random.randint(start, end)
        nums.append(num)
    return  nums

print(use_list_expression(count=5))
print(use_loop(count=8))"""

02_列表生成式.py

#需求: 找出1-100之間能被3整除的數(shù)值;
def use_loop(start=1, end=100, div_num=3):
    """使用傳統(tǒng)的方式實現(xiàn)需求"""
    nums = []
    for num in range(start, end + 1):
        if num % div_num == 0:
            nums.append(num)
    return nums

def use_list_expression(start=1, end=100, div_num=3):
    """使用列表生成式實現(xiàn)需求"""
    return [num for num in range(start, end + 1) if num % div_num == 0]

print(use_loop(1, 10, 4))
print(use_loop(div_num=50))
"""

03_列表生成式.py

nums = [item1+ item2 for item1 in 'abc' for item2 in '123']
print(nums)

nums = []
for item1 in 'abc':         # item1='a'             item1='b'               item1='c'
for item2 in '123':     # item2='1', '2', '3'   item2='1', '2', '3'     item2='1', '2', '3'
nums.append(item1 + item2)
print(nums)

04_集合生成式.py

#需求: 生成100個1~200之間的隨機且不重復(fù)數(shù)值。

import random
nums = {random.randint(1, 200) for count in range(100)}
print(nums)
null

05_字典生成式.py

dict = {
        'key1' : 'value1',
        'key1' : 'value1'
    }

import  pprint
#需求: 生成100個用戶字典, key是用戶名userx(x=1, 2, 3, ....), value是密碼passwordx(x=1, 2, 3...)
users_info = {'user' + str(x+1): 'password'+ str(x+1) for x in range(100)}
pprint.pprint(users_info)"""
null

06_生成式練習(xí).py

import math
def circle_example():
    """求以r為半徑的圓的面積和周長(r的范圍從1到10)。"""
    square = lambda r: math.pi * (r ** 2)
    C = lambda r: 2 * math.pi * r
    return [(square(r), C(r)) for r in range(1, 11)]

def swap_key_value(dictObj):
    """將字典的key值和value值調(diào)換"""
    return {value: key for key, value in dictObj.items()}

def is_prime(num):
    """判斷num是否為質(zhì)數(shù)?如果是,返回True, 否則返回False. 具體的代碼自行補充完整"""
    return  True

def find_prime():
    """找出1~100之間所有的質(zhì)數(shù)"""
    return [num for num in range(1, 101) if is_prime(num)]

if __name__ == '__main__':
    result1 = circle_example()
    print(result1)
    d = {
        'user1': 'passwd1',
        'user2': 'passwd2',
    }
    result2 = swap_key_value(d)
    print(result2)

二、生成器
1、定義和特點

(1)在python中,一邊循環(huán)一邊計算的機制,稱為生成器(Generator)
(2)應(yīng)用場景:
性能限制需要用到,比如讀取一個10G的文件,如果一次性將10G的文件加載到內(nèi)存處理的話 (read方法),內(nèi)存肯定會溢出。但使用生成器把讀寫交叉處理進行,比如使用(readline和readlines) 就可以再循環(huán)讀取的同時不斷處理,這樣就可以節(jié)省大量的內(nèi)存空間。
(3)特點:
1> 解耦。 爬蟲與數(shù)據(jù)存儲解耦;
2> 減少內(nèi)存占用.。隨時生產(chǎn), 即時消費, 不用堆積在內(nèi)存當中;
3> 可不終止調(diào)用.。寫上循環(huán), 即可循環(huán)接收數(shù)據(jù), 對在循環(huán)之前定義的變量, 可重復(fù)使用;
4> 生成器的循環(huán), 在 yield 處中斷, 沒那么占 cpu
2、創(chuàng)建和訪問

(1)創(chuàng)建:
方法一:列表生成式的改寫。 []改成()
方法二:yield關(guān)鍵字
(2)訪問:
方法一:通過for循環(huán), 依次計算并生成每一個元素
方法二:通過 next() 函數(shù)一個一個獲取

07_生成器創(chuàng)建方法一.py

第一種方法: 列表生成式的改寫。 []改成()

#列表生成式

nums = [num for num in range(1, 10001) if num % 8 == 0]
print(nums)

#生成器創(chuàng)建

nums_gen = (num for num in range(1, 10001) if num % 8 == 0)
print(nums_gen)             # <generator object <genexpr> at 0x7f8f2cb92350>
print(type(nums_gen))       # <class 'generator'>

#查看一個對象是否可以for循環(huán)?
from collections.abc import Iterable
print("生成器是否為可迭代對象?", isinstance(nums_gen, Iterable))

#訪問生成器對象元素的方法一: 通過for循環(huán), 依次計算并生成每一個元素。

"""
for num in nums_gen:
    if num > 50:
        break
    print(num)
"""

#訪問生成器對象元素的方法二: 如果要一個一個打印出來,可以通過next()函數(shù)獲得生成器的下一個返回值。
print(next(nums_gen)) #執(zhí)行一次next生成一個值
print(next(nums_gen))
print(next(nums_gen))
"""

08_生成器創(chuàng)建方法二.py

Fib數(shù)列的案例理解生成器的創(chuàng)建
"""

def fib1(num):
    """遞歸實現(xiàn)Fib數(shù)列"""
    if num in (1, 2):
        return 1
    return fib1(num - 1) + fib1(num - 2)

#第二種方法: 函數(shù)中包含yield關(guān)鍵字

def fib2(num):
    """不使用遞歸方式實現(xiàn)Fib數(shù)列"""
    count = 0
    a = b = 1
    while True:
        if count < num:
            count += 1
            yield a
            a, b = b, a + b
        else:
            break

#如果函數(shù)中有yield關(guān)鍵字, 那么函數(shù)的返回值是生成器對象.

result = fib2(100)
print(result)

#訪問生成器對象元素的方法一: 通過for循環(huán), 依次計算并生成每一個元素。

"""
for num in result:
    if num > 50:
        break
    print(num)
"""

#訪問生成器對象元素的方法二: 如果要一個一個打印出來,可以通過next()函數(shù)獲得生成器的下一個返回值。
print(next(result)) # 執(zhí)行一次next生成一個值
print(next(result))
print(next(result))

"""
yield:
函數(shù)中包含yield關(guān)鍵字, 返回的是生成器對象
當?shù)谝淮握{(diào)用next(genObj), 才開始執(zhí)行函數(shù)內(nèi)容。
遇到y(tǒng)ield關(guān)鍵字, 執(zhí)行停止。
再次調(diào)用next方法時, 從上次停止的代碼位置繼續(xù)執(zhí)行。
遇到y(tǒng)ield關(guān)鍵字, 執(zhí)行停止。

09_yield關(guān)鍵字與return關(guān)鍵字.py

"""
#def return_example():

"""

#理解return的工作原理
#1). 函數(shù)運行結(jié)果是什么?
#2). 是否會打印'step 1'? why?
#3). 是否會打印'step 2'? why?
#"""
#print('step 1')
##函數(shù)遇到return, 函數(shù)舊執(zhí)行結(jié)束。 后面的代碼不會執(zhí)行的。
#return True
#print('step 2')

def yield_example():
"""
理解yield的工作原理
1). 函數(shù)的運行結(jié)果是什么?
函數(shù)中包含yield關(guān)鍵字, 返回的是生成器對象。
當?shù)谝淮握{(diào)用next(genObj), 才執(zhí)行函數(shù)內(nèi)容.
遇到y(tǒng)ield關(guān)鍵字, 執(zhí)行停止。
再次調(diào)用next方法時, 從上詞停止的代碼位置繼續(xù)執(zhí)行。
遇到y(tǒng)ield關(guān)鍵字, 執(zhí)行停止。
............

    """
    for count in range(100):
        yield 'step' + str(count + 1)
        print("suucess")

if __name__ == '__main__':
    #return_example()
    #result是一個生成器, 因為調(diào)用的函數(shù)中包含yield關(guān)鍵字。
    result = yield_example()
    print(next(result))
    print(next(result))
"""

10_生成器的send方法.py

"""


def grep(kw):
    """搜索關(guān)鍵字"""
    while True:
        response = ''
        request = yield response
        if kw in request:
            print(request)
if __name__ == '__main__':
    grep_gen = grep('python')
    next(grep_gen)
    #send方法可以給生成器傳遞數(shù)據(jù), 并一直執(zhí)行, 遇到y(tǒng)ield停止。
    grep_gen.send('I love python')
    grep_gen.send('I love Java')

"""

11_聊天機器人.py

"""


def chatRobot():
    response = ''
    while True:
        request = yield  response
        if '姓名' in request:
            response = '姓名暫時保密'
        elif '你好' in request:
            response = '你好!Hello'
        else:
            response = '我不知道你在說些什么, 請換種說法'

if __name__ == '__main__':
    #生成器對象
    Robot = chatRobot()
# 調(diào)用next方法
next(Robot)
while True:
    request = input("Me: >> ")
    if request == '再見':
        print("歡迎下次聊天.....")
        break
    response = Robot.send(request)
    print("Robot: >> ", response)

"""

12_基于生成器的智能聊天機器人.py

代碼需要聯(lián)網(wǎng)運行
"""

#requests庫是python實現(xiàn)的最簡單易用的HTTP庫,多用于網(wǎng)絡(luò)爬蟲。
import requests
#json庫是python中實現(xiàn)json的序列化與反序列化的模塊。
import json
def robot_api(word):
    #青云提供的聊天機器人API地址
    url = 'http://api.qingyunke.com/api.php?key=free&appid=0&msg=%s' %(word)
    try:
        #訪問URL, 獲取網(wǎng)頁響應(yīng)的內(nèi)容。
        response_text = requests.get(url).text
        #將json字符串轉(zhuǎn)成字典, 并獲取字典的‘content’key對應(yīng)的value值
        #eg: {'result': 0, 'content': '有做廣告的嫌疑,清靜點別打廣告行么'}
        return  json.loads(response_text).get('content', "無響應(yīng)")
    except Exception as e:
        #如果訪問失敗, 響應(yīng)的內(nèi)容為''
        return  ''

def chatRobot():
    response = ''
    while True:
        #yield  response: response就是生成器執(zhí)行next方法或者send方法的返回值。
        #request = yield
        request = yield  response
        if '姓名' in request:
            response = '姓名暫時保密'
        elif '你好' in request:
            response = '你好!Hello'
        else:
            response = robot_api(request)

if __name__ == '__main__':
    #生成器對象
    Robot = chatRobot()
    #調(diào)用next方法
    next(Robot)
    while True:
        request = input("Me: >> ")
        if request == '再見':
            print("歡迎下次聊天.....")
            break
        response = Robot.send(request)
        print("Robot: >> ", response)

"""

三、生成器、迭代器、可迭代對象總結(jié)

生成式:快速生成列表,集合,字典
生成器(generator):一邊循環(huán)一邊計算
迭代器(iterator):可以調(diào)用next()方法訪問元素
可迭代對象:可以通過for循環(huán)訪問

生成器都是迭代器,都是可迭代對象
可迭代對象不一定是迭代器,例如:str,list,tuple,set,dict
怎么將可迭代對象轉(zhuǎn)換成迭代器:通過iter()關(guān)鍵字

14_生成器與迭代器.py

生成器: generator, 一邊循環(huán)一邊計算的工具。
迭代器: iterator, 可以調(diào)用next方法訪問元素的對象.
可迭代對象: Iterable, 可以實現(xiàn)for循環(huán)的

生成器都是迭代器么? Yes, 生成器內(nèi)部實現(xiàn)了迭代器的協(xié)議。
生成器都是可迭代對象嗎? Yes
可迭代對象都是迭代器嗎? Not Always, 比如: str,list,tuple,set,dict.
如何將可迭代對象轉(zhuǎn)換成迭代器? iter()內(nèi)置函數(shù)

""""""
四、閉包
1、定義

閉包就是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù)。
常見形式:
(1)函數(shù)嵌套
(2)內(nèi)部函數(shù)使用外部函數(shù)的變量
(3)外部函數(shù)的返回值是內(nèi)部函數(shù)的名稱
應(yīng)用場景:裝飾器
優(yōu)點:提高代碼可復(fù)用性

15_閉包.py


line_conf:是外部函數(shù)
line: 是內(nèi)部函數(shù)

line是否為閉包? Yes, line調(diào)用了line_conf的局部變量a和b
"""
import matplotlib.pyplot as plt

def line_conf(a, b):        # a=2, b=3
    """y = ax + b """
    def line(x):
        return a * x + b
    return line

#line1是一個函數(shù)名
line1 = line_conf(2, 3)  # 調(diào)用函數(shù), a=2, b=3
line2 = line_conf(3, 3)  # 調(diào)用函數(shù), a=3, b=3
line3 = line_conf(4, 3)  # 調(diào)用函數(shù), a=4, b=3

#x = [1, 3, 5, 7 .....99]
x = list(range(1, 100, 2))
y1 = [line1(item) for item in x]
y2 = [line2(item) for item in x]
y3 = [line3(item) for item in x]

#plot:折線圖
#plt.plot(x, y1, label='y=2x+3')
#plt.plot(x, y2, label='y=3x+3')
#plt.plot(x, y3, label='y=4x+3')

#scatter: 散點圖
plt.scatter(x, y1, label='y=2x+3')
plt.scatter(x, y2, label='y=3x+3')
plt.scatter(x, y3, label='y=4x+3')

#顯示繪制的圖形
plt.title('line display')   # 添加標題
plt.legend()                # 添加圖例
plt.show()

五、裝飾器
1、定義

(1)器指的是工具,而程序中的函數(shù)就是具備某一功能的工具,所以裝飾器指的是為被裝飾器對象添加額外功能的工具/函數(shù)。
(2)為什么要使用裝飾器
如果我們已經(jīng)上線了一個項目,我們需要修改某一個方法,但是我們不想修改方法的使用方法,這個時 候可以使用裝飾器。因為軟件的維護應(yīng)該遵循開放封閉原則,即軟件一旦上線運行后,軟件的維護對修 改源代碼是封閉的,對擴展功能指的是開放的。
裝飾器的實現(xiàn)必須遵循兩大原則:
1> 封閉: 對已經(jīng)實現(xiàn)的功能代碼塊封閉。 不修改被裝飾對象的源代碼
2> 開放: 對擴展開發(fā) 裝飾器其實就是在遵循以上兩個原則的前提下為被裝飾對象添加新功能。
(3)如何實現(xiàn)裝飾器:
裝飾器本質(zhì)上是一個函數(shù),該函數(shù)用來處理其他函數(shù),它可以讓其他函數(shù)在不需要修改代碼的前提下增加額外的功能,裝飾器的返回值也是一個函數(shù)對象。

16_裝飾器.py

#logging:專門做日志記錄或者處理的模塊。
import logging

#日志的基本配置
#官方符網(wǎng)站基本配置及使用: https://docs.python.org/zh-cn/3/howto/logging.html#logging-basic-tutorial
logging.basicConfig(
    level=logging.DEBUG,  # 控制臺打印的日志級別
    filename='message.log',  # 日志文件位置
    filemode='a',  # 寫入文件的模式,a是追加模式,默認是追加模式
    #日志格式
    format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
)

#logging.debug('Network start Ok')
#logging.warning('Network start Failed')

#1). 定義裝飾器
from functools import wraps

def logger(func):
    """插入日志的裝飾器"""
    #wraps裝飾器, 用來保留func函數(shù)原有的函數(shù)名和幫抓文檔。
    @wraps(func)
    def wrapper(*args, **kwargs):  # args, kwargs是形參, args是元組, kwargs是字典.
        """閉包函數(shù)"""
        logging.debug("函數(shù)%s開始執(zhí)行" % (func.__name__))
        result = func(*args, **kwargs)  # args, kwargs是實參, *args, **kwargs解包
        logging.debug("函數(shù)%s執(zhí)行結(jié)束" % (func.__name__))
        return result

    return wrapper

#2). 如何使用裝飾器?
#1). @logger語法糖,  login = logger(login), python解釋器遇到語法糖就直接執(zhí)行
#2). login函數(shù)目前指向logger(login)函數(shù)的返回值wrapper, login=wrapper
@logger
def login(username, password):
    """用戶登錄"""
    if username == 'root' and password == 'redhat':
        print('LOGIN OK')
        logging.debug('%s LOGIN OK' % (username))
    else:
        print('LOGIN FAILED')
        logging.error('%s LOGIN FAILED' % (username))

#實質(zhì)上執(zhí)行的是裝飾器里面的wrapper函數(shù)
login('root', 'westos')
#print(login.__name__)
#print(login.__doc__)

2019-12-21 17:15:53,226 - /home/kiosk/201911python/day08_code/16_裝飾器.py[line:32] - DEBUG: 函數(shù)login開始執(zhí)行
2019-12-21 17:15:53,227 - /home/kiosk/201911python/day08_code/16_裝飾器.py[line:46] - ERROR: root LOGIN FAILED
2019-12-21 17:15:53,227 - /home/kiosk/201911python/day08_code/16_裝飾器.py[line:34] - DEBUG: 函數(shù)login執(zhí)行結(jié)束
2019-12-21 17:17:00,105 - /home/kiosk/201911python/day08_code/16_裝飾
"""

生成器應(yīng)用范例.py

import os
#文件名稱的匹配,并且匹配的模式使用的unix shell風(fēng)格
import fnmatch
def locate(pattern, root=os.curdir):
    """生產(chǎn)者: 生產(chǎn)符合條件的文件名"""
    #os.walk返回三個值: 查詢根目錄, 子目錄,目錄文件
    for path, dirs, files in os.walk(os.path.abspath(root)):
        # fnmatch.filter實現(xiàn)列表特殊字符的過濾或篩選,返回符合匹配模式的字符列表
        for filename in fnmatch.filter(files, pattern):
            # 拼接文件的絕對路徑
            yield os.path.join(path, filename)

def rename():
    """消費者: 文件重命名"""
    while True:
        filename = yield
        dirname, basename = os.path.split(filename)
        rename = os.path.join(dirname, '[西部開源]_' + basename)
        os.rename(filename, rename)

if __name__ == '__main__':
    fname = locate('*.py')
    rename_gen = rename()
    next(rename_gen)
    for name in fname:
        rename_gen.send(name)

裝飾器的應(yīng)用場景

裝飾器經(jīng)常用于有切面需求的場景,比如:
插入日志、性能測試、事務(wù)處理、緩存、 權(quán)限校驗等應(yīng)用場景。

01_性能統(tǒng)計的裝飾器.py

from functools import  wraps
import time

def timeit(func):   # 2   func=download_music
    """打印被裝飾函數(shù)運行總時間的裝飾器"""
    #@wraps保留被裝飾函數(shù)的函數(shù)名和幫助文檔, 否則是wrapper的信息.
    @wraps(func)
    def wrapper(*args, **kwargs):   # 5     args=('Music', ), kwargs={}
        start_time = time.time()
        result = func(*args, **kwargs)  # 6 func('Music')=download_music('Music')
        end_time = time.time()
        print("%s函數(shù)運行總時間為%fs" %(func.__name__, end_time-start_time))
        return  result                  # 7
    return  wrapper     # 3

@timeit         # 1 @timeit實質(zhì)上執(zhí)行的內(nèi)容: download_music = timeit(download_music) = wrapper
def download_music(name):   # 7
    time.sleep(0.4)
    print('[Download]: ', name)
    return  True

#調(diào)用download_music函數(shù)時實質(zhì)上調(diào)用的是wrapper函數(shù)。
download_music('Music') # 4
"""

02_事務(wù)處理的裝飾器.py

import json
from functools import wraps
import string
def json_result(func):                  # 2
    """被裝飾函數(shù)的返回值序列化成json格式字符串"""

    #保留被裝飾函數(shù)的函數(shù)名和幫助文檔。
    @wraps(func)
    def wrapper(*args, **kwargs):       # 5
        result = func(*args, **kwargs)  # 6
        return json.dumps(result)       # 8
    return wrapper                      # 3

@json_result                            # 1
def get_users():                        # 7
    return {'user' + item: 'passwd' + item for item in string.digits}

result = get_users()                    # 4
print(result)                           # 9

"""

實現(xiàn)斐波那契數(shù)列,由于重復(fù)性占用很大的空間且計算緩慢,所以可以利用緩存來節(jié)省時間

03_Fib數(shù)列緩存的裝飾器.py

from functools import lru_cache
from functools import wraps
import time

def timeit(func):  # 2   func=download_music
    """打印被裝飾函數(shù)運行總時間的裝飾器"""

    #@wraps保留被裝飾函數(shù)的函數(shù)名和幫助文檔, 否則是wrapper的信息.
    @wraps(func)
    def wrapper(*args, **kwargs):  # 5     args=('Music', ), kwargs={}
        start_time = time.time()
        result = func(*args, **kwargs)  # 6 func('Music')=download_music('Music')
        end_time = time.time()
        print("%s函數(shù)運行總時間為%fs" % (func.__name__, end_time - start_time))
        return result  # 7

    return wrapper  # 3

def fib_cache(func):
    """打印被裝飾函數(shù)運行總時間的裝飾器"""
    caches = {1: 1, 2: 1, 3: 2, 4: 4}

    #@wraps保留被裝飾函數(shù)的函數(shù)名和幫助文檔, 否則是wrapper的信息.
    @wraps(func)
    def wrapper(num):
        # 如果緩存中能找到第num個Fib數(shù)列的值, 直接返回。
        if num in caches:
            return  caches.get(num)
        #如果緩存中不能找到第num個Fib數(shù)列的值,
        #1). 先執(zhí)行函數(shù)func(num)計算結(jié)果。
        #2). 然后將將計算的信息存儲在緩存中。并返回計算結(jié)果
        else:
            result = func(num)
            caches[num] = result
            return result

    return wrapper

#@fib_cache
@lru_cache(maxsize=10000)
def fib1(num):
    """計算第num個Fib數(shù)列"""
    if num in (1, 2):
        return 1
    else:
        return fib1(num - 1) + fib1(num - 2)

def fib2(num):
    """計算第num個Fib數(shù)列"""
    if num in (1, 2):
        return 1
    else:
        return fib2(num - 1) + fib2(num - 2)

@timeit # use_cache = timeit(use_cache)
def use_cache():
    result = fib1(20)
    print(result)

@timeit
def no_cache():
    result = fib2(20)
    print(result)

if __name__ == '__main__':
    use_cache()
    no_cache()
"""

一般情況下,在函數(shù)中可以使用一個裝飾器,但是有時也會有兩個或兩個以上的裝飾器。 多個裝飾器裝飾的順序是自下而上(就近原則),而調(diào)用的順序是自上而下(順序執(zhí)行)

04_權(quán)限驗證與多裝飾器.py

from functools import wraps
#系統(tǒng)中的用戶信息;
db = {
    'root': {
        'name': 'root',
        'passwd': 'westos',
        'is_super': 0  # 0-不是 1-是
    },
    'admin': {
        'name': 'admin',
        'passwd': 'westos',
        'is_super': 1  # 0-不是 1-是
    }
}
#存儲當前登錄用戶的信息;
login_user_session = {}

def is_login(func):
    """判斷用戶是否登錄的裝飾器"""
    #@wraps保留被裝飾函數(shù)的函數(shù)名和幫助文檔, 否則是wrapper的信息.
    @wraps(func)
    def wrapper1(*args, **kwargs):
        if login_user_session:
            result = func(*args, **kwargs)
            return result
        else:
            print("未登錄, 請先登錄.......")
            print("跳轉(zhuǎn)登錄".center(50, '*'))
            user = input("User: ")
            passwd = input('Password: ')
            if user in db:
                if db[user]['passwd'] == passwd:
                    login_user_session['username'] = user
                    print('登錄成功')
                    #***** 用戶登錄成功, 執(zhí)行buy的操作;
                    result = func(*args, **kwargs)
                    return result
                else:
                    print("密碼錯誤")
            else:
                print("用戶不存在")

    return wrapper1

def is_permission(func):
    """判斷用戶是否有權(quán)限的裝飾器"""

    #@wraps保留被裝飾函數(shù)的函數(shù)名和幫助文檔, 否則是wrapper的信息.
    @wraps(func)
    def wrapper2(*args, **kwargs):
        print("判斷是否有權(quán)限......")
        current_user = login_user_session.get('username')
        permissson = db[current_user]['is_super']
        if permissson == 1:
            result = func(*args, **kwargs)
            return result
        else:
            print("用戶%s沒有權(quán)限" % (current_user))
    return wrapper2

#多個裝飾器裝飾的順序是自下而上(就近原則),而調(diào)用/執(zhí)行的順序是自上而下(順序執(zhí)行)。
"""
被裝飾的過程: 
1). @is_permission:  buy = is_permission(buy)  ===> buy=wrapper2
2). @is_login: buy = is_login(buy)  ===> buy = is_login(wrapper2)   ===> buy=wrapper1
"""

@is_login
@is_permission
def buy():
    print("購買商品........")

"""
判斷用戶是否登錄..........
判斷用戶是否有權(quán)限..........
購買商品........

調(diào)用的過程: 
    1). buy() ===>  wrapper1()  print("判斷用戶是否登錄..........")
    2). wrapper2()              print("判斷用戶是否有權(quán)限..........")
    3). buy()                   print("購買商品........")                 
"""
buy()
"""

無參裝飾器只套了兩層,有參裝飾器: 套三層的裝飾器

05_有參數(shù)的裝飾器.py

from functools import  wraps
def auth(type):
    print("認證類型為: ", type)
    def desc(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if type == 'local':
                user = input("User:")
                passwd = input("Passwd:")
                if user == 'root' and passwd == 'westos':
                    result = func(*args, **kwargs)
                    return result
                else:
                    print("用戶名/密碼錯誤")
            else:
                print("暫不支持遠程用戶登錄")
        return  wrapper
    return  desc

結(jié)論: @后面跟的是裝飾器函數(shù)的名稱, 如果不是名稱, 先執(zhí)行,再和@結(jié)合。
1). @auth(type='local') 
2). desc = auth(type='local')
3). @desc
4). login = desc(login)
4). login = wrapper
"""
@auth(type='remote')
def home():
    print('網(wǎng)站主頁')

home()

內(nèi)置高階函數(shù)

把函數(shù)作為參數(shù)傳入,或者作為返回值返回
1、map()函數(shù)

map(function, *iterable)
傳入函數(shù)和可迭代對象
根據(jù)提供的函數(shù)對指定序列做映射。
python學(xué)習(xí)之高級特性
當序列多于一個時,map可以并行(注意是并行)地對每個序列執(zhí)行如下圖所示的過程:
python學(xué)習(xí)之高級特性

06_內(nèi)置高階函數(shù).py

#1+1*3
#add(1,cheng(1, 3))
#map() 會根據(jù)提供的函數(shù)對指定序列做映射。
#1). map的傳遞函數(shù)名可以是內(nèi)置函數(shù)
map_object = map(int, ['1', '2', '3'])
for item in map_object:
    print(item, type(item))

#2). map的傳遞函數(shù)名可以是匿名函數(shù)
iterator_object = (int(item) for item in ['1', '2', '3'])
for item in iterator_object:
    print(item, type(item))

map_object = map(lambda x: x ** 2, [1, 2, 3, 4])
print(list(map_object))  # [1, 4, 9, 16]

def data_process(x):
    return x + 4
#3). map的傳遞函數(shù)名可以是非匿名函數(shù)
map_object = map(data_process, [1, 2, 3, 4])
print(list(map_object))  # [1, 4, 9, 16]

#4). map的傳遞的可迭代對象可以是多個

x, y = 1, 1 2
x, y = 2, 2 6
x, y = 3, 3 12
"""
map_object = map(lambda x, y: x ** 2 + y, [1, 2, 3], [1, 2, 3])
print(list(map_object))
reduce() 函數(shù)

reduce(function, sequence[, initial]) -> value
對參數(shù)序列中元素進行累積
在python2中,reduce是內(nèi)置高階函數(shù)
在python3中,reduce函數(shù)需要導(dǎo)入:
from functools import reduce
python學(xué)習(xí)之高級特性

07_內(nèi)置高階函數(shù)reduce.py

#reduce() 函數(shù)會對參數(shù)序列中元素進行累積。
#py2中, reduce是內(nèi)置高階函數(shù);
#py3中, reduce函數(shù)需要導(dǎo)入;
from functools import reduce

nums_add = reduce(lambda x, y: x + y, list(range(1, 101)))
print(nums_add)

#需求: 通過reduce函數(shù)時先階乘
N = 5
result = reduce(lambda x, y: x * y, list(range(1, N + 1)))      # 1, 2, 3, 4, 5
print(result)

filter() 函數(shù)

filter(function or None, iterable)
用于過濾序列,過濾掉不符合條件的元素,返回由符合條件元素組成的新列表。
python學(xué)習(xí)之高級特性

08_內(nèi)置高階函數(shù)filter.py

#filter() 函數(shù)用于過濾序列,過濾掉不符合條件的元素,返回由符合條件元素組成的新列表。
result = filter(lambda x: x % 3 == 0, list(range(1, 11)))
print(list(result))

result = [item for item in range(1, 11) if item % 3 == 0]
print(result)
def is_prime(x):
    """判斷x是否為質(zhì)數(shù)"""
    pass

result = filter(is_prime, list(range(2, 101)))
print(list(result))"""

sorted() 函數(shù)

sorted(iterable, key=None, reverse=False)
key: 主要是用來進行比較的元素,只有一個參數(shù)
reverse: 排序規(guī)則,True 降序 ,F(xiàn)alse 升序(默認)。
對所有可迭代的對象進行排序操作。返回重新排序的列表。
sort() 和 sorted() 的區(qū)別:

(1)排序?qū)ο蟛煌? sort 是應(yīng)用在 list 上的方法,sorted 可以對所有可迭代的對象進行排序操作。
(2)返回值不同:
list 的 sort 方法返回的是對已經(jīng)存在的列表進行操作,無返回值
內(nèi)建函數(shù) sorted 方法返回的是一個新的 list,而不是在原來的基礎(chǔ)上進行的操作。

09_內(nèi)置高階函數(shù)sorted.py

import random
def is_odd(x):
    """判斷是否為偶數(shù)"""
    return x % 2 == 0
#排序需求: 偶數(shù)排前面, 奇數(shù)排后面
nums = list(range(10))  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
random.shuffle(nums)
print("排序前: ", nums)
nums.sort(key=lambda x: 0 if is_odd(x) else 1)
print("排序后: ", nums)
#sorted可以對所有可迭代的對象進行排序操作。
result = sorted({2, 3, 4, 5, 1})
print(list(result))"""
向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI