Python 基础之八步理解装饰器

装饰器
装饰器:在不改变原有代码的情况下,为该原函数扩展新功能
特征:返回信函数,替换旧函数
语法:@ 语法糖
#(1) 装饰器原型
#例1:

def kuozhan(func):
    def newfunc():
        print("吃饭前,无精打采")
        func()
        print("吃饭后,精神百倍")
    return newfunc
def func():
    print("我是个吃货")
#手动的 把新函数 赋值 给 旧函数
func = kuozhan(func)
func()

#(2)装饰器 @
#例 2:

print("=====例2=====")
def kuozhan(func):
    def newfunc():
        print("吃饭前,无精打采")
        func()
        print("吃饭后,精神百倍")
    return newfunc
@kuozhan
def func():
    print("我是个吃货")
func()
print("=================")
步骤解析:
第一步:先把下面的func当成参数传递给kuozhan
第二步:把返回的新函数重新赋值给func
* 谁跟在@ 这个装饰器的下面,就会自动把谁当成参数传递
func = kuozhan(func)

#(3) 互相嵌套的装饰器函数
print("=================")

#例3:
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("我是一个白富美5")
func()  #3 1 5 2 4
print("=================")
#(4)带有参数的装饰器
原函数在扩展之前是几个参数,那么扩展之后也相应有几个参数
print("=================")

#例4:
def kuozhan(func):
    def newfunc(who,where):
        print("开饭前,安安静静")
        func(who,where)
        print("开饭后,热热闹闹")
    return newfunc

@kuozhan
def func(who,where):
    print("{}进{}吃饭".format(who,where))

func("one","食堂")
print("=================")

#(5)带有参数返回值的装饰器
‘‘‘通过装饰器改造之后,原函数返回什么,新函数返回什么‘‘‘
print("=================")
#例5:

def kuozhan(func):
    def newfunc(*args, **kwargs):
        print("留下之前")
        res = func(*args, **kwargs)
        print("留下之后")
        return res

return newfunc

@kuozhan
def func(*args, **kwargs):
    print(args)
    for i in args:
        print("藏东西的地点:", i)
    dic = {‘p1‘: "one", "p2": "two"}
    ‘‘‘

#法一:for循环再将元素加入列表得到:
    lst = []
    for k,v in dic.items():
        #如果k在dic这个字典里,说明这个字典存在这个键,然后我就通过键取值
        if k in dic:
        lst.append("{}留下了黄金{}".format(dic[k],v))

‘‘‘

#法二:推导式方法得出:
    lst = ["{}留下了黄金{}".format(dic[k], v) for k, v in kwargs.items() if k in dic]
    return lst
res = func("电影院", "游泳池", p1="15克", p2="150克")
print("=================")
print(res)
print("=================")

回忆以前的知识点:
*  ** 的魔术方法(函数调用处)
#例:

def func(a,b,c):
    print(a,b,c)

func(*[1,2,3])

def func(a=1,b=2,c=3,*,d=4):
    print(a,b,c)

func(**{"a":3,"b":4,"c":5,"d":6})
#(6)用装饰器修饰原函数
#例6:

class MyClass():

def __call__(self,func):
        #pass
        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
#方法一
@MyClass.kuozhan1
def func():
    print("吃饭进行时...  ....")
func()
#方法二:
@MyClass()
def func():
    print("吃饭进行时... ...")
func()

#代码解析:
先把 @ 符号右边的值算出来,在通过 @ 符号把下面的函数当成参数进行传递
@MyClass() 就相当于 @obj
func当成参数传递给obj => obj(func)
obj 当成一个函数再进行调用,自动触发__call__魔术方法
return newfunc
func = newfunc
func() 就相当于 newfunc()
#(7)带有参数的函数装饰器
#例7:

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:
            return "今天天气好晴朗哦"
    return kuozhan

class MyClass():
    @outer(1)
    def func1(self):
        print("走一步")
    @outer(2)
    def func2(self):
        print("再走一步")
    @outer(3)
    def func3(self):
        print("换个角度想想")
print("=================")
obj = MyClass()
obj.func1()
print("=================")
obj.func2()
print("=================")
print(obj.func3)

#代码解析:
outer(1)  => 返回kuozhan 函数
@kuozhan
func1

@符号开始发挥作用
func1当成参数进行传递,传给kuozhan中的func进行接收
obj.func1 = newfunc1
obj.func1() <====>newfunc1

@outer(3) => 返回kuozhan 函数
@kuozhan
func3
@符号开始发挥作用
func3当成参数进行传递,传给kuozhan中的func进行接收
obj.func3 = "今天天气好晴朗哦"
print(该值) [因为函数名可以作为变量使用]
#(8) 带有参数的类装饰器
如果传递的参数是1 ,我就为该类,添加成员属性和方法
如果传递的参数是2,我就把该类当中的run方法变成属性
#例8:
class KuoZhan():
    ad = "高档餐厅,欢迎您来,欢迎您再来"
    def __init__(self,num):
        self.num = num

def __call__(self,cls):
        if self.num == 1:
            return self.kuozhan1(cls) #newfunc 返回
        elif self.num == 2:
            return self.kuozhan2(cls)

def money(self):
        print("收费标准,最低消费每人500")

def kuozhan1(self,cls):
        def newfunc():
            #添加成员属性
            cls.ad = KuoZhan.ad
            #添加成员方法
            cls.money = KuoZhan.money
            return cls()
        return newfunc
    def kuozhan2(self,cls):
        def newfunc():
            #先判断run方法是否在cls当中
            if "run" in cls.__dict__:
                #调用一个类中得run方法拿到返回值"亢龙有悔"
                res = cls.run()
                #成员属性run从方法变成属性,值替换了
                cls.run = res #把"亢龙有悔" 进行替换赋值给run成员属性
            return cls()
        return newfunc

