python基础四:装饰器

装饰器本质:就是函数,功能是为其他函数添加附加功能

装饰器原则:

  1. 不修改被修饰函数的源代码
  2. 不修改修饰函数的调用方式

装饰器的知识储备:

装饰器 = 高阶函数 + 函数嵌套 + 闭包

初识装饰器

先看一个需求:下面这个函数用来计算1到20的和

def calc(l):
    res = 0
    for i in l:
        time.sleep(0.01)
        res += i
    return res
result = calc(range(1,21))
print(result)

但现在需求有变,不仅要计算1到20的和,还需要计算该函数运行的时间,此时装饰器就应需而生

import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)
        stop_time = time.time()
        print(‘函数运行的时间为:%s‘ % (stop_time - start_time))
        return res
    return wrapper
@timer
def calc(l):
    res = 0
    for i in l:
        time.sleep(0.01)
        res += i
    return res
result = calc(range(1,21))
print(result)

运行结果如下:

函数运行的时间为:0.2048475742340088
210

上面的timer函数就是calc函数的装饰器

高阶函数

高阶函数定义:
1.函数接收的参数是一个函数名

2.函数的返回值是一个函数名

3.满足上述条件任意一个,都可称之为高阶函数

高阶函数示例

def foo():
    print(‘我的函数名作为参数传给高阶函数‘)
def gao_jie1(func):
    print(‘我就是高阶函数1,我接收的参数名是%s‘ %func)
    func()

def gao_jie2(func):
    print(‘我就是高阶函数2,我的返回值是%s‘ %func)
    return func

gao_jie1(foo)
gao_jie2(foo)

把函数当作参数传给高阶函数

#高阶函数应用1:把函数当做参数传给高阶函数
import time
def foo():
    print(‘from the foo‘)

def timmer(func):
    start_time=time.time()
    func()
    stop_time=time.time()
    print(‘函数%s 运行时间是%s‘ %(func,stop_time-start_time))
timmer(foo)
#总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式

函数返回值是函数名

#高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名
import time
def foo():
    print(‘from the foo‘)

def timmer(func):
    start_time=time.time()
    return func
    stop_time=time.time()
    print(‘函数%s 运行时间是%s‘ %(func,stop_time-start_time))
foo=timmer(foo)
foo()
#总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能

高阶函数总结
1.函数接收的参数是一个函数名
  作用:在不修改函数源代码的前提下,为函数添加新功能,
  不足:会改变函数的调用方式
2.函数的返回值是一个函数名
  作用:不修改函数的调用方式
  不足:不能添加新功能

函数嵌套

def father(name):
    print(‘from father %s‘ %name)
    def son():
        print(‘from son‘)
        def grandson():
            print(‘from grandson‘)
        grandson()
    son()
father(‘Poe‘)

闭包

‘‘‘
闭包:在一个作用哉里放放定义变量,相当于打了一个包
‘‘‘
def father(name):
    def son():
        print(‘My father is %s‘ %name)
        def grandson():
            print(‘my grandpa is %s‘ %name)
        grandson()
    son()
father(‘Poe‘)

无参数装饰器

无参装饰器=高级函数+函数嵌套

基本框架

‘‘‘
这就是一个实现 装饰器最基本的架子
‘‘‘
def timer(func):
    def wrapper():
        func()
    return wrapper()

回到上面需要计算函数运行时间的需求,在不使用装饰器的情况下加上以下代码

import time
def timer(func):
    def wrapper():
        startTime = time.time()
        func()
        stopTime = time.time()
        print(‘函数运行时间为:%s‘ % (stopTime - startTime))
    return wrapper

def test():
    time.sleep(3)
    print(‘test函数运行完毕‘)

res = timer(test)
res()

使用装饰器

import time
def timer(func):
    def wrapper():
        startTime = time.time()
        func()
        stopTime = time.time()
        print(‘函数运行时间为:%s‘ % (stopTime - startTime))
    return wrapper
@timer  #相当于test = timer(test)
def test():
    time.sleep(3)
    print(‘test函数运行完毕‘)
test()

返回值问题
如果test函数中有返回值怎么返回呢?test函数被调用时,实质就是调用wrapper函数,如果要返回test函数中的值,必须要在wrapper函数中将该值返回

