iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >如何进行Python各种类型装饰器的分析
  • 418
分享到

如何进行Python各种类型装饰器的分析

2023-06-22 00:06:57 418人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

这篇文章将为大家详细讲解有关如何进行python各种类型装饰器的分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。装饰器说明Python中的装饰器是一种可以装饰其它对象的工具。该工具本质上是

这篇文章将为大家详细讲解有关如何进行python各种类型装饰器的分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

装饰器说明

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

相信通过上述一段文字的描述,大家应该更加的迷惑了!所以下面我们就结合代码来理解Python中的装饰器。

装饰器分类

最简单的装饰器

def warp(obj):    return obj

没错!!!这就是最简单的装饰器,并且是一个没有任何用处的装饰器。但是它确实是一个装饰器,并且可以用的很好。比如:

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

而上面使用了装饰器的代码,其实我们可以通过其它方式达到相同的效果。具体见下:

def foo():    print('hello decorator!') foo = warp(foo)foo()    # => hello decorator!

So,通过最简单的代码,我们可以发现装饰器其实就是接受了一个函数(对象),并且返回了一个函数(对象)的函数(可调用对象)。

用于修改对象的装饰器

在理解了装饰器的含义之后,再来看一个稍微有点作用的装饰器。代码如下:

def warp(obj):    obj.name = 'python'    return obj

这个装饰器在上一个例子的基础上,只添加了一行代码,但是却有了实际的作用。它的作用就是给被装饰的对象,添加一个name属性并且设置值为python。这个装饰器的使用效果如下:

@warp        # => Bar = warp(Bar)class Bar(object):    def __init__(self):        pass print(Bar.name)     # => python

可以看到实际的使用过程中,warp装饰器已经成功的给Bar对象添加了name属性。除了给类对象添加属性之外,它还可以给函数对象添加属性。

@warp       # => foo = warp(foo)def foo():    pass print(foo.name)         # => python

用于模拟对象的装饰器--函数装饰器

上面例子中的装饰器,是直接修改了传入对象;而装饰器最常用的方式却是模拟一个传入对象。即返回一个和原对象相似的对象(即调用接口完全一样的另一个对象),并且该模拟对象是包装了原对象在内的。具体代码如下:

def outer(func):         # 函数装饰器    def inner():        func()     return inner

上面是一个函数装饰器,即用来修饰函数的装饰器。因为它返回了一个模拟func对象的inner对象。而这里inner对象是一个函数,所以这个装饰器只能装饰函数。(因为inner对象只能模拟func这样的函数对象,不能模拟class对象)

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

上述代码中最后一行foo(),其实质上是执行的inner()。为了证明这一点,我们可以在inner中打印一条信息。并查看下foo的__name__属性。

def outer(func):         # 函数装饰器    def inner():        print('hello inner')        func()     return inner @outer      # foo = outer(foo)def foo():    print('hello foo') print(foo.__name__)foo()

上述代码执行后的结果如下:

innerhello innerhello foo

可以看到首先打印的是 foo.__name__代码,注意内容是inner而不是foo(说明其本质上是inner函数);其次打印的时候,先打印inner函数中的内容,后打印foo函数中的内容。

用于模拟对象的装饰器--类方法装饰器

与函数装饰器类似的还有类方法装饰器,其作用相同,格式相近。只是些微有些区别,下面就是类方法装饰器的代码。

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()

可以看到类方法装饰器和函数装饰器,唯一的区别就是多了一个默认的self参数;这是因为类方法本身就比函数多这么一个参数。其执行的结果如下:

innerhello innerhello zoo

所以最后一行代码zoo.zoo函数执行的其实是inner函数。

用于模拟对象的装饰器--类装饰器

装饰器除了可以装饰函数、方法之外,还可以装饰器类对象。具体的代码如下:

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__)    # <class '__main__.outer.<locals>.Inner'>zoo.say()               # hello world!

通过代码可以看出,类装饰器与函数装饰器类似。即模拟一个与原参数接口一致的类对象。所以对于模拟类的装饰器,只能用在其可以模拟的对象之上,并不能互相修饰其它类型的对象。

特殊应用的装饰器

上面都是比较常规的装饰器,python中还有另外一些特殊的装饰器。比如:类静态属性装饰器。比如下面的代码:

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)    # => 1.4666666666666666

上述代码中的@property装饰器就是一个特殊的装饰器,它把ratio方法变成了一个属性。从最后一句调用代码可以看出,使用的是foo.ratio而不是foo.ratio()。

