首页 > 代码库 > Long Way To Go 之 Python 4

Long Way To Go 之 Python 4

装饰器decorator

    (“器”代表的是函数)

定义本质是函数

作用:用来装饰其他函数  in other words,为其他函数添加附加功能

        (eg. 假如程序已上线,如果想新增功能,但是又不能改源代码)

原则:

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

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

组成高阶函数+嵌套函数 --> 装饰器

 

Q:  高阶\嵌套函数是个什么鬼???

 

高阶函数:

      1.把一个函数当做实参传给另一个函数(在不修改被装饰函数源代码的情况下为其添加功能)        

技术分享
import time
def bar():
    time.sleep(3)
    print("in the bar")

def test1(func):
    start_time = time.time()
    func()   # run bar()
    stop_time = time.time()
    print("the func run time is %s"%(stop_time -start_time))   # 统计的是bar的运行时间

test1(bar) # func = bar 所以可以进行func()      传的内存地址
test1(bar())   # 把bar()的返回值传进去了        传的返回值
# BUT !调用方式变了,不是装饰器
View Code

 

      2.返回值中包含函数名(不修改函数的调用方式)

技术分享
import time
def bar():
    time.sleep(3)
    print("in the bar")

def test2(func):
    print(func) # 打印func的内存地址,也就是bar的内存地址
    return func # return bar的内存地址

bar = test2(bar)
bar() # run bar
View Code

 

嵌套函数:

     在一个函数的函数体内用def去申请另一个函数

技术分享
#嵌套函数
def foo():
    print("in the foo")
    def bar():    # 相当于局部变量,所以不能在外面直接调用bar(),所以要写在里面
        print("in the bar")
    bar()
foo()


# 这个不是函数的嵌套,这叫函数的调用
def test1():
    test2()
test1()
View Code

 

EXAMPLE 1

优化(@timmer)

技术分享
def timer(func): #timer(test1)   把test1的内存地址传给func,func = test1
    def deco():
        start_time = time.time()
        func()      # run test1
        stop_time = time.time()
        print("the func run time is %s"%(start_time-stop_time))
    return deco   # 返回这个函数的内存地址

@timer   # 这就相当于  test1 = timer(test1)
def test1():
    time.sleep(3)
    print("in the test1")

@timer
def test2():
    time.sleep(3)
    print("in the test2")

test1()  
test2()  # 其实调用的是deco这个函数,因为timer(test1)的返回值是deco的内存地址
View Code

优化(调用时传入多个参数)

技术分享
def timer(func): #timer(test1)   把test1的内存地址传给func,func = test1
    def deco(*args,**kwargs):
        start_time = time.time()
        func(*args,**kwargs)      # run test1
        stop_time = time.time()
        print("the func run time is %s"%(start_time-stop_time))
    return deco   # 返回这个函数的内存地址

@timer   # 这就相当于  test1 = timer(test1) = deco
def test1():
    time.sleep(1)
    print("in the test1")

@timer   # test2 = timer(test2)   =  deco
# test2() = deco()     所以在deco里加args
def test2(name,age):
    print("test2:",name,age,)

test1()
test2("alex",22)
View Code

 

EXAMPLE 2 !!

技术分享
import time

user,passwd = "alex","abc123"
def auth(auth_type):
    print("auth func:",auth_type)
    def outer_wrapper(func):
        def wrapper(*args,**kwargs):
             print("wrapper func args:",*args,**kwargs)
             if auth_type =="local":
                username = input("username:").strip()
                password = input("password:").strip()
                if user == username and passwd == password:
                   print("\033[32;1mUser has passed authenfication\033[0m")
                   res = func(*args,**kwargs) # return from home
                   print("------after authenficaiton")
                   return res
                else:
                   exit("\033[31;1mInvalid username or password\033[0m")
             elif auth_type == "ladp":
                   print("毛线ldap,不会------")
        return wrapper
    return outer_wrapper


def index(): # 首页
    print("welcome to index page")

@auth(auth_type = "local")   # 本地认证  & home = wrapper()
def home(): # 用户登录后的首页
    print("welcome to home page")
    return "from home"


@auth(auth_type = "ldap")   # 远程认证
def bbs(): # 论坛
    print("welcome to bbs page")

index()
print(home())   # return None  如果没有return func()的话
bbs()
View Code

 

 

ps:

函数及变量

技术分享
# 没问题
def bar():
    print("in the bar")
def foo():
    print("in the foo")
    bar()

foo()



# bar定义到下面也是可以运行的
def foo():
    print("in the foo")
    bar()
def bar():
    print("in the bar")

foo()



# 会报错,因为函数和变量一样,是先定义,在调用。所以会报错
def foo():
    print("in the foo")
    bar()

foo()
def bar():
    print("in the bar")
View Code

 

 

生成器generator

    原理:只有在调用时才会生成相应的数据(假如一个大数据,只循坏了前5次,那么后面的数据是没有准备好的)

    作用:省内存

    特点:生成器只记住当前位置(不管前后),不能后退回返,也不能跳着走

 

    只有一个next方法: __next__()

 

 

 

 

 

 

ps:

列表生成式

>>>print([i*2 for i in range(10)])
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>>
>>>[func(i) for i in range(10)] # 传函数也可以

 

 

 

 

 

 

 

    

    

Long Way To Go 之 Python 4