import time

def timer(func):
    def wrapper():
        startTime = time.time()
        res = func()
        stopTime = time.time()
        print(‘该函数运行时间为:%s‘ % (stopTime - startTime))
        return res
    return wrapper

@timer
def test():
    time.sleep(1)
    print(‘该函数运行完毕‘)
    return ‘这是test的返回值‘
res = test()        #实质调用的是wrapper函数
print(res)

带参数的装饰器

import time

def timer(func):
    def wrapper(*args,**kwargs):
        startTime = time.time()
        res = func(*args,**kwargs)
        stopTime = time.time()
        print(‘该函数运行时间为:%s‘ % (stopTime - startTime))
        return res
    return wrapper

@timer  #test = timer(test)
def test(name,age):
    time.sleep(1)
    print(‘该函数运行完毕,name is %s,age is %s‘ %(name,age))
    return ‘这是test的返回值‘
res = test(‘andy‘,18)        #实质调用的是wrapper函数
print(res)

补充知识:解压序列

>>> a,b,c=(2,3,4)
>>> a
2
>>> b
3
>>> c
4

a , b, c变量要与元组中的元素一一对应才能取到值
那么再看一个实例:

>>> l=[1,2,3,4,5,6,7,8]

利用序列的方法如何取得上面列表中的第一个元素与最后一个元素

>>> l=[1,2,3,4,5,6,7,8]
>>> l
[1, 2, 3, 4, 5, 6, 7, 8]
>>> a,*_,c=l
>>> a
1
>>> c
8
>>> a,*b,c=l
>>> a
1
>>> b
[2, 3, 4, 5, 6, 7]
>>> c
8

注意:号代表除a,c变量外所有元素,号后面必须要有一个变量,使用下划线表示*号代表的变量不想被取出

该方法可用来交换两个变量的值:

>>> a=1
>>> b=2
>>> a,b=(b,a)
>>> a
2
>>> b
1

装饰器示例

user_list = [
    {‘name‘:‘andy‘,‘passwd‘:‘123‘},
    {‘name‘:‘bruce‘,‘passwd‘:‘123‘},
    {‘name‘:‘poe‘,‘passwd‘:‘123‘},
    {‘name‘:‘jacky‘,‘passwd‘:‘123‘},
]
current_dic = {‘username‘:None,‘login‘:False}

def auth_func(func):
    def wrapper(*args,**kwargs):
        if current_dic[‘username‘] and current_dic[‘login‘]:
            res = func(*args,**kwargs)
            return res
        username = input(‘username:‘).strip()
        password = input(‘password:‘).strip()
        for user_dic in user_list:
            if username == user_dic[‘name‘] and password == user_dic[‘passwd‘]:
                current_dic[‘username‘] = username
                current_dic[‘login‘] = True
                res = func(*args,**kwargs)
                return res
        else:
            print(‘用户名或密码错误‘)
    return wrapper

@auth_func
def index():
    print(‘欢迎来到JD主页‘ )
@auth_func
def home(name):
    print(‘welcome %s to home‘ % name)
@auth_func
def shopping(name):
    print(‘%s的购物车里有%s,%s,%s‘ %(name,‘奶茶‘,‘妹妹‘,‘牙膏‘))

print(‘before : ‘,current_dic)
index()
home(‘andy‘)
shopping(‘andy‘)
print(‘after: ‘,current_dic)

代码执行结果:

before :  {‘username‘: None, ‘login‘: False}
username:andy
password:123
欢迎来到JD主页
welcome andy to home
andy的购物车里有奶茶,妹妹,牙膏
after:  {‘username‘: ‘andy‘, ‘login‘: True}

原文地址:http://blog.51cto.com/12332406/2159780

时间: 2024-10-09 04:07:36

python基础四:装饰器的相关文章

[python基础]关于装饰器

在面试的时候,被问到装饰器,在用的最多的时候就@classmethod ,@staticmethod,开口胡乱回答想这和C#的static public 关键字是不是一样的,等面试回来一看,哇,原来是这样,真佩服我当时厚着脸皮回答的那些问题... OK,先来张图看看装饰器内容: OK,我们留下一个印象,然后我们看实际的场景来操作. 我们先看一个方法: __author__ = 'bruce' def do_sth(): print 'some thing has been done' if __

