python修饰器的特殊用法

最基本的修饰器包括了无参数的修饰器和带参数的修饰器,这两种修饰器都是针对函数的,讲解的博客已经很多了,就不再赘述了,这里重点讲下修饰器的几种特殊用法。

使用类创建修饰器

因为类也是可以callable的,只要实现__call__魔法函数即可,所以类也可以实现修饰器效果。

import functools

class Debug(object):
    def __init__(self, function):
        self.function = function
        functools.update_wrapper(self, function)

    def __call__(self, *args, **kwargs):
        output = self.function(*args, **kwargs)
        print('%s(%r, %r): %r' % (self.function.__name__, args, kwargs, output))
        return output

@Debug
def spam(eggs):
    return "spam" * (eggs%5)

spam(3)

结果如下所示:

spam((3,), {}): 'spamspamspam'

使用类创建修饰器和使用函数创建修饰器的区别是,后者使用 functools.wraps,前者使用 functools.update_wrapper

修饰类的方法

修饰类的方法与修饰函数形式差不多,唯一需要注意的是类方法中必须提供第一个变量self

import functools

def plus_one(function):
    @functools.wraps(function)
    def _plus_one(self, n):
        return function(self, n+1)
    return _plus_one

class Spam(object):
    @plus_one
    def get_eggs(self, n):
        return n*"eggs"

spam = Spam()
print(spam.get_eggs(2))

结果如下所示:

eggseggseggs

classmethodstaticmethodproperty描述器本质上都是类方法修饰器。classmethodstaticmethod的区别是classmethod只需要传递类对象,staticmethod既不用传递类对象也不用传递类的实例。

首先看下classmethodstaticmethod的用法

import pprint

class Spam(object):
    def some_instancemethod(self, *args, **kwargs):
        print("self: %r" % self)
        print("args: %s" % pprint.pformat(args))
        print("kwargs: %s" % pprint.pformat(kwargs))

    @classmethod
    def some_classmethod(cls, *args, **kwargs):
        print("cls: %r" % cls)
        print("args: %s" % pprint.pformat(args))
        print("kwargs: %s" % pprint.pformat(kwargs))

    @staticmethod
    def some_staticmethod(*args, **kwargs):
        print("args: %s" % pprint.pformat(args))
        print("kwargs: %s" % pprint.pformat(kwargs))


spam = Spam()
spam.some_instancemethod(1,2, a=3, b=4)
Spam.some_classmethod()
spam.some_classmethod()
Spam.some_classmethod(1,2, a=3,b=4)
Spam.some_staticmethod()
Spam.some_staticmethod(1,2,a=3,b=4)

结果如下所示:

self: <__main__.Spam object at 0x000001AF5FF335F8>
args: (1, 2)
kwargs: {'a': 3, 'b': 4}
cls: <class '__main__.Spam'>
args: ()
kwargs: {}
cls: <class '__main__.Spam'>
args: ()
kwargs: {}
cls: <class '__main__.Spam'>
args: (1, 2)
kwargs: {'a': 3, 'b': 4}
args: ()
kwargs: {}
args: (1, 2)
kwargs: {'a': 3, 'b': 4}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小灰灰

JDK容器学习之Queue: ArrayDeque

数组双端队列 ArrayDeque 双端队列,表示可以添加元素到(或删除,获取)队列头也可以添加元素到(或删除,获取)队列尾 ? 1. 底层数据结构 类中定义成...

1956
来自专栏移动开发面面观

快速排序法及优化

1584
来自专栏静默虚空的博客

[Java IO]06_JSON操作

6.1 JSON 知识背景 6.1.1 JSON 简介 JSON: JavaScript Object Notation(JavaScript 对象表示法) J...

2178
来自专栏绿巨人专栏

[Java] 设计模式: Code Shape - 管理你的代码结构

4216
来自专栏绿巨人专栏

[Java] 设计模式: Code Shape - 管理你的代码结构

912
来自专栏DannyHoo的专栏

OC中内存管理的一些问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010105969/article/details/...

1313
来自专栏kalifaの日々

快速排序(quick sort)C++实现

每次选一个轴pivot(我选数组的第一个元素arr[p]),遍历其余数组元素使得比arr[p]大的数都在arr[p]的右边,比arr[p]小的数都在arr[p]...

3144
来自专栏前端新视界

常用的 JS 排序算法整理

关于排序算法的问题可以在网上搜到一大堆,但是纯 JS 版比较零散,之前面试的时候特意整理了一遍,附带排序效率比较。 //1.冒泡排序 var bubbleSo...

2319
来自专栏老九学堂

十七个C语言新手编程时常犯的错误及解决方式

编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。

1554
来自专栏闵开慧

java概念1

public static void main(String[] args) {//其中[]也可以写在args后面,args也可以随便写成其他字母,例如asd...

35111

扫码关注云+社区

领取腾讯云代金券