返回顶部
首页 > 资讯 > 后端开发 > Python >老生常谈Python进阶之装饰器
  • 494
分享到

老生常谈Python进阶之装饰器

进阶老生常谈Python 2022-06-04 18:06:53 494人浏览 薄情痞子

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

摘要

函数也是对象 要理解python装饰器,首先要明白在Python中,函数也是一种对象,因此可以把定义函数时的函数名看作是函数对象的一个引用。既然是引用,因此可以将函数赋值给一个变量,也可以把函数作为一个参数

函数也是对象

要理解python装饰器,首先要明白在Python中,函数也是一种对象,因此可以把定义函数时的函数名看作是函数对象的一个引用。既然是引用,因此可以将函数赋值给一个变量,也可以把函数作为一个参数传递或返回。同时,函数体中也可以再定义函数。

装饰器本质

可以通过编写一个纯函数的例子来还原装饰器所要做的事。


def decorator(func):
  
  def wrap():
    print("Doing someting before executing func()")
    func()
    print("Doing someting after executing func()")

  return wrap


def fun_test():
  print("func")


fun_test = decorator(fun_test)
fun_test()

# Output:
# Doing someting before executing func()
# func
# Doing someting after executing func()

fun_test所指向的函数的引用传递给decorator()函数

decorator()函数中定义了wrap()子函数,这个子函数会调用通过func引用传递进来的fun_test()函数,并在调用函数的前后做了一些其他的事情

decorator()函数返回内部定义的wrap()函数引用

fun_test接收decorator()返回的函数引用,从而指向了一个新的函数对象

通过fun_test()调用新的函数执行wrap()函数的功能,从而完成了对fun_test()函数的前后装饰

Python中使用装饰器

在Python中可以通过@符号来方便的使用装饰器功能。


def decorator(func):
  
  def wrap():
    print("Doing someting before executing func()")
    func()
    print("Doing someting after executing func()")

  return wrap

@decorator
def fun_test():
  print("func")


fun_test()

# Output:
# Doing someting before executing func()
# func
# Doing someting after executing func()

装饰的功能已经实现了,但是此时执行:


print(fun_test.__name__)

# Output:
# wrap

fun_test.__name__已经变成了wrap,这是应为wrap()函数已经重写了我们函数的名字和注释文档。此时可以通过functools.wraps来解决这个问题。wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。

更规范的写法:


from functools import wraps

def decorator(func):
  @wraps(func)
  def wrap():
    print("Doing someting before executing func()")
    func()
    print("Doing someting after executing func()")

  return wrap


@decorator
def fun_test():
  print("func")


fun_test()
print(fun_test.__name__)

# Output:
# Doing someting before executing func()
# func
# Doing someting after executing func()
# fun_test

带参数的装饰器

通过返回一个包裹函数的函数,可以模仿wraps装饰器,构造出一个带参数的装饰器。


from functools import wraps

def loginfo(info='info1'):
  def loginfo_decorator(func):
    @wraps(func)
    def wrap_func(*args, **kwargs):
      print(func.__name__ + ' was called')
      print('info: %s' % info)
      
      return func(*args, **kwargs)
    return wrap_func
  return loginfo_decorator
  
@loginfo()
def func1():
  pass
  
func1()

# Output:
# func1 was called
# info: info1

@loginfo(info='info2')
def func2():
  pass

func2()
# Output:
# func2 was called
# info: info2

装饰器类

通过编写类的方法也可以实现装饰器,并让装饰器具备继承等面向对象中更实用的特性

首先编写一个装饰器基类:


from functools import wraps

class loginfo:
  def __init__(self, info='info1'):
    self.info = info
    
  def __call__(self, func):
    @wrap
    def wrap_func(*args, **kwargs):
      print(func.__name__ + ' was called')
      print('info: %s' % self.info)
      
      self.after()  # 调用after方法,可以在子类中实现
      return func(*args, **kwargs)
    return wrap_func

  def after(self):
    pass


@loginfo(info='info2')
def func1():
  pass
  
# Output:
# func1 was called
# info: info1

再通过继承loginfo类,扩展装饰器的功能:


class loginfo_after(loginfo):
  def __init__(self, info2='info2', *args, **kwargs):
    self.info2 = info2
    super(loginfo_after, self).__init__(*args, **kwargs)

  def after(self):
    print('after: %s' % self.info2)


@loginfo_after()
def func2():
  pass

func2()
  
# Output:
# func2 was called
# info: info1
# after: info2

以上这篇老生常谈Python进阶之装饰器就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: 老生常谈Python进阶之装饰器

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

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

