首页 > 编程语言 >python装饰器

python装饰器

时间:2022-08-17 22:58:39浏览次数:54  
标签:__ python self print foo 装饰 def

1. 简介

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

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

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

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

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
  1. 基于函数实现装饰器,对函数进行增强
# 简单装饰器。 基于函数实现装饰器,对函数进行增强
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
  1. 给被装饰的对象添加一个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'>
  1. 函数装饰器: 对传入的对象进行增强,增强后返回新的对象
# 函数装饰器: 对传入的对象进行增强,增强后返回新的对象
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
  1. 对象方法装饰器。和普通的函数装饰器的区别是多了一个默认的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
  1. 类方法装饰器。 相当于对类进行增强
# 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!
  1. 特殊应用的装饰器,比如,类静态属性装饰器。 如下代码可以看出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)
  1. 装饰带参数和返回值的对象
# 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
  1. 装饰器本身带参数
# 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>}

标签:__,python,self,print,foo,装饰,def
From: https://www.cnblogs.com/qlqwjy/p/16572879.html

相关文章

  • 关于python如何引用excel文件
    关于python如何引用excel文件importpandasaspd#引用pandas库,as:将pandas简写为pdNowcoder=pd.read_excel("1.xlsx")#使用read_XXX函数,()内的是文件名.#需要注......
  • python序列-列表
    列表-LISTpython中的列表是有一系列按特定顺序排列的元素组成,列表是属于python内置的可变序列。语法上列表的元素都是放在一对中括号‘[]’中,两个相邻的元素之间使用......
  • python 代码测试(pytest)
    前话代码测试用于检验代码运行结果是否符合预期。优势一:编写测试函数,更规范,高效的核对代码运行结果,当被测试对象进行了调整和重构的时候,可以节省大量人工排查问题的时间......
  • Python抓取汇率并绘制成折线图
    公司的一个小工作,需要抓取美元、欧元汇率并绘制成折线图。很小的功能,背后却涉及很多Python知识,甚至一些冷门的知识点。知识点总结如下:1.python抓取网页数据,利用pandas.rea......
  • # Conda虚拟环境中的pip,python 等路径是base环境而非本虚拟环境
    现象一次运行项目发现,原本可以正常运行的项目,突然提示有个包不存在,但是经过piplist发现在我的虚拟环境中是存在这个包的,并且此时我是正常的位于我的虚拟环境中。报错......
  • python复习
    break;continue;passord();chr()格式化:%s;f’str’;format序列:字符串、列表、元组...                    索引切片:sname[start:end:step] ......
  • Python入门系列(一)安装环境
    python是什么python是一门很受欢迎的语言,除了不能生孩子以外,其它都可以做。它擅长的领域是脚本工具和科学数据这一块,比如大数据,数据分析什么的。python安装为了演示和......
  • python 中根据RNA序列输出密码子编码的氨基酸序列
     001、(base)root@PC1:/home/test4#lstest.py(base)root@PC1:/home/test4#cattest.py##测试程序#!/usr/bin/pythonrna="AUGGCCAUG......
  • 学习:python 第三方模块介绍
    第三方模块是由第三方个人或者组织使用python开发,需要先下载安装才能使用的工具包第三方模块来自各行各业使用python的开发人员为了不同行业的不停业务提供了解决方案 ......
  • 学习:python 内置模块datetime
    importtimeimportdatetime#获取当前的日期时间n=datetime.datetime.now()print(n)#获取一个指定时间da=datetime.datetime(2018,2,13,5,23,45)print(da)#日期......