python 装饰器重要在哪

1.什么是装饰器?

要理解什么是装饰器,您首先需要熟悉Python处理函数的方式。从它的观点来看,函数和对象没有什么不同。它们有属性,可以重新分配:

def func():
 print('hello from func')
func()
> hello from func
new_func = func
new_func()
> hello from func
print(new_func.__name__)
> func

此外,你还可以将它们作为参数传递给其他函数:

def func():
 print('hello from func')
def call_func_twice(callback):
 callback()
 callback()
call_func_twice(func)
> hello from func
> hello from func

现在,我们介绍装饰器。装饰器(decorator)用于修改函数或类的行为。实现这一点的方法是定义一个返回另一个函数的函数(装饰器)。这听起来很复杂,但是通过这个例子你会理解所有的东西:

def logging_decorator(func):
 def logging_wrapper(*args, **kwargs):
 print(f'Before {func.__name__}')
 func(*args, **kwargs)
 print(f'After {func.__name__}')
 return logging_wrapper

@logging_decorator
def sum(x, y):
 print(x + y)

sum(2, 5)
> Before sum
> 7
> After sum

让我们一步一步来:

  1. 首先,我们在第1行定义logging_decorator函数。它只接受一个参数,也就是我们要修饰的函数。
  2. 在内部,我们定义了另一个函数:logging_wrapper。然后返回logging_wrapper,并使用它来代替原来的修饰函数。
  3. 在第7行,您可以看到如何将装饰器应用到sum函数。
  4. 在第11行,当我们调用sum时,它不仅仅调用sum。它将调用logging_wrapper,它将在调用sum之前和之后记录日志。

2.为什么需要装饰器

这很简单:可读性。Python因其清晰简洁的语法而备受赞誉,装饰器也不例外。如果有任何行为是多个函数共有的,那么您可能需要制作一个装饰器。下面是一些可能会派上用场的例子:

  • 在运行时检查实参类型
  • 基准函数调用
  • 缓存功能的结果
  • 计数函数调用
  • 检查元数据(权限、角色等)
  • 元编程

和更多…

现在我们将列出一些代码示例。

3.例子

带有返回值的装饰器

假设我们想知道每个函数调用需要多长时间。而且,函数大多数时候都会返回一些东西,所以装饰器也必须处理它:

def timer_decorator(func):
 def timer_wrapper(*args, **kwargs):
 import datetime
 before = datetime.datetime.now()
 result = func(*args,**kwargs)
 after = datetime.datetime.now()
 print "Elapsed Time = {0}".format(after-before)
 return result

@timer_decorator
def sum(x, y):
 print(x + y)
 return x + y

sum(2, 5)
> 7
> Elapsed Time = some time

可以看到,我们将返回值存储在第5行的result中。但在返回之前,我们必须完成对函数的计时。这是一个没有装饰者就不可能实现的行为例子。

带有参数的装饰器

