资讯专栏INFORMATION COLUMN

python decorators

Yangyang / 523人阅读

摘要:装饰器基础本质本质是语法糖使用来修饰某个函数时其解释器会解释成注意这条语句会被执行多重装饰器相当于带参数装饰器相当于使用给被装饰函数传递参数是一个数组,一个字典带参数的装饰器等同于方法装饰器类方法是一个特殊的函数,它的第一个参数指向类实例

python decorators 装饰器基础 Decorator 本质

@ 本质是语法糖- Syntactic Sugar
使用@decorator 来修饰某个函数 func 时:

@decorator
def func():
    pass

其解释器会解释成:

func = decorator(func)

注意这条语句会被执行

多重装饰器

@decorator_one
@decorator_two
def func():
    pass

相当于:

func = decorator_one(decorator_two(func))

带参数装饰器

@decorator(arg1, arg2)
def func():
    pass

相当于:

func = decorator(arg1,arg2)(func)
使用 *args、**kwargs 给被装饰函数传递参数
def wrapper(func):
    def wrapper_in(*args, **kwargs):
        # args是一个数组,kwargs一个字典
        print("%s is running" % func.__name__)
        return func(*args, **kwargs)
    return wrapper_in

@wrapper
def func(parameter1, parameter2, key1=1):
    print("call func with {} {} {}".format(parameter1, parameter2, key1))


func("haha", None, key1=2)

# func is running
# call func with haha None 2
带参数的装饰器
def log(level):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if level == "warn":
                print("%s with warn is running" % func.__name__)
            elif level == "info":
                print("%s with info is running" % func.__name__)
            return func(*args, **kwargs)
        return wrapper

    return decorator


@log("warn")
def foo(*args, **kwargs):
    print("args {}, kwargs{}".format(args, kwargs))

foo(1, 2, a = 3)

# foo with warn is running
# args (1, 2), kwargs{"a": 3}

等同于

def foo(name="foo"):
    print("args {}, kwargs{}".format(args, kwargs))

foo = log("warn")(foo)
方法装饰器

类方法是一个特殊的函数,它的第一个参数 self 指向类实例
所以我们同样可以装饰类方法

def decorate(func):
   def wrapper(self):
       return "

{0}

".format(func(self)) return wrapper class Person(object): def __init__(self): self.name = "John" self.family = "Doe" @decorate def get_fullname(self): return self.name+" "+self.family my_person = Person() print my_person.get_fullname() #

John Doe

上例相当于固定了 self 参数,不太灵活
使用 *args, **kwargs传递给 wrapper 更加通用:

def pecorate(func):
   def wrapper(*args, **kwargs):
       return "

{0}

".format(func(*args, **kwargs)) return wrapper class Person(object): def __init__(self): self.name = "John" self.family = "Doe" @pecorate def get_fullname(self): return self.name+" "+self.family my_person = Person() print my_person.get_fullname()
类装饰器

类实现 __call__ 方法后变成可调用对象,故可以用类做装饰器

class EntryExit(object):

    def __init__(self, f):
        self.f = f

    def __call__(self):
        print "Entering", self.f.__name__
        self.f()
        print "Exited", self.f.__name__

@EntryExit
def func1():
    print "inside func1()"

@EntryExit
def func2():
    print "inside func2()"

def func3():
    pass

print type(EntryExit(None))
# func1 变为类实例
print type(func1)
print type(EntryExit)
# func3 是普通函数
print type(func3)
func1()
func2()

# 
# 
# 
# 
# Entering func1
# inside func1()
# Exited func1
# Entering func2
# inside func2()
# Exited func2

类装饰器

@EntryExit
def func1():
    print "inside func1()"

等同于

def func1():
    print "inside func1()"
# 此处可以看出 func1 是类EntryExit的一个实例
func1 = EntryExit(myfunc1)
装饰器装饰类
register_handles = []


