1.一层修饰符

1)简单版,编译即实现

在一个函数上面添加修饰符 @另一个函数名 的作用是将这个修饰符下面的函数作为该修饰符函数的参数传入,作用可以有比如你想要在函数前面添加记录时间的代码,这样每个函数调用时就能够知道是什么时候调用的,但是你不想手动地去给每个函数添加,那么就能够使用该修饰符实现这样的功能,下面举例说明:

#coding=UTF-
import time def showTime(fn):
print('calling time : ', time.time())
fn() #调用传入的参数 @showTime
def function1():
print('running function1 ') @showTime
def function2():
print('running function2 ')

返回:

calling time :  1567076890.053299
running function1
calling time : 1567076890.0533462
running function2

但是发现showTime()函数这样子写,即使将fn()行调用代码删除,也会在编译时就输出时间信息:

import  time
def showTime(fn):
print('calling time : ', time.time()) @showTime
def function1():
print('running function1 ') @showTime
def function2():
print('running function2 ')

返回:

calling time :  1567077493.420067
calling time : 1567077493.420131

而且这个时候如果调用function1()会报错:

TypeError: 'NoneType' object is not callable

2)调用才实现

如果去希望是在显示调用function1()和function2()函数时才显示时间,正确的写法是:

import time

def showTime(fn):
def getTime():
print('calling time : ', time.time())
fn() #要在修饰符函数中调用传入的函数参数fn,否则function1/function2是不会被调用的,仅仅只输出了时间信息
return getTime @showTime
def function1():
print('running function1 ') @showTime
def function2():
print('running function2 ') function1()
function2()

返回:

calling time :  1567077669.2308512
running function1
calling time : 1567077669.230927
running function2

3)传入参数

如果函数中需要传入参数:

def showTime(fn):
def getTime(*args):#*args获得fn的参数
print('args is : ', args) #查看传入的参数
print('calling time : ', time.time())
if len(args) > :
fn(args[]) #要在修饰符函数中调用传入的函数参数fn,否则function1/function2是不会被调用的,仅仅只输出了时间信息
else:
fn()
return getTime @showTime
def function1(a):
print('running function1 ')
print('a = ', a) @showTime
def function2():
print('running function2 ') function1()
function2()

返回:

args is :  (,)
calling time : 1567077936.79216
running function1
a =
args is : ()
calling time : 1567077936.792191
running function2

如果想要对传入的参数进行操作:

import time

def showTime(fn):
def getTime(*args):#*args获得fn的参数
print('args is : ', args) #查看传入的参数
print('calling time : ', time.time())
if len(args) > :
n = args[]
n *=
fn(n) #要在修饰符函数中调用传入的函数参数fn,否则function1/function2是不会被调用的,仅仅只输出了时间信息
else:
fn()
return getTime @showTime
def function1(a):
print('running function1 ')
print('a = ', a) @showTime
def function2():
print('running function2 ') function1()
function2()

返回:

args is :  (,)
calling time : 1567078015.031965
running function1
a =
args is : ()
calling time : 1567078015.0320058
running function2

2.如果是双重修饰符

1)简单版本,编译即实现

import time
def sayHello(fn):
print('Hello') def showTime(fn):
print('calling time : ', time.time())
fn() @sayHello
@showTime
def function1(a):
print('running function1 ')
print('a = ', a)

这个编译就会返回:

calling time :  1567078623.5239282
running function1
a =
Hello

2)调用才实现

如果想要以sayHello -> showTime -> function1的顺序,写法就要变为:

#coding:utf-8
import time def sayHello(fn):
def hello(*args):
print('Hello')
fn(*args) #
return hello # def showTime(fn):
def getTime(*args):# *args获得fn的参数
print('args is : ', args) #查看传入的参数
print('calling time : ', time.time())
if len(args) > :
n = args[]
n *=
fn(n) # 要在修饰符函数中调用传入的函数参数fn,否则function1/function2是不会被调用的,仅仅只输出了时间信息
else:
fn() return getTime # @sayHello
@showTime
def function1(a): #
print('running function1 ')
print('a = ', a) function1()

等于sayHello(showTime(function1(a))),所以调用function1(3)时运行的顺序为 :

  • 先调用sayHello()返回的hello(3),此时传入的参数*args为(3,),然后调用hello中的fn(*args)
  • 其实就是调用showTime()返回的getTime(3),此时传入的参数*args为(3,),然后调用getTime中的fn(n=6)
  • 其实就是调用function1(6),就结束了

返回:

Hello
args is : (,)
calling time : 1567078847.98264
running function1
a =

