python装饰器原理简介

最初的函数

实现一个打印函数,两个功能:

  • 打印:i am foo
  • 日志输出: foo is running
import logging

logging.basicConfig(level=logging.INFO)


def hello():
    print 'Hello world!'
    logging.info("hello is running")


hello()

控制台输出效果:

Hello world!
INFO:root:hello is running

两个函数有重复内容

两个函数都要输出日志:函数名 is running。

import logging

logging.basicConfig(level=logging.INFO)


def hello():
    print 'Hello world!'
    logging.info("hello is running")


def welcome():
    print 'Welcome!'
    logging.info("welcome is running")


hello()
welcome()

控制台输出效果:

Hello world!
INFO:root:hello is running
INFO:root:welcome is running
Welcome!

重构两个函数:提炼重复部分

把重复的部分logging.info("函数名 is running")提出来。

import logging

logging.basicConfig(level=logging.INFO)

def log_func(func):
    logging.info("%s is running" % func.__name__)
    func()


def hello():
    print 'Hello world!'


def welcome():
    print 'Welcome!'


log_func(hello)
log_func(welcome)

显示效果如下,与上面一节相同:

Hello world!
INFO:root:hello is running
Welcome!
INFO:root:welcome is running

再次重构:保持原函数名

仍然保留了原来的函数名:

import logging

logging.basicConfig(level=logging.INFO)

def log_func(func):

    def wrapper():
        logging.info("%s is running" % func.__name__)
        return func()
    return wrapper

def hello():
    print "Hello world!"

def welcome():
    print "Welcome!"

hello = log_func(hello)
hello()

welcome = log_func(welcome)
welcome()

输出效果:

INFO:root:hello is running
Hello world!
INFO:root:welcome is running
Welcome!

为了保证参数正确,使用不定参数

import logging

logging.basicConfig(level=logging.INFO)

def log_func(func):

    def wrapper(*args, **kwargs):
        logging.info("%s is running" % func.__name__)
        return func(*args, **kwargs)
    return wrapper

def hello():
    print "Hello world!"

def welcome():
    print "Welcome!"

hello = log_func(hello)
hello()

welcome = log_func(welcome)
welcome()

语法糖:@函数名

@函数名是语法糖,直接表示包裹在该函数的外层函数。最终还是调用里层函数,就可以同时实现包裹的外层函数的作用。

import logging

logging.basicConfig(level=logging.INFO)

def log_func(func):

    def wrapper(*args, **kwargs):
        logging.info("%s is running" % func.__name__)
        return func(*args, **kwargs)
    return wrapper

@log_func
def hello():
    print "Hello world!"

@log_func
def welcome():
    print "Welcome!"

hello()

welcome()

最终显示:

Hello world!
INFO:root:hello is running
Welcome!
INFO:root:welcome is running
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,282评论 19 139
  • 每个人都有的内裤主要功能是用来遮羞,但是到了冬天它没法为我们防风御寒,咋办?我们想到的一个办法就是把内裤改造一下,...
    chen_000阅读 5,160评论 0 3
  • //Clojure入门教程: Clojure – Functional Programming for the J...
    葡萄喃喃呓语阅读 9,303评论 0 7
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 177,245评论 25 709
  • 看完大结局,总觉得故事未完。 十年之后归来的若飞为了曾经的爆炸事故寻找真相,因为一个古董相机,命运的齿轮开始转动,...
    杏花疏影里阅读 2,144评论 0 2

友情链接更多精彩内容