猜你喜欢
  • 老生常谈Python进阶之装饰器
    函数也是对象 要理解Python装饰器,首先要明白在Python中,函数也是一种对象,因此可以把定义函数时的函数名看作是函数对象的一个引用。既然是引用,因此可以将函数赋值给一个变量,也可以把函数作为一个参数...
    99+
    2022-06-04
    进阶 老生常谈 Python
  • python进阶之装饰器
    一.无参装饰器 问题:如何计算一段程序的运行时间? 先看一段简单代码: 1 import time 2 def func(): 3 start = time.time() # 记录程序开始时间 4 time.sleep(...
    99+
    2023-01-30
    进阶 python
  • 老生常谈Java字符串进阶(必看篇)
    前言最常用的对字符串操作的类有三个,分别是String,StringBuilder,StringBuffer,下面将会详细的说说这三个类......StringString类代表字符串,这个是最基本的对字符串的类,这个也是使用比较多的类,这...
    99+
    2023-05-31
    java 字符串 进阶
  • python装饰器进阶
    目录 装饰器进阶 1. 被装饰的函数有多个参数。 2. 被装饰的函数有返回值 3.在函数中嵌入装饰器 4. 装饰器类 ...
    99+
    2023-01-30
    进阶 python
  • python装饰器3:进阶
    装饰器1:函数装饰器 装饰器2:类装饰器 装饰器3:进阶 函数装饰器装饰方法 函数装饰器装饰普通函数已经很容易理解了: @decorator def func():... #等价于 def func():... func = dec...
    99+
    2023-01-30
    进阶 python
  • python 进阶学习之python装饰器小结
    装饰器总结 什么是装饰器?处理函数的函数,加一个功能,但是不影响原来函数的内部结构生活中的例子:给手机加一个外壳,外壳保护了手机 装饰器有什么用?增强函数的功能 装饰器使用场景增加被...
    99+
    2024-04-02
  • 老生常谈python字典用法
    目录创建字典遍历访问修改删除setdefault() 方法创建字典 python 创建字典可以使用 dict 函数,或者使用花括号,用花括号的方式更为常见。 d = { ...
    99+
    2024-04-02
  • 老生常谈Python中的Pickle库
    目录简介pickle与json比较函数dumpsloadsdumpload简介 Python 中有个序列化过程叫作 pickle,它能够实现任意对象与文本之间的相互转化,也可以实现任...
    99+
    2024-04-02
  • python进阶之生成器
    迭代器   什么叫迭代     可以被for循环的就说明他们是可迭代的,比如:字符串,列表,字典,元祖,们都可以for循环获取里面的数据   下面我们看一个代码:   1 number = 12345 2 for i in number...
    99+
    2023-01-30
    进阶 生成器 python
  • 老生常谈设计模式之动态代理
    一、动态代理概念动态代理分为JDK动态代理和cglib动态代理两种方式。jdk动态代理是由Java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执...
    99+
    2023-05-31
    设计模式 动态代理
  • 老生常谈Vue中的侦听器watch
    目录一、侦听器watch1.1.初识侦听器watch1.2.Vue的data的watch1.3.Vue的watch侦听选项一、侦听器watch (思维导图不太完善,因为是按照自己看...
    99+
    2022-11-13
    Vue侦听器watch Vue侦听器 Vue watch
  • 老生常谈Session和Cookie之间区别与联系
    Session和Cookie是用于在Web开发中跟踪和存储用户状态的机制。Session是在服务器端存储用户状态的一种机制。当用户第...
    99+
    2023-08-15
    Session
  • Python之装饰器
    在Python中一切皆对象,函数是一等对象。这意味着可以通过名字引用函数。>>> a=123 >>> a 123 >>> name='zeng' >>> name 'z...
    99+
    2023-01-31
    Python
  • Python中如何浅谈装饰器
    本篇文章给大家分享的是有关Python中如何浅谈装饰器,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。一 装饰器是什么   装饰器是一个用于封装函数或者类的代...
    99+
    2023-06-04
  • day20-python之装饰器
    1.装饰器 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import time 4 def cal(l): 5 start_time=time.time() ...
    99+
    2023-01-31
    python
  • python三大器之迭代器、生成器、装饰器
    目录迭代器生成器装饰器(非常实用!)迭代器 聊迭代器前我们要先清楚迭代的概念:通常来讲从一个对象中依次取出数据,这个过程叫做遍历,这个手段称为迭代(重复执行某一段代码块,并将每一次迭...
    99+
    2024-04-02
  • python之装饰器(函数)
    1. 装饰器   遵循的原则:     开闭原则:   对功能的扩展开放  对代码的修改是封闭 # 通用装饰器写法 # 存在的意义: 在不破坏原有函数和原有函数调用的基础上,给函数添加新的功能. def wrapper...
    99+
    2023-01-30
    函数 python
  • python之yield与装饰器
    防伪码:忘情公子著python中的yield:  在之前发布的《python之列表解析与生成器》中我们有提到过,生成器所实现的是跟列表解析近似的效果,但是我们不能对生成器做一些属于列表解析的操作。  因为生成器本身就不是一个列表,它只是模拟...
    99+
    2023-01-31
    python yield
  • Python 语法之装饰器
      装饰器的概念  装饰器是 Python 的一个重要部分。简单地说:就是用于拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能。  这个函数的特殊之处在于它的返回值也是一个函数,这个函数是内嵌 “原”...
    99+
    2023-06-02
  • 老生常谈的Python基础知识学习笔记,老师又敲黑板了
    Python基础知识笔记总结元组Tuple是“不可变”的列表。内容及总数不可修改的。使用小括号tup1=('zhansan',1992,'physics')允许使用元组运算符产生新的元组(5,6,7)+(8,...
    99+
    2023-06-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作