有时候,我们想要一个接受值的装饰器(比如Flask中的@app.route('/login'):

def permission_decorator(permission):
 def _permission_decorator(func):
 def permission_wrapper(*args, **kwargs):
 if someUserApi.hasPermission(permission):
 result = func(*args, **kwargs)
 return result
 return None
 return permission wrapper
 return _permission_decorator

@permission_decorator('admin')
def delete_user(user):
 someUserApi.deleteUser(user)

为了实现这一点,我们定义了一个额外的函数,它接受一个参数并返回一个装饰器。

带有类的装饰器

使用类代替函数来修饰是可能的。唯一的区别是语法,所以请使用您更熟悉的语法。下面是使用类重写的日志装饰器:

class Logging: 

 def __init__(self, function):
 self.function = function 

 def __call__(self, *args, **kwargs):
 print(f'Before {self.function.__name__}')
 self.function(*args, **kwargs)
 print(f'After {self.function.__name__}')

@Logging
def sum(x, y):
 print(x + y)

sum(5, 2)
> Before sum
> 7
> After sum

这样做的好处是,您不必处理嵌套函数。你所需要做的就是定义一个类并覆盖__call__方法。

装饰类

有时,您可能想要修饰类中的每个方法。你可以这样写

class MyClass:
 @decorator
 def func1(self):
 pass
 @decorator
 def func2(self):
 pass

但如果你有很多方法,这可能会失控。值得庆幸的是,有一种方法可以一次性装饰整个班级:

def logging_decorator(func):
 def logging_wrapper(*args, **kwargs):
 print(f'Before {func.__name__}')
 result = func(*args, **kwargs)
 print(f'After {func.__name__}')
 return result
 return logging_wrapper

def log_all_class_methods(cls):
 class NewCls(object):
 def __init__(self, *args, **kwargs):
 self.original = cls(*args, **kwargs)

 def __getattribute__(self, s):
 try:
 x = super(NewCls,self).__getattribute__(s)
 except AttributeError:
 pass
 else:
 return x
 x = self.original.__getattribute__(s)
 if type(x) == type(self.__init__):
 return logging_decorator(x)
 else:
 return x
 return NewCls

@log_all_class_methods
class SomeMethods:
 def func1(self):
 print('func1')

 def func2(self):
 print('func2')

methods = SomeMethods()
methods.func1()
> Before func1
> func1
> After func1

现在,不要惊慌。这看起来很复杂,但逻辑是一样的:

  • 首先,我们让logging_decorator保持原样。它将应用于类的所有方法。
  • 然后我们定义一个新的装饰器:log_all_class_methods。它类似于普通的装饰器,但却返回一个类。
  • NewCls有一个自定义的__getattribute__。对于对原始类的所有调用,它将使用logging_decorator装饰函数。

内置的修饰符

您不仅可以定义自己的decorator,而且在标准库中也提供了一些decorator。我将列出与我一起工作最多的三个人:

@property -一个内置插件的装饰器,它允许你为类属性定义getter和setter。

@lru_cache - functools模块的装饰器。它记忆函数参数和返回值,这对于纯函数(如阶乘)很方便。

@abstractmethod——abc模块的装饰器。指示该方法是抽象的,且缺少实现细节。

以上就是python 装饰器重要在哪的详细内容,更多关于python 装饰器的资料请关注我们其它相关文章!

(0)

相关推荐

  • Python 中的函数装饰器和闭包详解

    函数装饰器可以被用于增强方法的某些行为,如果想自己实现装饰器,则必须了解闭包的概念. 装饰器的基本概念 装饰器是一个可调用对象,它的参数是另一个函数,称为被装饰函数.装饰器可以修改这个函数再将其返回,也可以将其替换为另一个函数或者可调用对象. 例如:有个名为 decorate 的装饰器: @decorate def target(): print('running target()') 上述代码的写法和以下写法的效果是一样的: def target(): print('running targe

  • python装饰器简介---这一篇也许就够了(推荐)

    Python装饰器(decorator)是在程序开发中经常使用到的功能,合理使用装饰器,能让我们的程序如虎添翼. 装饰器引入 初期及问题诞生 假如现在在一个公司,有A B C三个业务部门,还有S一个基础服务部门,目前呢,S部门提供了两个函数,供其他部门调用,函数如下: def f1(): print('f1 called') def f2(): print('f2 called') 在初期,其他部门这样调用是没有问题的,随着公司业务的发展,现在S部门需要对函数调用假如权限验证,如果有权限的话,才

  • python 一篇文章搞懂装饰器所有用法(建议收藏)

    01. 装饰器语法糖 如果你接触 Python 有一段时间了的话,想必你对 @ 符号一定不陌生了,没错 @ 符号就是装饰器的语法糖. 它放在一个函数开始定义的地方,它就像一顶帽子一样戴在这个函数的头上.和这个函数绑定在一起.在我们调用这个函数的时候,第一件事并不是执行这个函数,而是将这个函数做为参数传入它头顶上这顶帽子,这顶帽子我们称之为装饰函数 或 装饰器. 你要问我装饰器可以实现什么功能?我只能说你的脑洞有多大,装饰器就有多强大. 装饰器的使用方法很固定: 先定义一个装饰函数(帽子)(也可以

  • python 装饰器的实际作用有哪些

    接上一篇 终于知道python的装饰器是怎么回事,那在工作中,到底能干吗用呢? 尤其对我这个只会写写脚本又不做python开发的小测试/手动无辜脸. 先说结论,肯定是有用处滴. 一.自动化测试中使用 就拿写的自动化测试来说吧,如果我想统一的输出点东西,比如:case的运行时长,case名称等等,那就可以用起来. 首先,看下最简单的case,没有装饰器: import pytest def test_01(): a = 1 b = 2 assert a < b def test_02(): a =

  • 详解Python模块化编程与装饰器

    我们首先以一个例子来介绍模块化编程的应用场景,有这样一个名为requirements.py的python3文件,其中两个函数的作用是分别以不同的顺序来打印一个字符串: # requirements.py def example1(): a = 'hello world!' print (a) print (a[::-1]) def example2(): b = 'hello again!' print (b) print (b[::-1]) if __name__ == '__main__':

  • Python中的各种装饰器详解

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: 复制代码 代码如下: >>> def test(func):     def _test():         print 'Call the function %s().'%func.func_name         return func()     return _test >

  • python 装饰器的基本使用

    知识点 简单的装饰器 带有参数的装饰器 带有自定义参数的装饰器 类装饰器 装饰器嵌套 @functools.wrap装饰器使用 基础使用 简单的装饰器 def my_decorator(func): def wrapper(): print('wrapper of decorator') func() return wrapper() def test(): print('test done.') test = my_decorator(test) test 输出: wrapper of dec

  • Python classmethod装饰器原理及用法解析

    英文文档: classmethod(function) Return a class method for function. A class method receives the class as implicit first argument, just like an instance method receives the instance. To declare a class method, use this idiom: class C: @classmethod def f(c

  • 介绍Python的@property装饰器的用法

    在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改: s = Student() s.score = 9999 这显然不合逻辑.为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数: class Student(object): def get_score(self): return self._score def set_s

  • Python中的装饰器用法详解

    本文实例讲述了Python中的装饰器用法.分享给大家供大家参考.具体分析如下: 这里还是先由stackoverflow上面的一个问题引起吧,如果使用如下的代码: 复制代码 代码如下: @makebold @makeitalic def say():    return "Hello" 打印出如下的输出: <b><i>Hello<i></b> 你会怎么做?最后给出的答案是: 复制代码 代码如下: def makebold(fn):    

随机推荐