Python 装饰器

Python装饰器就是用于拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能。

装饰器由闭包和语法糖组成。

案例分析:
用户查询商品列表表示业务逻辑

def selectGoods():
	print("show the goodsList")


selectGoods()

调用方法名即可。

业务更改:
在查询商品列表之前需要添加权限验证:

def selectGoods():
	name = input("check your username")
	if name == "pxk":
		print("show the goodsList")
	else:
		print("you cannot look")


selectGoods()

虽然功能实现了,但是改变了原有函数。
在增加新功能的情况下改变原有业务逻辑实现,违背了开闭原则。

使用装饰器:
@函数 是python的一种语法糖。

def check(func):
    def check_name():
        name = input("check your username:")
        if name =="pxk":
            func()
        else:
            print("you cannot look")

    return check_name

@check
def selectGoods():
    print("show the goodsList")

selectGoods()

使用装饰器之后则selectGoods函数没有发生变化,且功能实现。

@函数名 执行逻辑

检测到需要执行的函数selectGoods 拥有装饰器@check
不执行selectGoods而是将selectGoods 作为参数传入check方法,并且执行check方法 此时func =selectGoods
将check的执行结果返回,即将check_name方法的引用返回,即实际执行的是check_name方法

装饰器调用顺序

装饰器是可以叠加使用的,那么使用装饰器以后代码是啥顺序呢?

对于Python中的”@”语法糖,装饰器的调用顺序与使用 @ 语法糖声明的顺序相反。

def check_username(func):
    def check():
        name = input("show your username please:")
        func()
        if name == "pxk":
            print("logining...")
        else:
            print("login failed")
    return check


def check_password(func):
    def check():
        password = input("show your password please:")

        if password == "666":
            print("login successful!!!")
            func()
        else:
            print("bye!!see you next time!!!")

    return check


@check_username
@check_password
def login():
    print("welcome!!!")

login()

在这个例子中,”login() = check_username(check_password(login()))”。

Python内置装饰器

在Python中有三个内置的装饰器,都是跟class相关的:staticmethod、classmethod 和property。

1.staticmethod 是类静态方法,其跟成员方法的区别是没有 self 参数,并且可以在类不进行实例化的情况下调用
2.classmethod 与成员方法的区别在于所接收的第一个参数不是 self (类实例的指针),而是cls(当前类的具体类型)
3.property 是属性的意思,表示可以通过通过类实例直接访问的信息

带有参数的装饰器

#如果你的装饰器需要参数,那么给当前的装饰器套一个
#壳子,用于接收装饰器的参数
def ke(a):
    def outter(func):
        def inner():
            print("你读的什么书?")
            func()
        def inner2():
            print("想读什么读什么")
            func()
        #装饰器壳子的参数,可用于在函数内去做流程控制
        if a == "hi":
            return inner
        else:
            return inner2
    return outter

@ke("hi")
def read():
    print("哈哈")

read()


"""
输出结果:
你读的什么书?
哈哈

"""

装饰带有参数的函数

#定义一个外函数
def outter(func):
    #外函数里面包裹一个内函数
    def inner(a):#如果装饰器带有参数的函数,需要在内函数中定义形参,并传递给调用的函数,因为调用原函数等于调用内函数
        print("你读的什么书?")
        #内函数引用外函数的变量
        func(a)
        print("那好好读这本书吧")
    #外函数返回内函数的引用
    return inner

@outter
def read(book_name):
    print(f"读的{book_name}这本书")

read("Python入门到精通") #read()->inner()       read(book_name)->inner(book_name)

print("*******************")

@outter
def read2(book_name):
    print(f"读的{book_name}这本书")

read2("Java入门到精通")

"""
输出结果 :
你读的什么书?
读的Python入门到精通这本书
那好好读这本书吧
*******************
你读的什么书?
读的Java入门到精通这本书
那好好读这本书吧
"""

装饰带有多参数的函数

def outter(func):
    def inner(book_name,*args):
        print("你读的什么书?")
        func(book_name,*args)
        print("那好好读这本书吧")
    return inner

@outter
def read(book_name,*args):
    print(f"{book_name}讲了",args)

read("Python从入门到精通",["数据类型","变量","面向对象"],{"面向对象":"封装、继承、多态"})

"""
输出结果:
你读的什么书?
Python从入门到精通讲了 (['数据类型', '变量', '面向对象'], {'面向对象': '封装、继承、多态'})
那好好读这本书吧
"""

类装饰器装饰函数

class Outter:
    #魔术方法:当把该类的对象当做函数调用时,自动触发
    def __call__(self, func):
        self.func = func #把传进来的函数当做对象的成员方法
        return self.inner #返回一个函数

    def inner(self,name):
        self.func(name)
        print("你说的对啊!")


@Outter()
def read(book_name):
    print(f"{book_name}这本书很好!")

read("Python精通")

"""
输出结果:
Python精通这本书很好!
你说的对啊!
"""
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值