python 看懂利用@修饰符代替swich的原理

来源:互联网 发布:淘宝订单处理中心 编辑:程序博客网 时间:2024/04/24 14:13

在知乎上看到个很神奇的方法可以在python中写出swich的效果:

_registered_actions = {}def action(name):    def decorator(f):        _registered_actions[name] = f        return f    return decorator@action("getInfo")def get_info(data):    ...@action("changeName")def change_name(data):    ...def do_action(action_name, data):    try:        f = _registered_actions[action_name]    except KeyError:        return json.dumps(...)    else:        f(data)        ...作者:灵剑链接:https://www.zhihu.com/question/50498770/answer/121288828来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我自学python还没多久,看的一脸懵逼,不过仔细钻研下,其实不麻烦

这里@修饰符是重点,其次是嵌套函数

首先呢,python没有需要声明函数的前提,所以在你跑起来后,它会自动扫描各个函数,在这个扫描过程中所有的@修饰符都会被执行一次。

根据官方文档:https://www.python.org/dev/peps/pep-0318/

我们可以知道:

@dec2@dec1def func(arg1, arg2, ...):    passThis is equivalent to:def func(arg1, arg2, ...):    passfunc = dec2(dec1(func))
拿知乎代码里的例子变化一下来说就是:

@actiondef get_info(data):    ...相当于action(get_info的函数指针)
修饰符还可以自己带参数:

@decomaker(argA, argB, ...)def func(arg1, arg2, ...):    passThis is equivalent to:func = decomaker(argA, argB, ...)(func)
再拿知乎代码里的例子:

@action("getInfo")def get_info(data):    ...相当于action("getInfo")(get_info的函数指针)
这就是个标准的嵌套函数,其他@修饰符的功能暂时用不上就不提了

我们继续看例子中的action函数

def action(name):    def decorator(f):        _registered_actions[name] = f        return f    return decorator
根据嵌套函数的定义,猜也猜的出来:
action("getInfo")(get_info的函数指针)
第一个括号内是外层函数的参数,第二个是内层函数的。

外层函数需要返回内部函数名,不过内部函数其实不一定需要返回值,return f 这句可以不写

这个函数利用两个参数,在最上面的_registered_actions字典里写入了 诸如:"getInfo":get_info函数指针 这样的内容

利用python自动扫描的特性,所有含@action的函数都会被自动写进字典中。

执行程序比较普通,就是调用字典我就不说了。

就像知乎里说的,这个方法其实就是查字典,不过维护起来很直观,我立马试了试:

import cv2import numpy as npimport PIL.Image as image_blur_actions = {}# @修饰符相当于 action(name)(修饰的函数名)def action(name):    def decorator(func):        _blur_actions[name] = func    # 嵌套函数的外层返回的是内部函数名    return decorator@action("blur")def mean_blur(*args):    return cv2.blur(*args)@action("GaussianBlur")def gaussian_blur(*args):    return cv2.GaussianBlur(*args)# 以列表形式返回图片像素值img = image.open("test.png")img.show()# 打散成 array形式,可以被 opencv直接使用imgMatrix = np.array(img)imgFlited = _blur_actions['GaussianBlur'](imgMatrix, (5, 5), 0)# 重组成 PIL可以使用的形式img2 = image.fromarray(imgFlited)img2.show()cv2.waitKey()cv2.destroyAllWindows()
代码整齐了一些...程序短感觉不出来,长了估计优势就明显了。









原创粉丝点击