python中的修饰符@的作用的更多相关文章

  1. Python 中的@修饰符作用

    在Python 2.4以上的的函数中偶尔会看到函数定义的上一行有@functionName的修饰,这一下这个语法细节,其实这有点像C语言带参数的宏操作,解释器读到这样的修饰之后,会先解析@后的内容,直 ...

  2. python中的 @ 修饰符

    今天学习廖老师的python教程,碰到了修饰符'@',不太了解,查看了下官方文档. 简单的整理下: @dec2 @dec1 def func(arg1, arg2, ...): pass 等价于 de ...

  3. C#中static修饰符的作用

    static在C#中表示的是静态的,比如一个静态的字段是归类型所有,而非归对象所有,也就是说,在调用这个字段时,只能用类型去调,而不能用对象. 实例字段时随着对象创建而创建,对象销毁而销毁,而静态字段 ...

  4. scanf函数中*修饰符的作用,如:%*d

    在scanf函数中,*修饰符可以跳过所在项的输入.如下: #include <stdio.h> int main() { ; printf("请输入:"); scanf ...

  5. JAVA语言中的修饰符

    JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...

  6. C/C++ 中 const 修饰符用法总结

    C/C++ 中 const 修饰符用法总结 在这篇文章中,我总结了一些C/C++语言中的 const 修饰符的常见用法,供大家参考. const 的用法,也是技术性面试中常见的基础问题,希望能够帮大家 ...

  7. [原创] 基础中的基础(二):C/C++ 中 const 修饰符用法总结

    在这篇文章中,我总结了一些C/C++语言中的 const 修饰符的常见用法,供大家参考. const 的用法,也是技术性面试中常见的基础问题,希望能够帮大家梳理一下知识,给大家一点点帮助.作者是菜鸟一 ...

  8. 转载----C/C++ 中 const 修饰符用法总结

    感谢原创作者,写的好详细.不忍错过,所以转载过来了... 原文地址: https://www.cnblogs.com/icemoon1987/p/3320326.html 在这篇文章中,我总结了一些C ...

  9. Java中的 修饰符

    java中的修饰符分为类修饰符,字段修饰符,方法修饰符. 根据功能的不同,主要分为以下几种. 1.权限访问修饰符  访问权限的控制常被称为具体实现的隐藏 把数据和方法包进类中,以及具体实现的隐藏,常共 ...

随机推荐

  1. 在springboot项目中使用swaggerui

    在pom.xml文件中配置(用的2.6.1版本,2.9.2有点丑) <properties> <!--<spring.swagger2.version>2.9.2< ...

  2. try catch 场景

    面试官:什么情况下用到try-catch?程序员:代码执行预料不到的情况,我会使用try-catch.面试官:什么是预料不到的情况呢?程序员:比如我要计算a除以b,但是b是变量,如果b等于0程序就会出 ...

  3. 行为型模式(四) 观察者模式(Observer)

    一.动机(Motivate) "观察者模式"在现实生活中,实例其实是很多的,比如:八九十年代我们订阅的报纸,我们会定期收到报纸,因为我们订阅了.银行可以给储户发手机短信,也是&qu ...

  4. git基础问题

    1).git add 与gitstage的区别 git stage只是git add的同义词,所以在使用上没有区别 i)Git仓库的三个组成部分:工作区(Working Directory).暂存区( ...

  5. java 第九次作业

    一.题目:利用接口和接口回调,实现简单工厂模式,当输入不同的字符,代表相应图形时,利用工厂类获得图形对象,再计算以该图形为底的柱体体积. 二.代码 /* 5个形状类分别调用Shape接口: 柱体类中, ...

  6. c++的动态绑定和静态绑定及多态的实现原理(摘)

    C++多态的实现原理 为了支持c++的多态性,才用了动态绑定和静态绑定.理解它们的区别有助于更好的理解多态性,以及在编程的过程中避免犯错误. 需要理解四个名词:对象的静态类型:对象在声明时采用的类型. ...

  7. Vue创建组件的三种方式

    1.使用 Vue.extend 来创建全局的Vue组件 <div id="app"> <!-- 如果要使用组件,直接,把组件的名称,以 HTML 标签的形式,引入 ...

  8. 一个关于gcd的等式的证明

    证:$a > b$ 且 $gcd(a,b)=1$,有 $gcd(a^n-b^n, a^m-b^m) = a^{gcd(n, m)} - b^{gcd(n,m)}$. 证明: 假设 $n > ...

  9. 3、HDFS架构和YARN架构

    HDFS 架构图 HDFS 服务功能 NameNode NameNode是主节点,存储文件的元数据如文件名,文件目录,文件属性(生成时间.副本数.文件权限),以及每个文件的块列表和块所在的DataNo ...

  10. 4:ELK分析tomcat日志

    五.ELK分析tomcat日志 1.配置FIlebeat搜集tomcat日志 2.配置Logstash从filebeat输入tomcat日志 3.查看索引 4.创建索引