python裝飾器案例

普通裝飾器函數

計算函數的運行時間網絡

import requests
import time
import re

# 黑名單
filter_urls = ['www.hao123.com', 'www.baidu.com', 'www.jd.com']


def filter_url(url):  # 過濾url
    print(url)
    host = re.findall(r'http[s]?://(.*?)/', url)[0]
    return host in filter_urls


# 測試網絡請求的響應時間
def check_runtime(func):
    print('--初始裝飾--', func.__name__)

    def wrapper(url, *args, **kwargs):  # 閉包函數
        # 判斷url的 / path路徑是否存在,若是不存在,則追加/
        if url[7:].find('/') == -1 or url[8:].find('/') == -1:
            url += '/'

        if filter_url(url):
            print('---已取消下載--:此url已在黑名單中')
            return
        # 獲取開始請求的時間
        start_time = time.time()
        # result = func(*args, **kwargs)
        result = func(url, *args, **kwargs)
        delta_seconds = round(time.time() - start_time, 5)
        print('[執行時間%.5f]' % delta_seconds)
        return result

    return wrapper  # 返回一個包裝函數(包裝被裝飾函數的參數列表)


@check_runtime
def request(url):
    print('--開始請求--', url)
    resp = requests.get(url)
    print('--響應--', resp.status_code)
    print(resp.content)
    print('---完成請求---')


request('http://www.hao123.com')

帶參數裝飾器函數

帶參數裝飾器
設定權限(表) 8 查詢(QUERY) 4 增長(ADD) 2 刪除(DELETE) 1 修改(UPDATE) 0 無(NOSET)
設定角色——權限 admin 15(8421) | default, 8
設置用戶-角色 disen: admin | cici: defaultsession

假如當前session中登陸的用戶是cici,其權限值爲8閉包

import time

current_rights = 8  # 當前登陸用戶的權限值
PERMISSION = (('QUERY', 8), ('ADD', 4), ('DELETE', 2), ('UPDATE', 1), ('NOSET', 0))


def get_permission(permission):  # 根據權限名,返回權限值
    for item in PERMISSION:
        if permission in item:
            return item[1]


def check_permission(permission):
    print('--驗證權限--', permission)

    def wrapper1(func):
        print('--初始化裝飾函數--')

        def wrapper2(*args, **kwargs):
            # 檢查當前用戶的權限
            permission_value = get_permission(permission)
            # print(permission_value)
            if current_rights & permission_value != permission_value:
                print('當前用戶沒有權限')
                return
            result = func(*args, **kwargs)

            return result

        return wrapper2

    return wrapper1


@check_permission('DELETE')
def delete_order(id):
    print('當前用戶 cici 正在刪除訂單:', id)
    time.sleep(2)
    print('刪除成功!')


def add_permission(permission):  # 添加權限
    global current_rights
    current_rights |= get_permission(permission)


# add_permission('DELETE')
delete_order(1010111)

不帶參數的裝飾器類

class Check():
    def __init__(self, func):
        self.func = func

    def __call__(self, *args):
        self.func(*args)

@Check
def login(uid):
       print(uid)
被裝飾的方法會傳遞給裝飾器的構造器(__init__),而後在被裝飾的函數被調用的時候,裝飾器的__call__()方法就會執行
注意: 在裝飾階段,__init__ 函數執行,在被裝飾的方法被調用的時候,__call__ 執行

帶參數的裝飾器類

class Check():
    def __init__(self, name):
        self.name = name

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)

        return wrapper


@Check('log')
def login(uid):
    print(uid)
__call__()會在裝飾階段被調用

帶參數裝飾器實現爬蟲超時處理

import time
import requests
RETRY_TIME = 3
DOWNLOAD_DELAY = 2
class Retry(object):
    def __init__(self,retries = 3,delay=0):
        self.retries = retries
        self.delay=delay

    def __call__(self,func):
        def wrapper(*args, **kwargs):
            for i in range(self.retries):
                try:
                    result=func(*args,**kwargs)
                except Exception as e:
                    print(e)
                    time.sleep(self.delay)
                    continue
                else:
                    return result
        return wrapper


@Retry(RETRY_TIME,DOWNLOAD_DELAY)
def fetch(url):
    print(f'Start fetch {url}')
    resp = requests.get(url,timeout=5)
    print(resp.status_code)


fetch('http://www.baidu.com')
相關文章
相關標籤/搜索