[email protected]装饰符

‘‘‘
# 不改变原函数代码,在调用原函数之前或之后执行其他代码

# 不加参数是两层def,会直接将原函数地址传递进来,返回new_fun(带原函数地址)下的inner函数
# 原函数执行前调用的函数(统一参数)
# def new_fun(sfunc):
#     def inner(args):
#         # 新添加内容
#         print(‘装饰符...‘)
#         sfunc(args)
#     return inner

# 原函数执行前调用的函数(不统一参数)
# def new_fun(sfunc):
#     # 如果多个函数使用这个装饰符,而函数,参数不一致的情况下,可以使用 *和**
#     def inner(*args, **kwargs):
#         # 新添加内容
#         print(‘装饰符...‘)
#         sfunc(*args, **kwargs)
#     return inner

# 原函数执行前调用的函数(不统一参数,且带返回值)
def new_fun(sfunc):
    # 如果多个函数使用这个装饰符,而函数,参数不一致的情况下,可以使用 *和**
    def inner(*args, **kwargs):
        # 新添加内容
        print(‘装饰符...‘)
        # 如果函数是带返回值的,就要加return返回
        return sfunc(*args, **kwargs)
    return inner

@new_fun
def print_str(tstr):
    print(‘str传递进来 %s ‘ % tstr)
    return tstr

def print_int(tint, tint2):
    print(‘int传递进来 %d %d‘ % (tint, tint2))
    return tint, tint2

print_int = new_fun(print_int)
# 装饰符相当于这样上面这句代码:
# 将原函数地址传递进new_fun,返回的是new_fun里的inner函数的地址,那么原函数地址调用时就是inner地址,相当于执行inner函数
# inner的形参和原函数形参相同,那么将参数传递进inner,就可以将参数传递进原函数,然后执行原函数
# 如果new_fun里不嵌套inner,那么在加载代码的时候就会直接执行new_fun内代码,达不到调用原函数时才执行的效果

rs = print_str(‘测试str‘)
rt1, rt2 = print_int(10086, 5566)
print(rs, rt1, rt2)‘‘‘

# 执行原函数前先执行的功能,在装饰器之前定义,不然无法找到地址
def before_func():
    print(‘before‘)

# 执行原函数后再执行的功能
def after_func():
    print(‘after‘)

# 多参装饰器(三层def),第一层装载装饰器参数,第二层装载原函数地址,第三层装载调用时的实际参数
def func_frame(before, after):
    def main_func(sourse_func):
        def inner(*args, **kwargs):
            before()
            sourse_func(*args, **kwargs)
            after()
        return inner
    return main_func

#@func_frame(before_func,after_func)
def print_tuple(tup=()):
    for i in tup:
        print(i)
    return ‘True‘

print_tuple = func_frame(before_func, after_func)(print_tuple)
# 多参装饰器相当于上面这句,等同于 @func_frame(before_func,after_func)
# 先执行func_frame()函数,将参数传递进函数体,返回函数体内装载有参数的main_func函数地址
# 接着执行返回的main_func()函数,将原函数地址传递进去,返回装载有装饰器参数和原函数地址的sourse_func函数地址
# 最后将sourse_func函数地址赋值给原函数,下次调用原函数名,
# 实际调用的是func_frame(带有参数值)下的main_func(带有原函数地址)下的sourse_func函数
# 那么在sourse_func里就可以操作func_frame的参数(可以是函数地址,也可以是其他数据类型)和调用原函数功能
# 如果装饰器是函数,那么就可以执行对应函数功能,不是的话,可以用装饰器参数执行判断等功能
# 以后在不改变原函数代码和装饰器代码的情况下,只需将写好功能的函数地址传递进装饰器就可以达到在执行原函数
# 之前和之后添加功能的效果

print_tuple((1, 2, 3, 4, 5, 6))

  

时间: 2024-10-18 12:06:16

[email protected]装饰符的相关文章

Go的魅力, 函数式(柯里化, 闭包, 高阶函数), [email protected]装饰器, 封装

Go朴实无华的代码风格是函数式的无尽魅力. 函数式有3个别名, 高大上的"柯里化", 编程语言的"闭包", 数学气息的"高阶函数". Python没有Go的func匿名函数, 但是具有可爱的语法糖(@装饰器). 编程语言都是相通的, 层层封装造就了灵活的风格. 理解了Go的"函数式", 再理解内嵌/接口/重写(设计模式), 剩下的是各个领域的工具了, 就可以写出服务于业务的代码. 感悟于 函数式 http://www.jian

