Python之路【第四篇】:Python基础(19)——装饰器

#普通装饰器# (@+函数名),需要记住关键两点:#功能:#1、自动执行outer函数,并且将其下面的函数名f1当作参数传递#2、将outer函数的返回值,重新赋值给f1

# #装饰器必备# ####第一:函数名和执行函数##### def foo():    #创建函数#     print(‘hello‘)    #函数体# foo #表示是函数名,代指整个函数# foo()   #表示执行f00函数# # 输出:hello

# ####第二:函数被重新定义#### def foo():#     print("foo1")## foo = lambda : print("foo2")    #lambda表达式,无参数## foo()   #执行下面的lambda表达式,而不是原来的foo函数,foo函数已经被重新定义

# #同名函数被覆盖# def f1():   #1#     print(123)## def f1():#2 #4#     print(456)  #5# f1()    #3# #输出: 456

#f1函数作为参数进行传递# def f1():   #1 创建f1函数 #6执行f1()函数,结果是打印输出123#     print("123")    #7#     #没有return,默认返回None# def f2(xxx):    #2 创建f2函数 #4  接收到传递的f1以后,xxx也是代指f1函数的整体,f2(xxx)就相当于f2(f1)#     ret = xxx()   #5  xxx()就等于是f1(),f1()就代表去执行f1()这整个函数。## f2(f1)    #3 调用f2函数,f1作为参数(f1没有单引号和双引号是一个函数名; f1没有带括号(),代指的是f1函数的整体,f1作为参数传递给xxx

# #装饰器   流程剖析 分解功能1:自动执行outer()函数,并将下面的函数名f1作为参数传递    ()# # def outer():    #TypeError: outer() takes 0 positional arguments but 1 was given 翻译:outer需要0个参数,但传递了1个参数# def outer(func):    #1在内存中创建outer函数  #3执行outer(f1)函数  #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。#     print(123)  #4  执行函数体:打印123#     print(func) #5  执行函数体:打印func参数,输出:<function f1 at 0x0000000000B28620># @outer  #2  自动执行outer()函数,并将下面的函数名f1作为参数传递。即@outer等价于outer(f1)# def f1():#     print("F1")

# #装饰器  流程剖析 分解功能2:将outer函数的返回值111,重新赋值给f1# def outer(func):    #1在内存中创建outer函数  #3执行outer(f1)函数  #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。#     return "111"    #4  将outer函数的返回值111,重新赋值给f1。# @outer  #2  自动执行outer()函数,并将下面的函数名f1作为参数传递# def f1():#     print("F1")# print(f1)   #5  原来的f1函数被覆盖,被重新赋值为111.

#问题解析:#4 (为什么outer函数的返回值111,就重新赋值给了f1,f1并没有调用outer(f1)函数啊?)这个问题纠结了我至少4个小时。感谢绍宁指点。如下:# @outter 等价于 outter(f1)# 等价于f1=outter(f1)# outter函数的返回值是111# 所以f1就变成了111# 装饰器就是在把原来的函数包起来加工一下,但是加工后还是叫原来的函数名,用了装饰器后 原来的函数名 等于装饰器函数的返回值# 参考链接:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html# #函数是一个对象,可以赋值给其他对象变量,通过变量可以调用该函数。# def foo():#     print("test")# f = foo #注意没有使用圆括号,因为不是在调用函数# f()# # # 输出:test# print(foo.__name__)#通过函数对象_name_属性,可以拿到函数的名字:# #输出:foo# print(f.__name__)# # 输出:foo

#装饰器 流程剖析   将outer函数的返回值,换成其他函数。#注:解释器解释后f1函数就等于111,这样f1函数就被成功修改了,那以后外部再来调用f1函数的时候就会调用111,那我们就成功的将f1函数换成了111#我们能把f1换成111,同理,也能换成一个其他函数。# def outer(func):    #1在内存中创建outer函数  #3执行outer(f1)函数  #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。#     # return "111"    #4  将outer函数的返回值111,重新赋值给f1。#     def inner():    #4 在内存中创建inner函数    #8 外部调用f1()函数就等于是调用inner函数,f1函数换成了inner函数,即新f1函数。#         print("在执行老的f1函数之前执行命令") #9  在执行老的f1函数之前执行#         func()  #10 第2步时,f1函数作为参数传递给了outer函数的func参数,func代指的就是老的f1函数,即装饰的原函数,func加括号,代表执行老的f1()函数#         print("在执行老的f1函数之后执行命令")    #11 在执行老的f1函数之后执行#     return inner    #5 inner不加括号代指的是整个inner函数,将outer函数的返回值inner函数,重新赋值给f1,f1就代指的是inner函数。#                     #inner()加括号是执行inner函数,代表的是return之前先执行inner函数,然后把返回值(默认为None)赋值给f1,把inner函数#                     #执行后的返回值赋值给f1,外部程序再调用时得到的是inner的返回值,不是f1的返回值,这样做会破坏f1函数原有的功能## @outer  #2  自动执行outer()函数,并将下面的函数名f1作为参数传递# def f1():#     print("F1")# # print(f1)   #6  原来的f1函数被覆盖,被重新赋值为inner函数。#  <function outer.<locals>.inner at 0x00000000030AF1E0>

