装饰器和单例模式练习

# -*- coding=utf-8 -*-
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2020/5/15 23:46
# @Author : "小多肉"
# @Email : 1021181701@qq.com

"""
TODO:
1、实现一个网络请求超时重试的装饰器,装饰下面的功能函数
如果请求网络超时,或者连接超时,可以重新发送请求,如果重试三次之后,还是超时,抛出对应的异常

def request_http(url):
    import requests
    return requests.get(url, timeout=5)

2、请设计一个装饰器,接收一个int类型的参数number,可以用来装饰任何的函数, 
如果函数运行的时间大于number,则打印出函数名和函数的运行时间 (面试真题)

3、 请设计一个装饰器 ,可以给函数扩展登录认证的功能(提示数账号密码,然后进行校验),
多个函数同时使用这个装饰器, 调用函数的时候,只要登录成功一次,
后续的函数无需再进行登录(默认的认证账号:qwe123,密码:123456)
(面试真题)
"""
# ###########################第一题##################################


def retry(fun):
    def wrapper(*args, **kwargs):
        for i in range(4):
            try:
                res = fun(*args, **kwargs)
            except Exception as e:
                if i == 0:
                    print(f"第一次请求失败!!!{e}
正在尝试为您重新发起请求。")
                else:
                    print(f"第{i}次重试……")
                    if i == 3:
                        raise e
                continue
            else:
                print("请求成功!!!", res)
                break 
    return wrapper

@retry
def request_http(url):
    import requests
    return requests.get(url, timeout=5)

# request_http("http://www.google.com.hk")
print("---------------------第一题-------------------------")
request_http("https://www.python.org/doc/")
print("---------------------第一题异常情况-------------------------")
try:
    request_http("http://www.google.com.hk")
except Exception:
    print("重试三次都失败了,抛出异常。")

# ############################第二题#################################
"""
2、请设计一个装饰器,接收一个int类型的参数number,可以用来装饰任何的函数, 
如果函数运行的时间大于number,则打印出函数名和函数的运行时间 (面试真题)
"""
import time

def performance(number):
    def decorator(fun):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            print("-------start--------", start_time)
            fun(*args, **kwargs)
            end_time = time.time()
            print("-------end--------", end_time)
            dur_time = end_time - start_time
            if dur_time > number:
                print(f"{fun.__name__}函数的运行时间为:{dur_time}")
        return wrapper
    return decorator

@performance(0.1)
def request_http2(url):
    import requests
    return requests.get(url)

print("-------------------第二题---------------------------")
request_http2("http://www.google.cn/")

# ############################第三题#################################
"""
3、 请设计一个装饰器 ,可以给函数扩展登录认证的功能(提示数账号密码,然后进行校验),
多个函数同时使用这个装饰器, 调用函数的时候,只要登录成功一次,
后续的函数无需再进行登录(默认的认证账号:qwe123,密码:123456)(面试真题)
"""
LOGIN_FLAG = 0
def login_check(func):
    def wrapper(*args, **kwargs):
        global LOGIN_FLAG
        if func.__name__ == "login":
            func()
        elif LOGIN_FLAG:
            func(*args, **kwargs)
        else:
            print("检测到您未成功登录,请先登录。")
    return wrapper

@login_check
def login():
    account = input("请输入账号:")
    password = input("请输入密码:")
    if account == "qwe123" and password == "123456":
        global LOGIN_FLAG
        LOGIN_FLAG = 1
    else:
        print("用户名或密码错误!登录失败!!!")

@login_check
def func1():
    print("函数1")

@login_check
def func2():
    print("函数2")

@login_check
def func3():
    print("函数3")

print("------------第三题-----------")
func1()
login()
func2()
func3()
原文地址:https://www.cnblogs.com/momoon/p/12911869.html