对于这类装饰器需要Python的特定属性和机制的支持才可以实现,不同特性的装饰器所需机制不同。如上述代码中的@property装饰器就可以使用下面的代码来实现。

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.4666666666666666

可以看到效果和原生的@property装饰器是一样的。

类实现的装饰器

在之前对于装饰器的说明中,有说道装饰器是一个callable对象。除了函数可以实现装饰器之外,还可以通过类来实现。那么类实现装饰器的具体代码如下:

class Warp(object):    def __init__(self):        pass     def __call__(self, obj):        obj.name = 'warp'        return obj

这个类装饰器实现的功能,也是给传入的对象添加name属性,并设置其值为warp。其调用效果如下:

@Warp()def foo():    pass print(foo.name)    # => warp

装饰带参数/返回值的对象

前面列举的所有例子,被装饰的对象都是无参数的。如果你需要装饰一个带参数的对象。那么就需要响应的修改下装饰器代码了。注意:这里特指那些模拟类型的装饰器。即函数装饰器、类方法装饰器、类装饰器。

假设我们先有一个带参数的函数,其内容如下:

def add(x, y):    return x * y

如果使用原来的函数装饰器,肯定就会出错。主要因为这个函数带参数,并且也有返回值。而原来的函数装饰器则不能支持,原函数装饰器如下:

def outer(func):         # 函数装饰器    def inner():        func()     return inner

可以看到inner模拟的仅仅是一个无参数、无返回值的对象。所以需要进行如下的修改:

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

这样的函数装饰器就可以装饰add函数了。因为inner函数添加了x,y参数,调用func对象时也添加了参数,并且返回了func对象的返回值。具体使用效果如下:

@outerdef add(x, y):    return x * y print(add(2, 3))    # => 6

上述代码虽然可以实现add的装饰功能,但是如果现在我们在出现一个三个参数的函数需要装饰,或者一个带默认值参数的韩式需要装饰怎么办。我们不可能为没一个不同参数的函数都写一个相同功能的装饰器。所以终极的函数装饰器的写法如下:

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

这里使用了python中动态参数的概念,这样装饰器就可以支持任意的组合参数的函数了。

装饰器带参数

上面说到的是被修饰的对象带参数的情况,还有一种情况就是装饰器本身希望支持带参数。这种情况类似于函数模块通过带参数可以更加灵活的道理一样。通过给装饰器带上参数,可以使得装饰器的功能更加的灵活。代码如下:

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

上面是一个URL路由映射的装饰器,可以给不同的函数绑定不同的路由。如果装饰器不能带参数,则无法实现这样的功能。其使用效果如下:

@route('/home')def home():    pass    @route('/index')def index():    pass    print(url_mapping)  # => {'/home': <function home at 0x01DAD810>, '/index': <function index at 0x01DAD7C8>}

装饰器应用

Python装饰器的应用比较广泛,大部分场景的公共处理逻辑都可以使用装饰器去简化。(使用上类似于JAVA中的注解)一般比较常见的场景比如:

日志记录

权限验证单

例模式竞争

资源管理

关于如何进行Python各种类型装饰器的分析就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

--结束END--

本文标题: 如何进行Python各种类型装饰器的分析

