zoukankan      html  css  js  c++  java
  • 装饰器

    装饰器: 在不改变原有代码的基础上,实现功能的扩充.用原函数扩展新功能,用新功能去代替旧功能,用@表示

    情况一: 基本用法(闭包函数),通过闭包函数来扩展新功能
    def kuozhan(tree):
        def new_tree():
            print("旁边有小草")
            tree()
            print("旁边有小花")
        return new_tree
    
    def tree():
        print("一棵大树")
    
    tree = kuozhan(tree)
    tree()
    # 旁边有小草
    # 一棵大树
    # 旁边有小花

    情况二:用@符号来表示装饰器,@符号自动把下面的函数传递给装饰器,把新函数返回,让新函数代替旧函数,以实现功能的扩充

    def kuozhan(tree):
        def new_tree():
            print("旁边有小草")
            tree()
            print("旁边有小花")
        return new_tree
    
    @kuozhan
    def tree():
        print("一棵大树")
    
    tree()
    # 旁边有小草
    # 一棵大树
    # 旁边有小花

    情况三:装饰器的嵌套

    def kuozhan2(tree):
        def new_tree():
            print("小草会长成草坪5")
            tree()
            print("小花会长成花卉4")
        return new_tree
    
    def kuozhan1(tree):
        def new_tree():
            print("旁边有小草3")
            tree()
            print("旁边有小花2")
        return new_tree
    
    @kuozhan1 # 再到装饰器1,返回3,5,1,4,2
    @kuozhan2 # 先到装饰器2,返回5,1,4
    def tree():
        print("一棵大树1")
    
    tree()
    # 旁边有小草3
    # 小草会长成草坪5
    # 一棵大树1
    # 小花会长成花卉4
    # 旁边有小花2

    情况四:用装饰器修饰带有参数的函数,装饰器内的函数也需有一一对应的参数

    def kuozhan(tree):
        def new_tree(name):
            print("{}旁边有小草".format(name))
            tree(name)
            print("旁边有小花")
        return new_tree
    
    @kuozhan
    def tree(name):
        print("{name}有一棵大树".format(name=name))
    
    tree("bob")
    # bob旁边有小草
    # bob有一棵大树
    # 旁边有小花

    情况五:用装饰器修饰带有参数返回值的函数

    def kuozhan(person):
        def new_person(*args,**kwargs):
            print("新学期的开始")
            lst = person(*args,**kwargs)
            print("大家加油")
            return lst
        return new_person
    
    @kuozhan
    def person(*args,**kwargs):
        list1 = ["bob","alice","jack"]
        for i in args:
            print("班主任是:"+i)
        return [(k,v) for k,v in kwargs.items() if k in list1 ]
    res = person("张三","李四",bob=18,alice=19,jack=20,lisa=21)
    print(res)
    # 新学期的开始
    # 班主任是:张三
    # 班主任是:李四
    # 大家加油
    # [('bob', 18), ('alice', 19), ('jack', 20)]

    情况六:用类装饰器来拓展原函数

    # 方式一: 用类.方法来调
    class Kuozhan():
        def kuozhan1(tree):
            print("大树旁边有小草")
            tree()
            print("大树旁边有小花")
    
    @Kuozhan.kuozhan1
    def tree():
        print("我是一颗大树")
    # 大树旁边有小草
    # 我是一颗大树
    # 大树旁边有小花
    
    # 方式二: 直接用类()调,配合__call__方法
    class Kuozhan():
        def __call__(self,tree):
            return self.kuozhan2(tree)
        
        def kuozhan1(tree):
            print("大树旁边有小草")
            tree()
            print("大树旁边有小花")
            
        def kuozhan2(self,tree):
            print("小草长大成草坪")
            tree()
            print("小花长大成花卉")
    
    @Kuozhan()
    def tree():
        print("我是一颗大树")
    # 小草长大成草坪
    # 我是一颗大树
    # 小花长大成花卉

    情况七:带有参数的函数装饰器

    def outter(num):
        def kuozhan(func):
            def new_tree(self):
                print("大树小的时候是小树")
                res = func(self)
                print("小树长大了是大树")
                return res
    
            def new_grass(self):
                print("小草小的时候是一棵草")
                res = func(self)
                print("小草长大了是草坪")
                return res
    
            if num == 1:
                return new_tree
            elif num == 2:
                return new_grass
            elif num == 3:
                return "我把flower方法变成了属性"
        return kuozhan
    
    
    class Plant():
        @outter(1)
        def tree(self):
            print("我是一颗大树")
    
        @outter(2)
        def grass(self):
            print("我是一颗小草")
    
        @outter(3)
        def flower(self):
            print("我是一朵花")
    
    obj = Plant()
    obj.tree()
    # 大树小的时候是小树
    # 我是一颗大树
    # 小树长大了是大树
    obj.grass()
    # 小草小的时候是一棵草
    # 我是一颗小草
    # 小草长大了是草坪
    print(obj.flower)
    # 我把flower方法变成了属性

    情况八:带有参数的类装饰器

    class Kuozhan():
        name = "大树"
        def __init__(self,num):
            self.num = num
        def __call__(self,cls):
            if self.num == 1:
                return self.new_func1(cls)
            elif self.num == 2:
                return self.new_func2(cls)
        def grass(self):
            print("大树旁边有小草")
    
        def new_func1(self,cls):
            def func1():
                cls.name = Kuozhan.name
                cls.grass = Kuozhan.grass
                return cls()
            return func1
    
        def new_func2(self,cls):
            def func2():
                if "mytree" in cls.__dict__:
                    res = cls.mytree()
                    cls.mytree = res
                    return cls()
            return func2
    
    # 形式一: 为类添加方法或者属性
    @Kuozhan(1)
    class Tree():
        def mytree():
            return "我是一颗大树"
    obj = Tree()
    print(obj.name) # 大树
    obj.grass() # 大树旁边有小草
    
    # 形式二: 将类的方法改为属性
    @Kuozhan(2)
    class Tree():
        def mytree():
            return "我是一颗大树"
    obj = Tree()
    print(obj.mytree) # 我是一颗大树
    面向对象中的方法:  普通方法,绑定方法,静态方法
    class Tree():
        #普通方法: 可以有参也可以无参,相当于普通的函数
        def grow():
            print("小树长成大树")
    
        # 绑定方法: (对象) 自动传递参数为对象
        def green(self):
            print("大树有成片的绿叶子")
    
        # 绑定方法: (类) 自动传递参数为类
        @classmethod
        def sing(cls):
            print(cls)
            print("风吹叶子的声音像唱歌")
    
        # 静态方法: 不管是对象还是类,都可以调用,默认不会传递任何参数
        @staticmethod
        def air():
            print("大树可以净化空气")
    obj = Tree()
    Tree.grow() # 小树长成大树
    
    obj.green() # 大树有成片的绿叶子  绑定方法推荐用对象调
    Tree.green(111) # 大树有成片的绿叶子
    
    Tree.sing()  # 绑定到类的方法推荐用类调
    # <class '__main__.Tree'>
    # 风吹叶子的声音像唱歌
    obj.sing()
    # <class '__main__.Tree'>
    # 风吹叶子的声音像唱歌
    
    # 静态方法有参数时保证参数一一对应.在类外,为对象添加的方法都是静态方法
    Tree.air() # 大树可以净化空气
    obj.air() # 大树可以净化空气
    porperty装饰器:
            功能: 将方法变成属性使用,自动触发
            作用: 控制属性的获取(@property),设置(@属性名.setter),删除(@属性名.deleter)操作
            意义: 间接增加成员的安全性,可以通过自定义逻辑对成员进行控制
    
    
    # 方式一: 使用相同的名称
    class Myname():
        def __init__(self,name):
            self.name = name
        # 获取属性
        @property
        def username(self):
            return self.name
        #设置属性
        @username.setter
        def username(self,strval):
            self.name = strval
        #删除属性
        @username.deleter
        def username(self):
            pass
    obj = Myname("bob")
    print(obj.name) #bob 自动触发property
    
    obj.name = "alice"
    print(obj.name) #alice  自动触发设置方法,strval接收alice
    
    del obj.username
    print(obj.name) # alice  因为自动触发的删除属性,阻止了删除
    
    # 方式二:
    class Myname():
        def __init__(self,name):
            self.name = name
        # 获取属性
        @property
        def get_username(self):
            return self.name
        #设置属性
        def set_username(self,strval):
            self.name = strval
        #删除属性
        def del_username(self):
            pass
        username = property(get_username,set_username,del_username)
    obj = Myname("bob")
    print(obj.name)  # bob
    
    obj.name = "jack"
    print(obj.name)  # jack
    
    del obj.username
    print(obj.name) # jack
    
    
     
  • 相关阅读:
    1334: 好老师
    poj 2255 Tree Recovery
    2006浙大:简单计算器
    POJ1001(C++处理大数)
    HDU2159(二维完全背包)
    POJ2080:Calendar(计算日期)
    2008上交:Day of Week
    POJ1365:质因数分解
    VIJOS:P1706(舞会)
    POJ2449:K短路
  • 原文地址:https://www.cnblogs.com/fdsimin/p/13027135.html
Copyright © 2011-2022 走看看