python之旅--装饰器

装饰器

定义:本质是函数,装饰其它函数,为其它函数添加附加功能。

原则:

  1.不能修改被装饰的函数的源代码。

  2.不能修改被装饰的函数的调用方式。

  装饰器对被装饰的函数是完全透明的。

#统计函数运行时间的装饰器
import time
def timmer(func):
    def warpper(*args,**kwargs):
        start_time = time.time()
        func(*args,**kwargs)
        stop_time = time.time()
        print("The func run time is %s " %(stop_time-start_time))
    return warpper

@timmer
def test1():
    time.sleep(1)
    print("in the test1")

test1()

#运行结果
#in the test1
#The func run time is 1.000936508178711 

装饰圈 = 高阶函数 + 嵌套函数

1.函数即变量

变量都是存在内存中,如x=1,以房间和门牌号为例,门牌号为x,房间为1。

加一个变量y且y=x 即门牌号为y,房间为1

解释器内存回收机制即门牌号没有了就回收内存。

函数在内存中存放方式:门牌号为函数名,房间为函数体。

2.高阶函数

  A 把一个函数名当作实参传给另外一个函数。

  在不修改被装饰函数源代码的情况下为其添加功能 

#例 统计函数运行时间
import time
def bar():
    time.sleep(1)
    print("In the bar")

def test(func):
    start_time = time.time()
    func() #相当于 bar()
    stop_time = time.time()
    print("The func run time is %s " %(stop_time - start_time))

test(bar) #bar其实就是一个函数的内存地址
# In the bar
# The func run time is 1.0003819465637207 

  B 返回值中包含函数名。

   不修改函数的调用方式

import time
def bar():
    time.sleep(1)
    print("In the bar")
def test(func):
    print(func)
    return func
test(bar) #得到bar函数的内存地址 内存地址+括号可以运行函数
bar = test(bar)
bar() #run bar 

3.嵌套函数

#嵌套函数 在一个函数里面用def 定义一个函数
def foo():
    print("In the foo")
    def bar():
        print("In the bar")
    bar()
foo()

#局部作用域与全局作用域的访问顺序
x = 0
def grandpa():
    x = 1
    def dad():
        x = 2
        def son():
            x = 3
            print(x)
        son()
    dad()
grandpa()

装饰器

#用装饰器实现函数运行时间
#装饰器分步实现 step1 改变了调用方式
import time
def test1():
    time.sleep(1)
    print("In the test1")
def test2():
    time.sleep(1)
    print("In the test2")

def deco(func):
    start_time = time.time()
    func()
    stop_time = time.time()
    print("The func run time is %s" %(stop_time-start_time))

deco(test1)
deco(test2)

#step2 不改变源代码不改变调用方式
import time
def test1():
    time.sleep(1)
    print("In the test1")
def test2():
    time.sleep(1)
    print("In the test2")

def timmer(func):
    def deco():
        start_time = time.time()
        func() #run test1
        stop_time = time.time()
        print("The func run time is %s" %(stop_time-start_time))
    return deco

test1 = timmer(test1)
test2 = timmer(test2)
test1()
test2()

#step3 在python中使用语法糖 @装饰器名
#在需要添加新功能的函数前面加上语法糖 
#可以用debug查看逻辑变化及顺序
import time
def timmer(func):
    def deco():
        start_time = time.time()
        func() #run test1
        stop_time = time.time()
        print("The func run time is %s" %(stop_time-start_time))
    return deco

@timmer #语法糖 
def test1():
    time.sleep(1)
    print("In the test1")
@timmer
def test2():
    time.sleep(1)
    print("In the test2")

test1()
test2()

#有参数的函数被装饰
import time
def timmer(func):
    def deco(*args,**kwargs):
        start_time = time.time()
        func(*args,**kwargs) #run test1
        stop_time = time.time()
        print("The func run time is %s" %(stop_time-start_time))
    return deco

@timmer
def test1():
    time.sleep(1)
    print("In the test1")
@timmer
def test2(name):
    time.sleep(1)
    print("In the test2" ,name)

test1()
test2('test')

#用户登陆认证装饰器 part1
user,passwd = 'test','123'
def auth(func):
    def wrapper(*args,**kwargs):
        username = input("Usernmae:").strip()
        password = input("Password:").strip()
        if user == username and passwd == password:
            print("\033[32;1mUser has passed\033[0m")
            res = func(*args,**kwargs)
            return res
        else:
            exit("\033[31;1mInvalid username or passwd\033[0m")
    return wrapper
@auth
def index():
    print("Welcome to index page")
@auth
def home():
    print("Welcome to home page")
    return "from home"
@auth
def bbs():
    print("Welcome to bbs page")

index()
home()
print(home())
bbs()

#区分本地和ldap登陆 
user,passwd = 'test','123'
def auth(auth_type):
    def outer_wrapper(func):
        def wrapper(*args,**kwargs):
            if auth_type == "local":
                username = input("Usernmae:").strip()
                password = input("Password:").strip()
                if user == username and passwd == password:
                    print("\033[32;1mUser has passed\033[0m")
                    res = func(*args,**kwargs)
                    return res
                else:
                    exit("\033[31;1mInvalid username or passwd\033[0m")
            elif auth_type == "ldap":
                print("The ldap")
        return wrapper
    return outer_wrapper

def index():
    print("Welcome to index page")
@auth(auth_type="local")
def home():
    print("Welcome to home page")
    return "from home"
@auth(auth_type="ldap")
def bbs():
    print("Welcome to bbs page")

index()
home()
print(home())
bbs()

猜你喜欢

转载自www.cnblogs.com/wangzihong/p/9114167.html