我终于弄懂了Python的装饰器(二)
此系列文档:
二、装饰器的高级用法
将参数传递给装饰函数
#它不是黑魔法,只是给包装(wrapper)传递参数:
def a_decorator_passing_arguments(function_to_decorate):
def a_wrapper_accepting_arguments(arg1, arg2):
print("I got args! Look: {0}, {1}".format(arg1, arg2))
function_to_decorate(arg1, arg2)
return a_wrapper_accepting_arguments
#因为当您调用装饰器返回的函数时,调用的包装器(wrapper),将参数传递给被包装器包装的函数
@a_decorator_passing_arguments
def print_full_name(first_name, last_name):
print("My name is {0} {1}".format(first_name, last_name))
print_full_name("Peter", "Venkman")
# 输出:
#I got args! Look: Peter Venkman
#My name is Peter Venkman
将参数传递给装饰器
关于将参数传递给装饰器本身,您怎么认为?
因为装饰器必须接受一个函数作为参数,所以这可能会有些别扭。
因此,您不能将装饰函数的参数直接传递给装饰器。
在寻求解决方案之前,让我们写一些提醒:
#装饰器是普通函数
def my_decorator(func):
print("I am an ordinary function")
def wrapper():
print("I am function returned by the decorator")
func()
return wrapper
# 因此,你可以调用它,而不用 "@"
def lazy_function():
print("zzzzzzzz")
decorated_function = my_decorator(lazy_function)
#输出: I am an ordinary function
# 它输出了 "I am an ordinary function", 因为你只是调用了装饰器,而没有调用函数:
# 这里没有什么神奇的地方,使用'@'
@my_decorator
def lazy_function():
print("zzzzzzzz")
#outputs: I am an ordinary function
结果一样。
my_decorator”被调用了。
因此,当您使用时@my_decorator,您要告诉Python,通过变量来调用my_decorator标记了的函数。
def decorator_maker():
print("I make decorators! I am executed only once: "
"when you make me create a decorator.")
def my_decorator(func):
print("I am a decorator! I am executed only when you decorate a function.")
def wrapped():
print("I am the wrapper around the decorated function. "
"I am called when you call the decorated function. "
"As the wrapper, I return the RESULT of the decorated function.")
return func()
print("As the decorator, I return the wrapped function.")
return wrapped
print("As a decorator maker, I return a decorator")
return my_decorator
#让我们新建一个装饰器
new_decorator = decorator_maker()
#输出:
#I make decorators! I am executed only once: when you make me create a decorator.
#As a decorator maker, I return a decorator
# 让我们装饰这个函数
def decorated_function():
print("I am the decorated function.")
decorated_function = new_decorator(decorated_function)
#输出:
#I am a decorator! I am executed only when you decorate a function.
#As the decorator, I return the wrapped function
# 让我们调用这个函数
decorated_function()
#输出:
#I am the wrapper around the decorated function. I am called when you call the decorated function.
#As the wrapper, I return the RESULT of the decorated function.
#I am the decorated function.
毫不奇怪,跟我们前边演示的内容一样。
让我们再做一次完全一样的事情,但是这次我们跳过所有讨厌的中间变量:
def decorated_function():
print("I am the decorated function.")
decorated_function = decorator_maker()(decorated_function)
#输出:
#I make decorators! I am executed only once: when you make me create a decorator.
#As a decorator maker, I return a decorator
#I am a decorator! I am executed only when you decorate a function.
#As the decorator, I return the wrapped function.
# Finally:
decorated_function()
#输出:
#I am the wrapper around the decorated function. I am called when you call the decorated function.
#As the wrapper, I return the RESULT of the decorated function.
#I am the decorated function.
让我们把它变的更精简:
@decorator_maker()
def decorated_function():
print("I am the decorated function.")
#输出:
#I make decorators! I am executed only once: when you make me create a decorator.
#As a decorator maker, I return a decorator
#I am a decorator! I am executed only when you decorate a function.
#As the decorator, I return the wrapped function.
#最终:
decorated_function()
#输出:
#I am the wrapper around the decorated function. I am called when you call the decorated function.
#As the wrapper, I return the RESULT of the decorated function.
#I am the decorated function.
嘿,你看到了吗?我们使用了带有“ @”语法的函数调用!
因此,回到带有参数的装饰器。
如果我们可以使用函数即时生成装饰器,则可以将参数传递给该函数,对吗?
def decorator_maker_with_arguments(decorator_arg1, decorator_arg2):
print("I make decorators! And I accept arguments: {0}, {1}".format(decorator_arg1, decorator_arg2))
def my_decorator(func):
#这里传递的参数是闭包的。
#如果您对封包感到不舒服,可以忽略这点。
print("I am the decorator. Somehow you passed me arguments: {0}, {1}".format(decorator_arg1, decorator_arg2))
#不要混淆装饰器参数和函数参数!
def wrapped(function_arg1, function_arg2) :
print("I am the wrapper around the decorated function.\n"
"I can access all the variables\n"
"\t- from the decorator: {0} {1}\n"
"\t- from the function call: {2} {3}\n"
"Then I can pass them to the decorated function"
.format(decorator_arg1, decorator_arg2,
function_arg1, function_arg2))
return func(function_arg1, function_arg2)
return wrapped
return my_decorator
@decorator_maker_with_arguments("Leonard", "Sheldon")
def decorated_function_with_arguments(function_arg1, function_arg2):
print("I am the decorated function and only knows about my arguments: {0}"
" {1}".format(function_arg1, function_arg2))
decorated_function_with_arguments("Rajesh", "Howard")
#输出:
#I make decorators! And I accept arguments: Leonard Sheldon
#I am the decorator. Somehow you passed me arguments: Leonard Sheldon
#I am the wrapper around the decorated function.
#I can access all the variables
# - from the decorator: Leonard Sheldon
# - from the function call: Rajesh Howard
#Then I can pass them to the decorated function
#I am the decorated function and only knows about my arguments: Rajesh Howard
记住它:带参数的装饰器,可以将变量作为参数:
c1 = "Penny"
c2 = "Leslie"
@decorator_maker_with_arguments("Leonard", c1)
def decorated_function_with_arguments(function_arg1, function_arg2):
print("I am the decorated function and only knows about my arguments:"
" {0} {1}".format(function_arg1, function_arg2))
decorated_function_with_arguments(c2, "Howard")
#输出:
#I make decorators! And I accept arguments: Leonard Penny
#I am the decorator. Somehow you passed me arguments: Leonard Penny
#I am the wrapper around the decorated function.
#I can access all the variables
# - from the decorator: Leonard Penny
# - from the function call: Leslie Howard
#Then I can pass them to the decorated function
#I am the decorated function and only know about my arguments: Leslie Howard
如您所见,您可以像任何函数传递参数一样传递参数给装饰器。
您甚至可以根据需要使用*args, **kwargs。
但是请记住,装饰器仅被调用一次,仅在Python导入脚本时。之后,您将无法动态设置参数。
当您执行“ import x”时,该函数已经被修饰,因此您无法进行任何更改。
本文首发于BigYoung小站
我终于弄懂了Python的装饰器(二)的更多相关文章
- 我终于弄懂了Python的装饰器(一)
此系列文档: 1. 我终于弄懂了Python的装饰器(一) 2. 我终于弄懂了Python的装饰器(二) 3. 我终于弄懂了Python的装饰器(三) 4. 我终于弄懂了Python的装饰器(四) 一 ...
- 我终于弄懂了Python的装饰器(四)
此系列文档: 1. 我终于弄懂了Python的装饰器(一) 2. 我终于弄懂了Python的装饰器(二) 3. 我终于弄懂了Python的装饰器(三) 4. 我终于弄懂了Python的装饰器(四) 四 ...
- Python之装饰器(二)
以前你有没有这样一段经历:很久之前你写过一个函数,现在你突然有了个想法就是你想看看,以前那个函数在你数据集上的运行时间是多少,这时候你可以修改之前代码为它加上计时的功能,但是这样的话是不是还要大体读读 ...
- 理解Python中的装饰器//这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档
转自:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档 ...
- 进阶Python:装饰器 全面详解
进阶Python:装饰器 前言 前段时间我发了一篇讲解Python调试工具PySnooper的文章,在那篇文章开始一部分我简单的介绍了一下装饰器,文章发出之后有几位同学说"终于了解装饰器的用 ...
- Python各式装饰器
Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...
- Python札记 -- 装饰器补充
本随笔是对Python札记 -- 装饰器的一些补充. 使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码: #!/usr/bin/env python def deco(func): def ...
- python基础——装饰器
python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...
- 【转】详解Python的装饰器
原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...
随机推荐
- tensorflow2.0学习笔记
今天我们开始学习tensorflow2.0,用一种简单和循循渐进的方式,带领大家亲身体验深度学习.学习的目录如下图所示: 1.简单的神经网络学习过程 1.1张量生成 1.2常用函数 1.3鸢尾花数据读 ...
- iOS-Swift版本自定义CStextView的实现
CSTextView继承自UITextView,并为其增加了placeHolder属性,支持代码和SB方式创建:demo实现了CSTextView的自动排版 效果图 CSTextView地址: htt ...
- 环境篇:呕心沥血@CDH线上调优
环境篇:呕心沥血@线上调优 为什么出这篇文章? 近期有很多公司开始引入大数据,由于各方资源有限,并不能合理分配服务器资源,和服务器选型,小叶这里将工作中的总结出来,给新入行的小伙伴带个方向,不敢说一定 ...
- <WP8开发学习笔记>修改panorama全景控件的标题的大小
panorama(全景)控件非常具有WinPhone特色,但是那个巨大的标题许多时候会让人觉得违和.怎么修改它呢? 最开始想到的是加一个FontSize,结果毫无影响.╮(╯-╰)╭ <phon ...
- @topcoder - 2013TCO3A D1L3@ TrickyInequality
目录 @description@ @accepted code@ @accepted code@ @details@ @description@ 现有不等式组: \[\begin{cases} x_1 ...
- [每日一题2020.06.07]codeforces Round #627 (Div. 3)
problem A /* * Author: RoccoShi * Time: 2020-06-07 19:37:51 */ #include <bits/stdc++.h> using ...
- 恕我直言你可能真的不会java第1篇:lambda表达式会用了么?
本文配套教学视频:B站观看地址 在本号之前写过的一些文章中,笔者使用了lambda表达式语法,一些读者反映说代码看不懂.本以为java 13都已经出了,java 8中最重要特性lambda表达式大家应 ...
- Springboot基于assembly的服务化打包
(1)首先我们编辑 assembly.xml 配置文件,在前文的基础上新增第三方依赖设置(高亮部分),实现将第三方的 jar 包添加到压缩包里的 lib 目录: <?xml version=&q ...
- weblogic高级进阶之查看日志
域的日志位于 D:\Oracle\Middleware\user_projects\domains\base_domain\servers\AdminServer\logs 名字是base_domai ...
- redis高级命令1
设置name的过期时间是20秒 redis默认是16个数据库,默认是将数据存储在第0个数据库中 因为默认是0,当你选择其他数据的时候,是没有值的