装饰器

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

一. 装饰器的基本用法

def kuozhan(func):
    def newfunc():
        print('厕所前.蓬头垢面')
        func()
        print('厕所后,精神抖擞')
    return newfunc


def func():
    print('我是宋云杰')



func = kuozhan(func)
func()

二. @符号的使用

"""
@符号作用:
        (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()

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

def kuozhan(func):
    def newfunc(who,where):
        print('厕所前,未弥补站')
        func(who,where)
        print('厕所后,兽性大发')
     return newfunc

@kuozhan
def func(who,where)
        print('{}在{}接手'.format(who,where))


func('孙志和','鸟窝')

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

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 "我是女性"
"""
解析

八、带有参数的类装饰器

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

参数:

"""
参数为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
View Code

绑定到类:

obj.attack()
Cat.attack(obj)
View Code

绑定方法(类)

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

静态方法

obj.jump()
Cat.jump()
View Code

 十、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)

 

原文地址:https://www.cnblogs.com/whc6/p/14289317.html