@KuoZhan(1) # @obj = > obj(MyClass)
class MyClass():
    def run():
        return "亢龙有悔"
obj = MyClass()
print(obj.ad)
obj.money()

"""

#代码解析:
KanZhan(1) => obj 自动触发init方法 ,存储num => self.num = num
@obj
@符发挥作用把MyClass 当成一个参数传递给obj => obj(MyClass)
触发__call__ 魔术方法,最后将newfunc进行返回
MyClass = newfunc 以前是类 现在是函数
obj = MyClass <========> newfunc()
obj = cls() #cls() 是一个对象,是以前MyClass 这个类的对象
"""
@KuoZhan(2)
class MyClass():
    def run():
        return "亢龙有悔"

obj = MyClass()
print(obj.run)
print("=====================================")
#外面全局的abc 与函数内部局部的 abc 两者不发生冲突,彼此独立
class abc():
    a = 19
def func(cls):
    cls.b = 20
    return cls
obj2 = func(abc)
print(abc().a)
abc = 68970
print(abc)
print(obj2.b)
print(obj2.a)

原文地址:https://www.cnblogs.com/hszstudypy/p/10925623.html

时间: 2024-10-13 11:14:36

Python 基础之八步理解装饰器的相关文章

Python基础(八)装饰器

今天我们来介绍一下可以提升python代码逼格的东西——装饰器.在学习装饰器之前我们先来复习一下函数的几个小点,方便更好的理解装饰器的含义. 一.知识点复习 1, 在函数中f1和f1()有什么不同,f1:表示的是将整个函数看作一个整体:f1():表示执行f1函数,下面通过一个例子来看一下: 1 2 3 4 5 def f1():     print('f1') f1                    #代表函数体本身,什么也不操作 f1()                  #代表执行函数

Day4 - Python基础4 迭代器、装饰器、软件开发规范

Python之路,Day4 - Python基础4 (new版) 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1,你怎么实现?你可能会想到2种方式 >>> a [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>

[python]在场景中理解装饰器

原来我也自己通过查资料,来学习python的装饰器,但是效果不好.因为没有接触过需要用到装饰器的场景,所以 一起的资料都只停留在纸面上,但是今天偶然看到了vimer的这篇文章:http://www.vimer.cn/2011/04/python%E8%A3%85%E9%A5%B0%E5%99%A8%E7%9A%84%E4%B8%80%E4%B8%AA%E5%A6%99%E7%94%A8.html 我们就根据这篇文章的思路来,在场景中理解python装饰器 其中的一个场景是:爬取数据的时候,目标网

Python之路【第四篇】:Python基础(19)——装饰器

#普通装饰器# (@+函数名),需要记住关键两点:#功能:#1.自动执行outer函数,并且将其下面的函数名f1当作参数传递#2.将outer函数的返回值,重新赋值给f1 # #装饰器必备# ####第一:函数名和执行函数##### def foo(): #创建函数# print('hello') #函数体# foo #表示是函数名,代指整个函数# foo() #表示执行f00函数# # 输出:hello # ####第二:函数被重新定义#### def foo():# print("foo1&

Python基础day-7[闭包,装饰器]

闭包: 首先说下闭包是什么? 闭包就是在函数内部定义的函数,包含对外部作用域的引用,但不包含全局作用域.因为函数的作用域在定义的时候就固定死了,所以闭包函数有自带作用域和延迟计算的特点. 闭包函数定义:如果一个内部函数,包含了对外部作用域的引用,但是不是包含全局作用域.那么这个函数就被认为是闭包函数.闭包函数可以使用".__closure__" 来查看闭包函数的属性.下面我们来看一个示例: def t(): money = 100 def s(): print(money) retur

Step4 - Python基础4 迭代器、装饰器、软件开发规范

1.装饰器 定义:本质是函数,就是为其他函数添加附加功能 原则:1.不能修改被装饰的函数的源代码 2.不能修改被装饰的函数的调用方式 例子: import time def timer(func): def warpper(*args,**kwargs): start_time = time.time() func() stop_time = time.time() print("the func run time is %s" % (stop_time-start_time)) re

python基础09--闭包,装饰器

1.1 闭包 1.函数作为第一类对象,支持赋值给变量,作为参数传递给其它函数,作为其它函数的返回值,支持函数的嵌套,实现了__call__方法的类实例对象也可以当做函数被调用 2.s= func  -->执行函数的内存地址 s =func() -->函数的调用 3.闭包:嵌套函数,内部函数调用外部函数的变量 可以让一个局部变量常驻内存 def  outer(): a=1 def inner():       #闭包函数 pritn(a) print(inner.__closuer__)  #如

python基础学习-有参装饰器

一.有参装饰器: 1.知识储备 由于语法糖@的限制,outter函数只能有一个参数,并且该才是只用来接收被装饰对象的内存地址 def outter(func): ? #func = 函数的内存地址 ? def wrapper(*args,**kwargs): res=func(*args,**kwargs) return res return wrapper ? @outter # index=outter(index) # index=>wrapper @outter # outter(ind

Python之简单理解装饰器(1)

装饰器是Python高级应用的一部分,其应用也很广泛.网上对其介绍和讲解也是五花八门,我在这里就对其进行简单介绍,并对如何渐进理解使用装饰器进行说明,以便和大家共同学习.如有更高见解,也请大家留言指正. 装饰器概念简单理解 循序渐进装饰器 装饰器概念简单理解 装饰器按照我的理解,就是在不改变原有函数代码的情况下,对原有函数进行功能的扩展. 这里先写个简单的装饰器,给大家有个概念性的认识. def anotherone(func):  #定义装饰器     def inner():