iOS开发核心语言Objetive C —— 编译器指令@[email protected]自定义构造方法及类工厂

本分享是面向有意向从事iOS开发的伙伴们,或者已经从事了iOS的开发者.如果您对iOS开发有极高的兴趣,可以与我一起探讨iOS开发,一起学习,共同进步.如果您是零基础,建议您先翻阅我之前分享的iOS开发分分钟搞定C语言系列,然后在开始Objective C语言的学习,如果您遇到问题也可以与我探讨,另外将无偿分享自己整理的大概400G iOS学习视频及学习资料,都是干货哦!可以新浪微博私信?关注极客James,期待与您的共同学习和探讨!!由于时间有限,每天在工作之余整理的学习分享,难免有不足之处,

OC基础[email protected]后的修饰符及其用法小结

[email protected]后的修饰符 strong : 该属性值对应 __strong 关键字,即该属性所声明的变量将成为对象的持有者,等同于"retain" weak : 该属性对应 __weak 关键字,与 __weak 定义的变量一致,该属性所声明的变量将没有对象的所有权,并且当对象被释放之后,对象将被自动赋值nil,记住IBOutlet应该使用weakcopy : 和之前的copy一样,复制一个对象并创建strong关联assign : 对象不能使用assign,但原始

pytest框架[email protected](scpoe=‘xxx')装饰器

pytest是一个非常成熟的全功能的Python测试框架 用例设计原则 谨记:当我们使用pytest框架写case的时候,一定要拿它的命令规范去case,这样框架才能识别到哪些case需要执行,哪些不需要执行文件名以test_.py文件和_test.py以Test开头的类以test_开头的函数以test_开头的方法 运行方式可以通过pycharm里的终端命令,也可以pytest.main()运行(主推) @pytest.fixture() 即测试用例执行的环境准备和清理,相当于unittest的

[email protected]动态代理-类加载器

一.测试单元     概述:用于测试JAVA代码的工具类,已内置在Eclipse中;     格式:         1.在方法的上面添加@Test;         2.对被测试的方法的要求:权限-public;返回值-void;参数-空参         [email protected]:在@Test标注的方法前执行,可以用于初始化;           @After:在@Test标注的方法后执行,可以用于释放资源; 二.注解     概述:java的一种数据类型,和类/接口在同一级别  

连接[email protected]操作步骤

一.准备工作 软件下载 Git:地址 TortoiseGit:地址 二.安装与配置 1.Git安装 Git配置 设置客户端的用户名和email 然后,到[email protected] 上面注册一个帐号. 这个帐号就是设置客户端的eamil 下一步,根据eamil生成key 生成key的命令 ssh-keygen -t rsa -C "youer email" 如果命令无误执行后,会在当前用户文件夹下,建立一个.ssh的文件夹,文件夹中有两个文件分别是id_rsa和id_rsa.pu

Makefile的编写及四个特殊符号的意义@、[email protected]、$^、$<

我们先看三段C++程序: 一.line1的源码 line1.h 1 #ifndef _LINE_1_H 2 #define _LINE_1_H 3 void line1_print(const char *strMsg); 4 #endif line1.cpp 1 #include "line1.h" 2 #include <stdio.h> 3 void line1_print(const char *strMsg) 4 { 5 printf("This is

Shell特殊变量:Shell $0, $#, $*, [email&#160;protected], $?, $$和命令行参数

变量名只能包含数字.字母和下划线,因为某些包含其他字符的变量有特殊含义,这样的变量被称为特殊变量. 例如,$ 表示当前Shell进程的ID,即pid,看下面的代码: $echo $$ 运行结果 29949 特殊变量列表 变量 含义 $0 当前脚本的文件名 $n 传递给脚本或函数的参数.n 是一个数字,表示第几个参数.例如,第一个参数是$1,第二个参数是$2. $# 传递给脚本或函数的参数个数. $* 传递给脚本或函数的所有参数. [email protected] 传递给脚本或函数的所有参数.被

[email&#160;protected]和@synthesize

@porperty @porperty是一个编译器指令 在Xocde4.4之前, 可以使用@porperty来代替getter/setter方法的声明, 也就是说我们只需要写上@porperty就不用写getter/setter方法的声明 2.编译器只要看到@property,就知道我们要生成某一个属性的getter/setter方法的声明 @propertyde格式 @property数据类型变量名 property增强 从Xcode4.4以后,对@property进行了增强, 以后只要利用一