# #装饰器 流程剖析   返回值# #注:解释器解释后f1函数就等于111,这样f1函数就被成功修改了,那以后外部再来调用f1函数的时候就会调用111,那我们就成功的将f1函数换成了111# #我们能把f1换成111,同理,也能换成一个其他函数。# def outer(func):    #1在内存中创建outer函数  #3执行outer(f1)函数  #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。#     # return "111"    #4  将outer函数的返回值111,重新赋值给f1。#     def inner():    #4 在内存中创建inner函数    #8 外部调用f1()函数就等于是调用inner函数,f1函数换成了inner函数,即新f1函数。#         print("在执行老的f1函数之前执行命令") #9  在执行老的f1函数之前执行#         # ret = func()  #10 第2步时,f1函数作为参数传递给了outer函数的func参数,func代指的就是老的f1函数,即装饰的原函数,func加括号,代表执行老的f1()函数#         r = func()  #10 执行func()函数,等于执行原f1()函数,原f1函数有返回值,定义变量r用于接收原f1函数的返回值#         print("在执行老的f1函数之后执行命令")    #11 在执行老的f1函数之后执行#         return r    #12 r代表原f1函数的返回值,新f1函数执行之后将原f1函数的返回值返回给函数调用者。(函数遇到return就不再向下执行,所以把return放在最下面)#     return inner    #5 inner不加括号代指的是整个inner函数,将outer函数的返回值inner函数,重新赋值给f1,f1就代指的是inner函数。#                     #inner()加括号是执行inner函数,代表的是return之前先执行inner函数,然后把返回值(默认为None)赋值给f1,把inner函数#                     #执行后的返回值赋值给f1,外部程序再调用时得到的是inner的返回值,不是f1的返回值,这样做会破坏f1函数原有的功能## @outer  #2  自动执行outer()函数,并将下面的函数名f1作为参数传递# def f1():#     print("F1")#     return "原f1函数返回值FFFF"    #原f1函数有返回值FFFF# # print(f1)   #6  原来的f1函数被覆盖,被重新赋值为inner函数。#  <function outer.<locals>.inner at 0x00000000030AF1E0>

# #装饰器 流程剖析   1个参数# #注:解释器解释后f1函数就等于111,这样f1函数就被成功修改了,那以后外部再来调用f1函数的时候就会调用111,那我们就成功的将f1函数换成了111# #我们能把f1换成111,同理,也能换成一个其他函数。# def outer(func):    #1在内存中创建outer函数  #3执行outer(f1)函数  #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。#     # return "111"    #4  将outer函数的返回值111,重新赋值给f1。#     def inner(a):    #4 在内存中创建inner函数    #8 外部调用f1()函数就等于是调用inner函数,f1函数换成了inner函数,即新f1函数。#8.1外部调用新f1函数的实参,首先传递给形参“a”#         print("在执行老的f1函数之前执行命令") #9  在执行老的f1函数之前执行#         # ret = func()  #10 第2步时,f1函数作为参数传递给了outer函数的func参数,func代指的就是老的f1函数,即装饰的原函数,func加括号,代表执行老的f1()函数#         r = func(a)  #10 执行func()函数,等于执行原f1()函数,原f1函数有返回值,定义变量r用于接收原f1函数的返回值    #10.1将函数调用者传递的参数传递给原f1()函数。#         print("在执行老的f1函数之后执行命令")    #11 在执行老的f1函数之后执行#         return r    #12 r代表原f1函数的返回值,新f1函数执行之后将原f1函数的返回值返回给函数调用者。(函数遇到return就不再向下执行,所以把return放在最下面)#     return inner    #5 inner不加括号代指的是整个inner函数,将outer函数的返回值inner函数,重新赋值给f1,f1就代指的是inner函数。#                     #inner()加括号是执行inner函数,代表的是return之前先执行inner函数,然后把返回值(默认为None)赋值给f1,把inner函数#                     #执行后的返回值赋值给f1,外部程序再调用时得到的是inner的返回值,不是f1的返回值,这样做会破坏f1函数原有的功能## @outer  #2  自动执行outer()函数,并将下面的函数名f1作为参数传递# def f1(arg):    #10.2接收函数调用者传递的参数arf = a#     # print("F1")#     print(arg)#     return "原f1函数返回值FFFF"    #原f1函数有返回值FFFF# # print(f1)   #6  原来的f1函数被覆盖,被重新赋值为inner函数。#  <function outer.<locals>.inner at 0x00000000030AF1E0>