本文链接: https://www.lsjlt.com/news/301614.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何进行Python各种类型装饰器的分析
    这篇文章将为大家详细讲解有关如何进行Python各种类型装饰器的分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。装饰器说明Python中的装饰器是一种可以装饰其它对象的工具。该工具本质上是...
    99+
    2023-06-22
  • Python各种类型装饰器详细介绍
    目录装饰器说明装饰器分类最简单的装饰器用于修改对象的装饰器用于模拟对象的装饰器--函数装饰器用于模拟对象的装饰器--类方法装饰器用于模拟对象的装饰器--类装饰器特殊应用的装饰器类实现...
    99+
    2024-04-02
  • 如何进行void类型深层的分析
    今天就跟大家聊聊有关如何进行void类型深层的分析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。下面将对void关键字的深刻说明,并详述void及void指针类型的使用方法与技巧,初...
    99+
    2023-06-17
  • 如何进行MySQL INNODB存储引擎中各类型SQL加锁分析
    这篇文章给大家介绍如何进行MySQL INNODB存储引擎中各类型SQL加锁分析,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。 MYSQL5.6事物隔离级...
    99+
    2024-04-02
  • 如何进行Python函数装饰器的使用
    如何进行Python函数装饰器的使用,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。装饰器装饰器的定义关于装饰器的定义,我们先来看一段github上大佬的定义:Functio...
    99+
    2023-06-26
  • 如何进行python中类的全面分析
    本篇文章为大家展示了如何进行python中类的全面分析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。面向对象重要的概念就是类(Class)和实例(Instance)...
    99+
    2024-04-02
  • python装饰器的示例分析
    这篇“python装饰器的示例分析”除了程序员外大部分人都不太理解,今天小编为了让大家更加理解“python装饰器的示例分析”,给大家总结了以下内容,具有一定借鉴价值,内容详细步骤清晰,细节处理妥当,希望大家通过这篇文章有所收获,下面让我们...
    99+
    2023-06-06
  • 带参数的全类型 Python 装饰器
    这篇短文中显示的代码取自我的小型开源项目按合同设计,它提供了一个类型化的装饰器。装饰器是一个非常有用的概念,你肯定会在网上找到很多关于它们的介绍。简单说,它们允许在每次调用装饰函数时(之前和之后)执行代码。通过这种方式,你可以修改函数参数或...
    99+
    2023-05-14
    Python 装饰器
  • 如何进行C++继承类成员访问权限修饰符的分析
    这期内容当中小编将会给大家带来有关如何进行C++继承类成员访问权限修饰符的分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1. 前言C++提供了三个修饰符来限定类成员的被访问权限,分别是public ,...
    99+
    2023-06-21
  • python装饰器代码的示例分析
    这篇文章主要介绍python装饰器代码的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1.装饰器通用模型def wrapper(fn):    def&nbs...
    99+
    2023-06-29
  • 如何进行Linux系列中各种环境的安装集合
    如何进行Linux系列中各种环境的安装集合,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。linux环境安装集合1. 利用VirtualBox安装Linux系统百度百科:http...
    99+
    2023-06-19
  • 如何在python中使用类装饰器
    这篇文章将为大家详细讲解有关如何在python中使用类装饰器,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。python有哪些常用库python常用的库:1.requesuts;2.scrap...
    99+
    2023-06-14
  • dreamweaver如何制作各种类型的菜单栏
    这篇文章主要介绍dreamweaver如何制作各种类型的菜单栏,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!打开dreamweaver,新建html,在右下方管理站点,然后新建站点,选择一个你想放网站文件的位置。最后...
    99+
    2023-06-08
  • Python深入分析@property装饰器的应用
    目录什么是propertyproperty属性定义的两种方式@property属性值的限制什么是property 简单地说就是一个类里面的方法一旦被@property装饰,就可以像调...
    99+
    2024-04-02
  • 如何在 Python 中使用 API 来 load 各种数据类型?
    Python 是一种高级编程语言,被广泛应用于数据科学、机器学习、人工智能等领域。在这些领域中,我们通常需要使用各种数据类型来进行分析和建模。这些数据类型可能来自于不同的来源,例如数据库、文件、网络等。为了方便地处理这些数据,我们可以使用 ...
    99+
    2023-07-21
    load 数据类型 api
  • python如何使用类来实现装饰器
    这篇文章主要介绍python如何使用类来实现装饰器,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!尝试用类来实现装饰器绝大多数装饰器都是基于函数和 闭包 实现的,但...
    99+
    2024-04-02
  • Python如何处理Windows平台下的各种响应数据类型?
    在Windows平台下,我们经常会遇到各种各样的响应数据类型,比如HTTP响应、JSON响应、XML响应等等。Python作为一种强大的编程语言,在处理这些响应数据类型时也有着出色的表现。本篇文章将介绍Python如何处理Windows平...
    99+
    2023-09-30
    windows 响应 数据类型
  • 如何进行ADO MD对象模型的分析
    这期内容当中小编将会给大家带来有关如何进行ADO MD对象模型的分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。用 Description 属性获取简短的错误描述。显示此属性向用户警告您不能或不想处理的...
    99+
    2023-06-17
  • redis部署及各种数据类型使用命令的示例分析
    这篇文章给大家分享的是有关redis部署及各种数据类型使用命令的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。编译安装redis开始部署[root@mcw01 ~]$ lsanacon...
    99+
    2023-06-29
  • Windows平台下Python如何应对各种响应数据类型?
    在Python中,我们常常需要和不同的响应数据类型打交道。Windows平台下Python可以通过各种方式处理这些响应数据类型,本文将介绍一些常用的方法。 处理JSON数据 JSON是一种轻量级的数据交换格式,常用于Web应用程序中。在...
    99+
    2023-09-30
    windows 响应 数据类型
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作