def route(url):
    global register_handles

    def register(handler):
        register_handles.append((".*$", [(url, handler)]))
        return handler

    return register

@route("/index")
class Index():
    def get(self, *args, **kwargs):
        print("hi")

# Index 仍然为原来定义的类实例
# 相当于在定义类的同时调用装饰器函数 route, 将该类注册到全局路由 register_handles
@route("/main")
class Main():
    def get(self, *args, **kwargs):
        print("hi")

print (register_handles)

print(type(Index))

# [(".*$", [("/index", )]), (".*$", [("/main", )])]
# 
@route("/index")
class Index():
    def get(self, *args, **kwargs):
        print("hi")
Index = route("/index")(Index)
# register 返回传入的 handler,故 Index 仍然为类对象
functools

上述装饰器实现有个问题,就是被装饰函数的属性被改变

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/42700.html

相关文章

  • python 装饰器 part2

    摘要:装饰器传参被装饰的函数带有参数的情况接上一篇,直接上代码函数也就是被装饰的函数的运行时间是装饰器的正确使用,不需要传参装饰器的正确使用,需要传参此时不用再像上面一样赋值,可以直接调用返回值被装饰的函数有返回值在装饰器内部需被装饰函数的调用 python 装饰器 传参 被装饰的函数带有参数的情况 接上一篇,直接上代码 import time def decorator(func): ...

    sanyang 评论0 收藏0
  • Python函数修饰器---当方法前遇到@参数化的修饰器方法时发生的事

    一、前提概念   Python中的函数是对象。也因此,函数可以被当做变量使用。 二、代码模型 以下代码片段来自于: http://www.sharejs.com/codes/python/8361 # -*- coding: utf-8 -*- from threading import Thread import time class TimeoutEx...

    huashiou 评论0 收藏0
  • Python 装饰器使用指南

    摘要:装饰器是可调用的对象,其参数是另一个函数被装饰的函数。第二大特性是,装饰器在加载模块时立即执行。另一个常见的装饰器是,它的作用是协助构建行为良好的装饰器。 装饰器是可调用的对象,其参数是另一个函数(被装饰的函数)。 装饰器基础知识 首先看一下这段代码 def deco(fn): print I am %s! % fn.__name__ @deco def func(): ...

    NeverSayNever 评论0 收藏0
  • Python装饰器

    摘要:一引用书流畅的书二基本概念问题装饰器是什么解答严格来说,装饰器只是语法糖,装饰器是可调用的对象,可以像常规的可调用对象那样调用,特殊的地方是装饰器的参数是一个函数问题装饰器有什么特性解答装饰器有个特性,一是可以把被装饰的函数替换成其他函数, 一, 引用 [书] 流畅的Python [书] Effective Python 二, 基本概念 showImg(https://segme...

    aisuhua 评论0 收藏0
  • Python知识点:理解和使用装饰器 @decorator

    摘要:使用类装饰器,优点是灵活性大,高内聚,封装性。不过不用担心,有,本身也是一个装饰器,它的作用就是把原函数的元信息拷贝到装饰器函数中,使得装饰器函数也有和原函数一样的元信息。 showImg(https://segmentfault.com/img/bVbrFWb?w=742&h=484);Python的装饰器(decorator)是一个很棒的机制,也是熟练运用Python的必杀技之一。...

    cyqian 评论0 收藏0
  • python装饰器详解

    摘要:为了避免重复调用,可以适当地做缓存,的装饰器可以完美的完成这一任务。这意味着我们可以为方法创建装饰器,只是要记得考虑。装饰器封装了函数,这使得调试函数变得困难。另外,使用装饰器去管理缓存和权限。 原文地址 之前用python简单写了一下斐波那契数列的递归实现(如下),发现运行速度很慢。 def fib_direct(n): assert n > 0, invalid n ...

    maybe_009 评论0 收藏0

发表评论

0条评论

Yangyang

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<