诚意
诚意如你,当一诚的态度对待

导航

 

学习装饰器之前,请先把闭包函数学好,装饰器是闭包函数的应用

 

一:开放封闭原则

1:介绍开放封闭

所谓开放封闭原则就是软件实体应该对扩展开放,而对修改封闭。开放封闭原则是所有面向对象原则的核心。软件设计本身所追求的目标就是封装变化,降低耦合,而开放封闭原则正是对这一目标的最直接体现。

   开放封闭原则主要体现在两个方面:

   对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。

   对修改封闭,意味着类一旦设计完成,就可以独立其工作,而不要对类进行任何修改。

 

2:为什么要用到开放封闭原则呢?

软件需求总是变化的,世界上没有一个软件的是不变的,因此对软件设计人员来说,必须在不需要对原有系统进行修改的情况下,实现灵活的系统扩展。

 

3:如何做到对扩展开放,对修改封闭呢?

      实现开放封闭的核心思想就是对抽象编程,而不对具体编程,因为抽象相对稳定。让类依赖于固定的抽象,所以对修改就是封闭的;而通过面向对象的继承和多态机制,可以实现对抽象体的继承,通过覆写其方法来改变固有行为,实现新的扩展方法,所以对于扩展就是开放的。

      对于违反这一原则的类,必须通过重构来进行改善。常用于实现的设计模式主要有Template Method模式和Strategy 模式。而封装变化,是实现这一原则的重要手段,将经常变化的状态封装为一个类。

 

二:简单的装饰器

说了这么多,终于到了我们的装饰器了。

装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等应用场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

 

1:为什么要使用装饰器呢?

  装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展

  装饰器的本质:就是一个闭包函数

 

2:装饰器

(当老板让我们对一个函数的功能添加一些功能时,这会是什么情况呢?如果我们在这个函数里面修改,这违背了封闭原则;因为已经封装的代码轻易是不能修改的。那么我们又要扩展功能,那么我们在写一个函数不就行了函数名不和原来函数名相同。可是我们已经把原来的函数接口给了客户,难道我们还要因为一次功能修改在通知客户接口修改了,这肯定不行。这就难办了。新增加功能不能再原来的函数上修改,也不能新建一个不同的函数名接口实现功能。)

我们的目的是不改接口,还能实现新增功能

###################################################
def login(func):#新增的功能
    user=input("user:>>>")
    pwd=input("pwd:>>>")

    if user=='lilz' and pwd == '123':
        print ("success")
        func()
    else:
        print ("error")

def index():
    print("this is index")

login(index)  


###################偷梁换柱:实现了新增功能,不修改原代码########################

def login(func):#新增的功能:装饰器函数
    def inner():
        user = input("user:>>>")
        pwd = input("pwd:>>>")

        if user == 'lilz' and pwd == '123':
            print ("success")
            func()
        else:
            print ("error")
    return inner    #实现的关键点就是闭包函数能够应用外层函数的func

def index():  #原函数
    print("this is index")

index=login(index)  #此时的index已经不是原来的那个index了
index()  #应用接口

##########################  语法糖   #########################################
def login(func):#新增的功能:装饰器函数
    def inner():
        user = input("user:>>>")
        pwd = input("pwd:>>>")

        if user == 'lilz' and pwd == '123':
            print ("success")
            func()
        else:
            print ("error")
    return inner    #实现的关键点就是闭包函数能够应用外层函数的func

@login    #语法糖,等同于index=login(index)
def index():  #原函数
    print("this is index")

index()#引用

 

上面的语法糖看似巧妙,实际上源函数名已经发生改变,如何才能使得源函数名不发生改变呢?

 

三:带参数的被装饰器

 

import time
 
def show_time(func):
 
    def wrapper(a,b):
        start_time=time.time()
        func(a,b)
        end_time=time.time()
        print('spend %s'%(end_time-start_time))
 
    return wrapper
 
@show_time   #add=show_time(add)
def add(a,b):
 
    time.sleep(1)
    print(a+b)
 
add(2,4)

 

四:不定长参数

#***********************************不定长参数
import time

def show_time(func):

    def wrapper(*args,**kwargs):
        start_time=time.time()
        func(*args,**kwargs)
        end_time=time.time()
        print('spend %s'%(end_time-start_time))

    return wrapper

@show_time   #add=show_time(add)
def add(*args,**kwargs):

    time.sleep(1)
    sum=0
    for i in args:
        sum+=i
    print(sum)

add(2,4,8,9)

 

 

 

补充

1:classonlymethod

 

classmethod:

  对象.方法

  类.方法

classonlymethod: 

   类.方法

对比可以看到 classonlymethod的目的是为了用   类.方法   来调用方法,禁止  对象.方法  的方式调用

 

Django类装饰器

  

  

 

 

 

 

 

 


参考他人博文:Yuan先生

 

posted on 2018-10-27 21:51  诚意  阅读(228)  评论(0)    收藏  举报