python自学大数据 爬虫Python AI Sql

python装饰器

2018-05-18  本文已影响49人  dpengwang

python装饰器是一个以函数作为参数并返回一个替换函数的可执行函数,在不改变函数源码的情况下为函数增添一些新功能

函数装饰器

不带参数的装饰器

python接收函数返回函数实现:

def outer(func):
   def innner():
       print("before func")
       ret =func()
       return ret+1
   return innner
def func():
   return 1

newfunc =  outer(func)
print(newfunc())

==>

2

newfunc()就是func函数的装饰版本,注意写这种闭包函数的时候函数是否加( )(即是调用函数引用还是函数执行的问题)

利用@语法糖形式

def outer(func):
    def innner():
        print("before func")
        ret =func()
        return  ret+1
    return innner
@outer
def func():
    return 1
func()
2
带参数的装饰器

上面的装饰器中,装饰器的唯一参数就是在执行业务的参数,装饰器的允许我们在调用时,提供其他参数,这样就为装饰器的编写和使用提供了更大的灵活性

不带参数的装饰器一般有两层,带参数的装饰器一般三层(我认为的),最内层返回原函数的调用,@得到装饰后的函数,调用的时候将返回的方法执行出来

import logging
def use_logging(level):
    def decrator(func):
        def wrapper():
            if level=="warn":
                logging.warn("this is warning")
            return func()
        return wrapper
    return decrator
@use_logging(level="warn")
def f():
    print("hello")
f()

不用语法糖的形式是:

func=use_logging(level="warn")(foo)
f()

ps:才知道竟然可以这样给嵌套函数传递参数TT

类装饰器

写一个类,里面实现initcall方法,call方法会别自动装饰在目标函数上,在使用@语法糖的时候,以@类名()的形式,而装饰器函数时@func的形式

class logged(object):
    def __init__(self):
        pass

    def __call__(self, func):
        def wrapped_function():
            print("decorator has run")
            return func()
        return wrapped_function


@logged()
def f():
    print("hello")
f()

==>

decorator has run
hello

装饰器的缺点

会使原函数的元信息被装饰器的信息覆盖,比如函数的_name_

def loggeg(func):
    def with_logging(*args):
        print(func.__name__+" is calling")
        return  func(*args)
    return  with_logging
@loggeg
def f():
    print("hello")

print(f.__name__)

==>

with_logging

不加装饰器的时候输出的是f

用functools.wraps可以将原函数的元信息拷贝到装饰器函数中,这样就能让装饰器函数和原函数有一样的元信息了

from functools import  wraps
def loggeg(func):
    @wraps(func)#注意要传入func
    def with_logging(*args):
        print(func.__name__+" is calling")
        return  func(*args)
    return  with_logging
@loggeg
def f():
    print("hello")

print(f.__name__)

==>

f
上一篇下一篇

猜你喜欢

热点阅读