python装饰器

1. 简介

​ Python中的装饰器是一种可以装饰其它对象的工具。类似于装饰模式,实际是对原有对象进行功能上的增强(原有对象可以是对象、函数、类)。其使用像java 的注解。

​ 该工具本质上是一个可调用的对象(callable),所以装饰器一般可以由函数、类来实现。装饰器本身需要接受一个被装饰的对象作为参数,该参数通常为函数、方法、类等对象。装饰器需要返回一个对象,该对象可以是 经过处理的原参数对象、一个包装且类似原参数的对象;或者返回一个不相干内容。

​ 基于@语法和函数闭包,将原函数封装在闭包中,然后将函数赋值为一个新的函数(内置函数),执行函数时再在内层函数中执行闭包中的原函数。可以在你改变函数内部代码和调用的前提下,实现在函数执行和执行拓展功能。

​ 适用于多个函数系统统一在执行前后定义一些功能。

2.简单使用

2.1基于类实现装饰器,对函数进行增强

# 简单装饰器。 基于类实现装饰器,对函数进行增强
class wrap(object):
    def __init__(self):
        pass

    def __call__(self, obj):
        print("======1")
        print(obj)
        print("======2")
        return obj


@wrap()  # 等价于 foo = wrap(foo)
def foo():
    print('hello decorator!')


print(foo())

结果:

======1
<function foo at 0x0000021FDBB9EF70>
======2
hello decorator!
None

2.基于函数实现装饰器,对函数进行增强

# 简单装饰器。 基于函数实现装饰器,对函数进行增强
def wrap(obj):
    print("======1")
    print(obj)
    print("======2")
    return obj


@wrap  # 等价于 foo = wrap(foo)
def foo():
    print('hello decorator!')


print(foo())  

结果:

======1
<function foo at 0x000002171B1F1F70>
======2
hello decorator!
None

3.给被装饰的对象添加一个name 属性, 并且值设置为 张三

# 装饰器-给被装饰的对象添加一个name 属性, 并且值设置为 张三
def wrap(obj):
    obj.name = '张三'
    return obj


@wrap
class User:
    def __int__(self):
        pass


print(User.name)  # => hello decorator!
print(User)

结果:

张三
<class '__main__.User'>

4.函数装饰器: 对传入的对象进行增强,增强后返回新的对象

# 函数装饰器: 对传入的对象进行增强,增强后返回新的对象
def outer(func):
    def inner():
        print("hello inner")
        func()

    return inner


@outer  # foo = outer(foo)
def foo():
    print('hello foo')


print(foo.__name__)
foo()  # => hello foo

结果:

inner
hello inner
hello foo

5.对象方法装饰器。和普通的函数装饰器的区别是多了一个默认的self 参数

# desc: 对象方法装饰器。和普通的函数装饰器的区别是多了一个默认的self 参数

def outer(obj):
    def inner(self):
        print('hello inner')
        obj(self)

    return inner


class Zoo(object):
    def __init__(self):
        pass

    @outer  # => zoo = outer(zoo)
    def zoo(self):
        print('hello zoo')


zoo = Zoo()
print(zoo.zoo.__name__)
zoo.zoo()

结果:

inner
hello inner
hello zoo

6.类方法装饰器。 相当于对类进行增强

# desc: 类方法装饰器。 相当于对类进行增强

def outer(clss):
    class Inner(object):
        def __init__(self):
            self.clss = clss()

        def __getattr__(self, attr):
            return getattr(self.clss, attr)

    return Inner


@outer  # Zoo = outer(Zoo)
class Zoo(object):
    def __init__(self):
        pass

    def say(self):
        print('hello world!')


zoo = Zoo()
print(zoo.__class__)
zoo.say()

结果:

<class '__main__.outer.<locals>.Inner'>
hello world!

7.特殊应用的装饰器,比如,类静态属性装饰器。 如下代码可以看出ratio 会作为一个属性,而不是方法

class Foo(object):
    def __init__(self, height, weigth):
        self.height = height
        self.weigth = weigth

    @property
    def ratio(self):
        return self.height / self.weigth


foo = Foo(176, 120)
print(foo.ratio)

自己实现:

class Prop(object):
    def __init__(self, fget):
        self.fget = fget

    def __get__(self, instance, owner):
        return self.fget(instance)


class Foo(object):
    def __init__(self, height, weigth):
        self.height = height
        self.weigth = weigth

    @Prop
    def ratio(self):
        return self.height / self.weigth


foo = Foo(176, 120)
print(foo.ratio)

8.装饰带参数和返回值的对象

# desc: 装饰带参数和返回值的对象

# def outer(func):  # 函数装饰器
#     def inner(x, y):
#         print('hello inner')
#         return func(x, y)
#
#     return inner


def outer(func):  # 函数装饰器
    def inner(*args, **kwargs):
        print('hello inner')
        return func(*args, **kwargs)

    return inner


@outer
def add(x, y):
    return x + y


print(add(1, 4))

结果:

hello inner
5

9.装饰器本身带参数

# desc: 装饰器本身带参数

url_mapping = {}


def route(url):
    def decorator(func):  # 函数装饰器
        url_mapping[url] = func
        return func

    return decorator


@route('/home')
def home():
    print(1)
    pass


@route('/index')
def index():
    print(2)
    pass


print(url_mapping)

结果:

{'/home': <function home at 0x000001B16D480D30>, '/index': <function index at 0x000001B16D48F040>}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值