在知乎上看到个很神奇的方法可以在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
@dec1
def func(arg1, arg2, ...):
pass
This is equivalent to:
def func(arg1, arg2, ...):
pass
func = dec2(dec1(func))
拿知乎代码里的例子变化一下来说就是:
@action
def get_info(data):
...
相当于
action(get_info的函数指针)
修饰符还可以自己带参数:
@decomaker(argA, argB, ...)
def func(arg1, arg2, ...):
pass
This 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 cv2
import numpy as np
import 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()
代码整齐了一些...程序短感觉不出来,长了估计优势就明显了。