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

    """
    装饰器 : 为原函数去扩展新功能,用新函数去替换旧函数
    作用   : 在不改变原代码的前提下,实现功能上的扩展
    符号   : @(语法糖)
    """

    一、装饰器的基本用法

    def kuozhan(func):
        def newfunc():
            print("厕所前,蓬头垢面")
            func()
            print("厕所后,精神抖擞")
        return newfunc
    
    def func():
        print("我是宋云杰")
    
    
    func = kuozhan(func) # func = newfunc
    func() # newfunc()

    二、@符号的使用

    """
    @符号作用:
        (1) 可以自动把@符号下面的函数当成参数传递给装饰器
        (2) 把新函数返回,让新函数去替换旧函数,以实现功能上的扩展(基于原函数)
    """
    def kuozhan(func):
        def newfunc():
            print("厕所前,牛头马面")
            func()
            print("厕所后,黑白无常")
        return newfunc
    
    @kuozhan
    def func():
        print("我是高雪峰")
    
    func()

    三、装饰器的嵌套

    def kuozhan1(func):
        def newfunc():    
            print("厕所前,人模狗样1")
            func()
            print("厕所后,斯文败类2")
        return newfunc
        
    def kuozhan2(func):
        def newfunc():
            print("厕所前,洗洗手3")
            func()
            print("厕所后,簌簌口4")
        return newfunc
        
    @kuozhan2
    @kuozhan1
    def func():
        print("我是葛龙0")
    
    func()

    四、用装饰器扩展带有参数的原函数

    print("<========================>")
    def kuozhan(func):
        def newfunc(who,where):
            print("厕所前,萎靡不振")
            func(who,where)
            print("厕所后,兽性大发")
            
        return newfunc
    
    @kuozhan
    def func(who,where):
        print("{}在{}解手".format(who,where))
    
    func("孙致和","鸟窝") # func = newfunc => func("孙致和","鸟窝") <=> newfunc("孙致和","鸟窝")

    五、用装饰器扩展带有参数和返回值的原函数

    def kuozhan(func):
        def newfunc(*args,**kwargs):
            print("厕所前,饥肠辘辘")
            res = func(*args,**kwargs)
            print("厕所后,酒足饭饱")
            return res
        return newfunc
            
    @kuozhan
    def func(*args,**kwargs):
        lst = []
        dic = {"gaoxuefeng":"高雪峰","sunzhihe":"孙致和","gelong":"戈隆"}
        
        # 解手的地点遍历出来
        for i in args:
            print("拉屎的地点:",i)
        
        for k,v in kwargs.items():
            if k in dic:
                strvar = dic[k] + "留下了" + v + "黄金"
                lst.append(strvar)
        return lst
    
    lst = func("电影院","水下",gaoxuefeng = "15g",sunzhihe = "15顿",gelong="15斤")
    print(lst)

    六、用类装饰器来拓展原函数

    class Kuozhan():
        def __call__(self,func):        
            return self.kuozhan2(func)
        
        def kuozhan1(func):
            def newfunc():
                print("厕所前,老实巴交")
                func()
                print("厕所后,咋咋乎乎")
            return newfunc
    
        def kuozhan2(self,func):
            def newfunc():
                print("厕所前,唯唯诺诺")
                func()
                print("厕所后,重拳出击")
            return newfunc
    
    # 方法一
    """"""
    @Kuozhan.kuozhan1
    def func():
        print("厕所进行中....")
    
    # func()
    
    # 方法二
    
    @Kuozhan()  # @obj => obj(func)
    def func():
        print("厕所进行中....")
    
    func()
    """
    print("<======分割线1=======>")
    Kuozhan() #=> obj
    def func():
        print("厕所进行中....")
    @符发动第一次发动技能:
        func 当成参数传递给obj => obj(func) 这种形式把对象当成函数使用 -> 直接触发__call__魔术方法
        调用结束之后.
    @符发动第二次发动技能:
        将返回的新函数 赋值给 旧函数,形成替换的效果
    func = newfunc
    func() <=> newfunc()
    """
    """
    print("<======分割线2=======>")
    <==相当于==>
    def func():
        print("厕所进行中....")
    obj = Kuozhan()
    func = obj(func)
    func()
    """

    七、带有参数的函数装饰器

    def outer(num):
        def kuozhan(func):    
            def newfunc1(self):
                print("厕所前,干净整齐")
                func(self)
                print("厕所后,一片狼藉")
            
            def newfunc2(self):
                print("厕所前,大腹便便")
                func(self)
                print("厕所后,满口雌黄")
                
            if num == 1:
                return newfunc1
            elif num == 2:
                return newfunc2
            elif num == 3:
                # 把func3方法变成属性
                return "我是女性"
    
        return kuozhan
    
    class MyClass():
        
        @outer(1) # => (1) kuozhan(func1) => newfunc1   (2) 发动技能做替换  func1 = newfunc1 
        def func1(self):
            print("向前一小步,文明一大步")
        
        @outer(2) # => (2) kuozhan(func2) => newfunc2   (2) 发动技能做替换  func2 = newfunc2 
        def func2(self):
            print("来也冲冲,去也冲冲")
        
        @outer(3) # => (3) kuozhan(func3) => "我是女性" (2) 发动技能做替换  func3 = "我是女性" 
        def func3(self):
            print("尿道外面,说明你短")
    
    obj = MyClass()
    print("<================>")
    obj.func1() # <=> newfunc1
    print("<================>")
    obj.func2()
    print("<================>")
    # obj.func3() error
    print(obj.func3)
    print(MyClass.func3)
    """
    套上outer这层函数就是为了保留1 2 3 三个参数,可以在闭包函数中使用
    调用outer 结束之后,才是返回正常的装饰器kuozhan
    此刻,@符第一次发动技能,
        把func1当成参数传递给kuozhan , 返回newfunc1
    然后,@符第二次发动技能,
        将返回的newfunc1替换原来func1
    obj.func1() => newfunc1(obj)
    
    if num == 1 返回闭包函数newfunc1
    if num == 2 返回闭包函数newfunc2 
    来做替换
    
    obj.func3 在执行时,装饰器已经把func3变成了属性func3 = "我是女性"
    所以obj.func3  或者 MyClass.func3 都是"我是女性" 字符串.
    obj.func3 => return "我是女性"
    MyClass.func3 => return "我是女性"
    """
    解析

    八、带有参数的类装饰器

    """
    如果参数是1,就为当前类添加成员属性和方法
    如果参数是2,就把原方法run变成属性
    """
    class Kuozhan():
        money = "贵族厕所,每小时1000元,贵族厕所欢迎您来,欢迎您再来"
        
        def __init__(self,num):
            self.num = num
        
        def __call__(self,cls):
            if self.num == 1:
                return self.newfunc1(cls)
                
            elif self.num == 2:
                return self.newfunc2(cls)
        
        def ad(self):
            print("贵族茅厕,茅厕中的百岁山")
        
        def newfunc1(self,cls):
            def newfunc():
                # 为当前cls这个类,添加属性
                cls.money = Kuozhan.money
                # 为当前cls这个类,添加方法
                cls.ad = Kuozhan.ad
                return cls()
            return newfunc
        
        def newfunc2(self,cls):
            def newfunc():
                # 判断run成员是否在类当中
                if "run" in cls.__dict__:
                    # 调用类中的方法,得到对应的返回值
                    res = cls.run()
                    # 把返回值重新赋值到run属性上
                    cls.run = res# cls.run = "亢龙有悔"
                    
                    return cls()
            return newfunc

    参数1

    class MyClass():
        def run():
            return "亢龙有悔"
    obj = MyClass()
    print(obj.money)
    obj.ad()
    """
    参数为1,代码解析:
    @Kuozhan(1)  => @obj => @符第一次发动技能:
        把MyClass当成参数传递给obj => obj(MyClass) => return self.newfunc1(cls) => return newfunc
                    @obj => @符第二次发动技能:
        实现替换效果,将 MyClass = newfunc 
        
    obj = MyClass() = newfunc() = cls() = 对象
    对象.属性   obj.money
    对象.方法   obj.ad()
    """
    
    '''
    # 全局范围内类
    class Ceshi():
        ad = 10
    obj = Ceshi()
    print(obj.ad)
    
    def func(cls):
        cls.money = 100
        return cls()
    # 把类当成参数传递到函数当中,在局部空间中,形成独立的副本
    obj = func(Ceshi)
    # 把类变量Ceshi 变成字符串
    Ceshi = "你好"
    # 发现局部空间中类对象中的成员,并没有受到影响
    print(obj.money) # 100
    '''
    解析

    参数2

    @Kuozhan(2)
    class MyClass():
        def run():
            return "亢龙有悔"
    
    obj = MyClass()
    print(obj.run)
    """
    参数为2,代码解析:
    @Kuozhan(2)  => @obj => @符第一次发动技能:
        把MyClass当成参数传递给obj => obj(MyClass) => return self.newfunc2(cls) => return newfunc
                    @obj => @符第二次发动技能:
        实现替换效果,将 MyClass = newfunc 
        
    obj = MyClass() = newfunc() = cls() = 对象
    对象.run = "亢龙有悔"
    """

    九、面向对象当中的方法

    """
    普通方法: 有参或者无参,如果是无参,只能类来调用
    绑定方法: (1) 绑定到对象(自动传递对象参数) (2) 绑定到类(自动传递类参数)
    静态方法: 无论是对象还是类,都可以调用此方法,而不会默认传递任何参数;
    """
    class Cat():
        name = "tom"
        
        # 普通方法
        def mai_meng():
            print("小猫会卖萌")
            
        # 绑定方法(对象)
        def attack(self):
            print("小猫会卅(sua)人")
            
        # 绑定方法(类)
        @classmethod
        def youmi(cls):
            print(cls)
            print("可以放大招,伤害最高")
            
        # 静态方法
        @staticmethod
        def jump(a,b,c,d,e):
            print("小猫会上树,抓老鼠")
    
    obj = Cat()

    普通方法

    # 普通方法 (无参方法只能类调用)
    Cat.mai_meng()
    # obj.mai_meng() error
    普通方法

    绑定方法(对象)

    obj.attack()
    Cat.attack(obj)
    绑定方法(对象)

    绑定方法(类)

    """对象和类都可以调用绑定到类的方法 推荐使用类来调用"""
    Cat.youmi()
    obj.youmi()
    # print(obj.__class__)
    绑定方法(类)

    静态方法

    obj.jump()
    Cat.jump()
    静态方法

     十、property

    """
    property  可以把方法变成属性使用
    作用: 控制属性的获取,修改,删除等操作
    变向的增加成员的安全性,可以通过自定义的逻辑进行控制
    
    自动触发 : 要求名字相同,同一个名字
        获取@property
        设置@属性名.setter
        删除@属性名.deleter
    """

    1、写法一

    class MyClass():
    
        def __init__(self,name):
            self.name = name    
        
        @property
        def username(self):
            # return self.name
            pass # 不获取
            
        @username.setter
        def username(self,val):
            # 在触发时:val =  朴飘乐  self就是本对象
            # self.name = val
            pass # 不设置
            
        @username.deleter
        def username(self):
            # print("删除方法被触发...")
            # del self.name
            pass # 不删
            
    
    obj = MyClass("朴一生")
    # 获取属性
    print(obj.username)
    # 设置属性
    obj.username = "朴飘乐"
    # 获取属性
    print(obj.username)
    
    # 删除属性
    del obj.username
    
    # 获取属性
    print(obj.username)

    2、写法二

    class MyClass():
    
        def __init__(self,name):
            self.name = name    
    
        # 获取方法
        def get_username(self):
            return self.name
            # pass # 不获取
    
        # 设置方法
        def set_username(self,val):
            self.name = val
            # pass # 不获取
            
        # 删除方法
        def del_username(self):
            # del self.name
            pass
    
        # property(获取方法,设置方法,删除方法)
        username = property(get_username,set_username,del_username)
    
    obj = MyClass("朴仁猛")
    # 获取操作
    print(obj.username)  # 自动触发get_username方法
    # 设置操作
    obj.username = "pdd" # 自动触发set_username方法
    # 获取操作
    print(obj.username)
    # 删除操作 
    del obj.username     # 自动触发del_username方法
    # 获取操作
    print(obj.username)
  • 相关阅读:
    K8s环境搭建
    opencv一些重要的函数或者类
    opencv的点的表示
    opencv矩阵的格式输出
    opencv矩阵运算(二)
    opencv矩阵运算(一)
    如何安装指定版本的Kubernetes
    使用minikube快速部署k8s集群
    Ceph 存储集群
    学习tcpIp必备的抓包工具wireshark
  • 原文地址:https://www.cnblogs.com/kongxiangqun/p/13455960.html
Copyright © 2011-2022 走看看