详解Python装饰器的四种定义形式
作者:北极象 发布时间:2022-06-20 13:35:04
标签:Python,装饰器
前言
装饰器(decorator)在Python框架中扮演着重要角色,是Python中实现切面编程(AOP)的重要手段。
aspect-oriented programming (AOP) ,在不改变代码自身的前提下增加程序功能
不改变代码自身,但需要在函数和类头上加一个标注(annotation),这个标注在Python里叫装饰器,在java里叫注解。
在Python里,一共有四种组合形式。下面一一举例。
用函数装饰函数
采用一个函数定义装饰器:
def decorate(f):
def wrapper(*args):
return f(*args)*2
return wrapper
然后作用在一个函数上:
@decorate
def add(a, b):
return a + b
测试一下效果:
def test_decorate():
sum = add(3, 5)
assert sum == 16
用函数装饰一个类
这里通过装饰器实现单例模式:
def singleton(cls):
instances = {}
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
使用该装饰器:
@singleton
class MyClass:
def method(self):
pass
于是,当你定义多个对象时,返回的是同一实例:
obj = MyClass() # creates a new instance
obj2 = MyClass() # returns the same instance
obj3 = MyClass() # returns the same instance
...
用类定义装饰器,然后装饰一个函数
先采用类定义一个装饰器:
class Star:
def __init__(self, n):
self.n = n
def __call__(self, fn):
@wraps(fn)
def wrapper(*args, **kwargs):
result = fn(*args, **kwargs)
return result
return wrapper
再作用在一个函数上:
@Star(5)
def add(a, b):
return a + b
主要是在类中实现__call__方法。上面例子也可以简化:
class MyDecorator:
def __init__(self, function):
self.function = function
def __call__(self, *args, **kwargs):
# We can add some code
# before function call
self.function(*args, **kwargs)
# We can also add some code
# after function call.
# adding class decorator to the function
@MyDecorator
def function(name, message ='Hello'):
print("{}, {}".format(message, name))
用类定义装饰器,然后装饰一个类
先定义装饰器:
class MyClassDecorator(object):
_instances = dict()
def __init__(self, name):
pass
def __call__(self, cls):
class WrappedClass(cls):
def say_hello(self):
print(f'Hello: {self.username}')
return WrappedClass
该装饰器给被装饰的类上添加了一个方法,名称为say_hello()。使用如下:
@MyClassDecorator('test')
class MyClass():
def __init__(self, username):
self.username = username
然后:
def test_decoratorforclass():
obj = MyClass('user1')
obj.say_hello()
打印出: Hello: user1
小结
学习类装饰,对Python的内部机制会有更多的了解。如__init__, call, __new__等内置方法。
来源:https://blog.csdn.net/jgku/article/details/128020535


猜你喜欢
- 在javascript中,null>=0 为真,null==0却为假,null的值详解1.前言今天看见朋友们在讨论一个问题,说 null 到
- MySQL去重的方法整理【初级】有极少的重复行使用distinct查出来,然后手动一行一行删除。【中级】按照单个字段的重复去重例如:对id字
- 中文编码问题一直是Python程序设计中很头痛的问题,本文对此较为详细的进行了总结归纳。具体如下: 当字符串是:'\u4e
- 概述 -------------------------------------------------------------------
- 本文实例讲述了Vue 实现从小到大的横向滑动效果。分享给大家供大家参考,具体如下:最近项目中遇到一个需求,需要实现横向滑动,并且在滑动过程中
- 使用MySql的窗口函数统计数据时,发现一个小的问题,与大家一起探讨下。环境配置:mysql-installer-community-8.0
- 我是使用源码编译的方式安装的,网上有的可以添加 ppa 源进行在线安装,但我试了行不通,所以还是采用源码安装1、安装编译依赖项sudo ap
- 在 linux 系统中连接 mdb 数据库,直接连接的话,mdb 默认的驱动无法识别非 windows 的路径, 所以不能使用常规的连接方式
- 在使用django的modelform的时候,修改表单,图片在form表单显示的是一个链接。显示缩略图如下第一步:from django.f
- __init__.py 文件的作用是将文件夹变为一个Python模块,Python 中的每个模块的包中,都有__init__.py 文件。通
- Python使用贪婪算法解决问题集合覆盖问题假设你办了个广播节目,要让全美50个州的听众都收听到。为此,你需要决定在哪些广播台播出。在每个广
- 问题Vue项目中需要用Echarts的柱状图显示数据,并且每次搜索要更新柱状图。这时候小编发现在控制台会出现这样的报错:原来的代码是这样的,
- MySQL 数据表是由行和列构成的,通常把表的“列”称为字段(Field),把表的&
- MySQL清空表数据清空表数据一共有三种方式1 、truncate (速度很快) 自增字段清空从1开始 全表清空首选2、drop 直接删表&
- 废话不多说,直接上代码create database mydbuse mydbgocreate table account( i
- 在之前只知道SqlServer支持数据批量插入,殊不知道Oracle、SQLite和MySql也是支持的,不过Oracle需要使用Orace
- 在进行网页抓取的时候,分析定位html节点是获取抓取信息的关键,目前我用的是lxml模块(用来分析XML文档结构的,当然也能分析html结构
- 最好的学习方式就是实践。 我们通过导入gin包来深入学习。环境go 1.13.5goland 2019.3.1manjaro-gnome3.
- 在项目中遇到需要支持上传gif图片,并把其分解的帧图片一次展示给用户。话不多说直接上代码分解gif图片需要使用libgif-js这个库!1.
- 开发中偶尔需要判断网络的连通性,没有什么方法比 ping 更直接了当,通常检查网络情况都是运行命令ping www.baidu.com ,查