Python基础【装饰器】

装饰器: 装饰器:用来修改函数功能的函数 可以在不改变原函数的基础上添加功能实现装饰器的方法:从函数中返回函数,将原函数作为一个参数传给另一个函数 代码:装饰器pro_print在函数执行前输出提示"welcome to class" def pro_print(fun): # 装饰器函数 def wrapper(*args,**kwargs): # 接收各种类型的不定长参数 print("welcome to class") fun() return wrappe

1.16 Python基础知识 - 装饰器

Python中的装饰器就是函数,作用就是包装其他函数,为他们起到修饰作用.在不修改源代码的情况下,为这些函数额外添加一些功能,像日志记录,性能测试等.一个函数可以使用多个装饰器,产生的结果与装饰器的位置顺序有关. 装饰器基本形式: @装饰器1 def 函数1: 函数体 相当于:==> 函数1 = 装饰器1(函数1) 装饰器特点: 1.不修改源代码的调用方式 2.不修改源代码内容 3.装饰器有高阶函数与递归函数相融合的特点 多个装饰器修饰,示例: @foo @spam def bar():pass

Python基础4 装饰器

python装饰器 一:函数调用顺序:其他高级语言类似,Python 不允许在函数未声明之前,对其进行引用或者调用错误示范: def foo():     print 'in the foo'     bar()       foo()   报错: in the foo   Traceback (most recent call last):   File "<pyshell#13>", line 1, in <module>     foo()   File 

【Python基础】装饰器的解释和用法

装饰器的用法比较简单,但是理解装饰器的原理还是比较复杂的,考虑到接下来的爬虫框架中很多用到装饰器的地方,我们先来讲解一下. 函数 我们定义了一个函数,没有什么具体操作,只是返回一个固定值 请注意一下缩进 def sample(): return 1 print(sample()) 作用域 函数内部的变量和函数外的变量是不同的 我们看一下下面的例子,locals()和globals()方法会得到局部变量和全局变量 我们可以在函数中调用全局变量,但是无法在函数中改变全局变量的值 global_str

Python基础15_装饰器

一. 装饰器 开闭原则: 软件设计的原则之一, 又称为开放封闭原则. 开放: 对功能扩展开放 封闭: 对修改代码封闭 装饰器: 在目标函数前或后插入一段新的代码, 不改变目标函数的代码 可以给目标函数传参, 拿到目标函数的返回值 python里面的动态代理 在不破坏目标函数和目标函数调用的基础上给函数添加新的功能 通用语法: def wrapper(fn):                        # fn 是目标函数 def inner(*args, **kwargs):        

Python基础day-8[装饰器补充,迭代器(未完)]

wraps模块: 让函数保留原来的说明信息. 在闭包函数上面 @wraps 可以把原代码的解释,引用到装饰器中,让用户彻底无法感知装饰器的存在 使用 func.__doc__ 和 print(help(func))来查看函数的注释信息 from functools import wraps import time def coutime(func): @wraps(func) #调用wraps模块 def wrapper(*args,**kwargs): # 'a1231231231231232

python基础 之 装饰器详解

装饰器的语法以@开头,接着是装饰器函数的名字.可选参数. 紧跟装饰器声明的是被装饰的函数和被装饰的函数的可选参数,如下: @decorator(dec_opt_args) def func(func_args):   .... 其实总体说起来,装饰器其实也就是一个函数,一个用来包装函数的函数,装饰器在函数声明完成的时候被调用,调用之后声明的函数被换成一个被装饰器装饰过后的函数. 如: def deco(func):    ...    return func @deco def foo():  

Python基础(装饰器)

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

Python基础05 - 装饰器

@@@文章内容参照老男孩教育 Alex金角大王,武Sir银角大王@@@ 函数即对象 在python中,函数和我们之前的[1,2,3],'abc',8 等一样都是对象,而且函数是最高级的对象(对象是类的实例化,可以调用相应的方法,函数是包含变量对象的对象.) 高阶函数 嵌套函数及闭包 1 def func(): 2 x = 1 3 def foo(): 4 print(x) 5 return foo 6 7 a = func() 8 a() 闭包(closure)是函数式编程的重要的语法结构 定义