#注:解释器解释后f1函数就等于111,这样f1函数就被成功修改了,那以后外部再来调用f1函数的时候就会调用111,那我们就成功的将f1函数换成了111#我们能把f1换成111,同理,也能换成一个其他函数。# def outer(func):    #1在内存中创建outer函数  #3执行outer(f1)函数  #这是装饰器的基本格式,必须带参数,如果没有参数就会报错。#     # return "111"    #4  将outer函数的返回值111,重新赋值给f1。#     def inner(a):    #4 在内存中创建inner函数    #8 外部调用f1()函数就等于是调用inner函数,f1函数换成了inner函数,即新f1函数。#8.1外部调用新f1函数的实参,首先传递给形参“a”#         print("在执行老的f1函数之前执行命令") #9  在执行老的f1函数之前执行#         # ret = func()  #10 第2步时,f1函数作为参数传递给了outer函数的func参数,func代指的就是老的f1函数,即装饰的原函数,func加括号,代表执行老的f1()函数#         r = func(a)  #10 执行func()函数,等于执行原f1()函数,原f1函数有返回值,定义变量r用于接收原f1函数的返回值    #10.1将函数调用者传递的参数传递给原f1()函数。#         print("在执行老的f1函数之后执行命令")    #11 在执行老的f1函数之后执行#         return r    #12 r代表原f1函数的返回值,新f1函数执行之后将原f1函数的返回值返回给函数调用者。(函数遇到return就不再向下执行,所以把return放在最下面)#     return inner    #5 inner不加括号代指的是整个inner函数,将outer函数的返回值inner函数,重新赋值给f1,f1就代指的是inner函数。#                     #inner()加括号是执行inner函数,代表的是return之前先执行inner函数,然后把返回值(默认为None)赋值给f1,把inner函数#                     #执行后的返回值赋值给f1,外部程序再调用时得到的是inner的返回值,不是f1的返回值,这样做会破坏f1函数原有的功能## @outer  #2  自动执行outer()函数,并将下面的函数名f1作为参数传递# def f1(arg):    #10.2接收函数调用者传递的参数arf = a#     # print("F1")#     print(arg)#     return "原f1函数返回值FFFF"    #原f1函数有返回值FFFF# # print(f1)   #6  原来的f1函数被覆盖,被重新赋值为inner函数。#  <function outer.<locals>.inner at 0x00000000030AF1E0>

#装饰器 流程剖析   函数传递多个参数使用万能参数,*args,**kwargs

def outer(func):    #创建outer函数;f2函数作为参数传递给outer函数,func代指装饰的原函数,即原f2函数。    def inner(*args,**kwargs):    #创建嵌套的inner函数,a,b接收f2函数调用者传递的参数   #*args,**kwargs可以接收任意参数        # pass        print("before:执行原函数之前")        r = func(*args,**kwargs)  #执行原函数,接收原函数返回值;a,b将调用者传递的参数传递给原f2函数。#python自动把*args,**kwargs里面的参数传递给原函数        print("after:执行原函数之后")        return r    #返回原函数返回值    return inner    #将inner函数的返回值重新赋值给f2函数,inner函数即为新f2函数。(inner后面无括号)@outerdef f1():    print("F1")    return "f1"@outerdef f2(a1,a2):    print(a1,a2)    return "f2"
时间: 2024-08-03 19:23:38

Python之路【第四篇】:Python基础(19)——装饰器的相关文章

Pthon学习之路 第四篇 Python基础(二)

