python—装饰器

一、装饰器的定义

  装饰他人的器具,在不修改被装饰对象的源代码,不修改被修饰对象的调用方式,为被装饰对象添加上新功能。

  利用装饰器(decorator),可在不侵入内部实现,甚至在不之情的情况下,插入扩展逻辑。

  利用装饰器功能,我们可以编写各种辅助开发工具,完成诸如调用跟踪、性能测试、内存检测等任务。当然,更多的时候用于模式设计,改善代码结构

二、装饰器的实现

1、不带参数装饰器

def login(func):
    def inner():
        your_name = input("name:")
        your_password = input("password:")
        if your_name == "ways" and your_password == "123":
            func()
            # return func()  如果被装饰的函数有返回值,则需要返回
        else:
            print("warning.....")
    return inner

def home():
    print("i am home")


def bbs():
    print("i am bbs")

# 1.执行login函数,并将 @login 下面的 函数 作为login函数的参数,即:@w1 等价于 login(chat)
# 所以,内部就会去执行:
#     def inner:
#         #验证
#         return chat()   # func是参数,此时 func 等于 f1
#     return inner     # 返回的 inner,inner代表的是函数,非执行函数
# 其实就是将原来的 f1 函数塞进另外一个函数中
# 2.将执行完的 loign 函数返回值赋值给@login下面的函数的函数名chat
@login
def chat():
    print("i am chat")

chat = login(chat)
chat()

2、装饰的的函数有参数

def login(func):
    def inner(*arg,**kwargs):
        your_name = input("name:")
        your_password = input("password:")
        if your_name == "ways" and your_password == "123":
            func(*arg,**kwargs)
            # return func(*arg,**kwargs)  如果被装饰的函数有返回值,则需要返回
        else:
            print("warning.....")
    return inner


def home():
    print("i am home")


def bbs():
    print("i am bbs")


@login
def chat(style):
    print("i am chat",style)


chat("我是聊天室")

3、装饰器带参数

def login(type):
    def outter(func):
        def inner(*arg,**kwargs):
            if type == "wx":
                print("我是bbs")
            else:
                print("我是chat")
            your_name = input("name:")
            your_password = input("password:")
            if your_name == "ways" and your_password == "123":
                func(*arg,**kwargs)
                # return func(*arg,**kwargs)  如果被装饰的函数有返回值,则需要返回
            else:
                print("warning.....")
        return inner
    return outter

def home():
    print("i am home")

@login("wx")
def bbs():
    print("i am bbs")

@login("qq")  #等价于  1,xx = login("qq") 其实就是outter  2,xx(chat)赋值给chat
def chat(style):
    print("i am chat",style)

chat("我是聊天室")
bbs()

4、基于类的装饰器

  在利用类定义装饰器时,我们用到了两个魔法方法。
    __init__():初始化方法,设置实例的相关属性,用于初始化一个实例对象,它接收一个函数作为参数,也就是被装饰的函数。

    __call()__:让一个实例对象可调用,就像函数调用一样,在调用被装饰函数时被调用,当一个类实现__call__方法时,这个类的实例就会变成可调用对象,让对象可以像函数那样调用。

# Author:ways
class Person:
    """
    不带参数的类装饰器
    """

    def __init__(self, fn):   # 形参fn 用来接收函数名:hh
        self.fn = fn
        print(self.fn)

    def __call__(self, *args, **kwargs):
        print(*args, **kwargs)
        print("函数执行前,我执行了")
        return self.fn(*args, **kwargs)
        print("函数执行后,我执行了")


@Person
def hh(x, y):
    print(x+y)


hh(1, 2)


class Logging:
    """
    带参数的类装饰器
    """

    def __init__(self, level="INFO"):   # 形参level,用来接收带参数装饰器的参数
        self.level = level

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            if self.level == "INFO":
                print("写正常日志")
            elif self.level == "DEBUG":
                print("写错误日志")
            return func(*args, **kwargs)
        return wrapper


@Logging("DEBUG")
def my_sum(x, y):
    print(x+y)


@Logging()
def my_subtraction(x,y):
    print(x-y)


my_sum(1, 2)
my_subtraction(1,2)

三、装饰器的小例子

1、装饰器装饰类中的方法

def my_warpper(func):

    def wrapper(self,*args, **kwargs):    # 传入self, 可以调用类中的方法和属性
        print(self.name)
        func(self,*args,**kwargs)

    return wrapper


class Person:

    def __init__(self, name, age):
        self.name = name
        self.age = age

    @my_warpper
    def print_info(self):
        print("%s:%s" % (self.name, self.age))


p = Person("ways",13)
p.print_info()

  

 

posted @ 2018-11-29 19:58  waystank  阅读(112)  评论(0)    收藏  举报