1.运算符:+  -  *(乘法)  /(除法)  %(求余)  //(求商)  **(求幂) 2.成员运算:in      not in:判断单个字符或者子序列在不在字符串中.(not in是in的反操作) [在python里在英文输入法下用  "  " 引起来的整体叫字符串,其里面的每一个个体单位叫做一个字符.字符串中的两个或者两个以上连续的字符叫做字符串的子序列] n1=input("请输入名言:") if "中国真好" in n1: pr

Python之路【第二篇】:Python基础(一)

Python之路[第二篇]:Python基础(一) 入门知识拾遗 一.作用域 对于变量的作用域,执行声明并在内存中存在,该变量就可以在下面的代码中使用. 1 2 3 if 1==1:     name = 'wupeiqi' print  name 下面的结论对吗? 外层变量,可以被内层变量使用 内层变量,无法被外层变量使用 二.三元运算 1 result = 值1 if 条件 else 值2 如果条件为真:result = 值1如果条件为假:result = 值2 三.进制 二进制,01 八进

Python之路【第九篇】:Python基础(26)——socket server

socketserver Python之路[第九篇]:Python基础(25)socket模块是单进程的,只能接受一个客户端的连接和请求,只有当该客户端断开的之后才能再接受来自其他客户端的连接和请求.当然我 们也可以通过python的多线程等模块自己写一个可以同时接收多个客户端连接和请求的socket.但是这完全没有必要,因为python标准库已经为 我们内置了一个多线程的socket模块socketserver,我们直接调用就可以了,完全没有必要重复造轮子. 我们只需简单改造一下之前的sock

Python之路【第九篇】:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

Python之路[第九篇]:Python操作 RabbitMQ.Redis.Memcache.SQLAlchemy Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度.Memcached基于一个存储键/值对的hashmap.其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信. Memc

python学习记录第四篇--数据库

只要用到MySQLdb,使用时请先安装MySQLdb,百度上可以下载! #coding=utf-8'''@author: 使用python操作MySQL数据库'''import MySQLdb#import MySQLdb.cursorsconn=MySQLdb.connect(user='root',passwd='root') #connect共三个值,user,passwd,host,无密码且连接本地数据库时,可以都为空.cur=conn.cursor() #创建游标,使用游标进行数据库操

Python之路番外:PYTHON基本数据类型和小知识点

Python之路番外:PYTHON基本数据类型和小知识点 一.基础小知识点 1.如果一行代码过长,可以用续行符 \换行书写 例子 if (signal == "red") and (car == "moving"): car = "stop" else : pass 等同于 if (signal == "red") and (car == "moving"): car = "stop"

Python学习系列(四)Python 入门语法规则2

Python学习系列(四)Python 入门语法规则2 2017-4-3 09:18:04 编码和解码 Unicode.gbk,utf8之间的关系 2.对于py2.7, 如果utf8>gbk, utf8解码成Unicode,再将unicode编码成gbk 对于py3.5 如果utf8>gbk, utf8 直接编码成gbk(中间那一步直接被优化了) 3.很多时候,这个可以直接跳过,只有当编码出下问题的时候,再考虑这个知识点 二.运算符 1.算数运算: 2.比较运算: 3.赋值运算: 4.逻辑运算

Python基础(装饰器)

代码的编写和软件的开发,都应该遵循开放封闭原则. 开放封闭原则(OCP,Open Closed Principle)是所有面向对象原则的核心.其核心思想是: 对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况. 对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改. 而装饰器(就是函数)的作用就是为已经存在的对象添加额外的功能. 此篇文章主要介绍装饰器的五种使用情况. 需求场景: 让一个已经开发完成的功能在执行之前,先执行某些操作. 一.基本用

Python之路【第一篇】:Python基础

本节内容 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 .pyc是个什么鬼? 数据类型初识 数据运算 表达式if ...else语句 表达式for 循环 break and continue 表达式while 循环 作业需求 一. Python介绍 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语

Python之路(第四十二篇)线程相关的其他方法、join()、Thread类的start()和run()方法的区别、守护线程

一.线程相关的其他方法 Thread实例对象的方法 # isAlive(): 返回线程是否活动的. # getName(): 返回线程名. # setName(): 设置线程名. ? threading模块提供的一些方法: # threading.currentThread(): 返回当前的线程对象. # threading.enumerate(): 返回一个包含正在运行的线程的list.正在运行指线程启动后.结束前,不包括启动前和终止后的线程. # threading.activeCount(