写一个命令分发器
- 程序员可以方便的注册函数到某一个命令,用户输入命令时,路由到注册的函数
- 如果此命令没有对应的注册函数,执行默认函数
- 用户输入用input(">>")
分析
- 输入命令映射到一个函数,并执行这个函数。应该是cmd_tbl[cmd] = fn的形式,字典正好合适
- 如果输入了某一个cmd命令后,没有找到函数,就要调用缺省的函数执行,这正好是字典缺省参数
- cmd是字符串
# 构建全局字典
cmd_table = {}
# 注册函数
def reg(cmd, fn):
cmd_table[cmd] = fn
# 缺省函数
def default_func():
print('Unknown command')
# 分发器,调度
def dispatcher():
while True:
cmd = input(">>")
# 退出条件
if cmd.strip() == '':
return
cmd_table.get(cmd, default_func)() # get,当cmd不存在时,使用缺省值defaul_func
# 自定义函数
def foo1():
print('hello')
def foo2():
print('python')
# 注册
reg('hi', foo1)
reg('py', foo2)
# 循环
dispatcher()
- 分析:
- 代码函数的注册不好看
- 所有的函数和字典都在全局中定义,不好
- 改进办法
封装
- 将reg函数封装成装饰器,并用它来注册函数
def command_dispatcher():
# 构建全局字典
cmd_table = {}
# 注册函数
def reg(cmd):
def _reg(fn):
cmd_table[cmd] = fn
return fn
return _reg
# 缺省函数
def default_func():
print('Unknown command')
# 分发器,调度
def dispatcher():
while True:
cmd = input(">>")
# 退出条件
if cmd.strip() == '':
return
cmd_table.get(cmd, default_func)()
# get,当cmd不存在时,使用缺省值defaul_func
return reg,dispatcher # 把两个函数标识符(分别对应函数)封装到元组中
reg, dispatcher = command_dispatcher() # 将两个函数解构
# 自定义函数
@reg('hi')
def foo1():
print('hello')
@reg('py')
def foo2():
print('python')
# 循环
dispatcher()
完善命令分发器
- 完善命令分发器,实现函数可以带任意参数(可变参数除外),解析参数并要求用户输入
- 即解决下面的问题
# 自定义函数
@reg('hi')
def foo1(x,y):
print('hello', x, y)
@reg('py')
def foo2(a,=100):
print('python', a, b)
思路
- 可以有2中方式
- 注册的时候,固定死,@reg(‘py’,200,100)
可以认为@reg(‘py’,200,100)和@reg(‘py’,300,100)是不同的函数,可以用partial函数 - 运行时,在输入cmd的时候,逗号或空格分割,获取参数
- 一般用户都喜欢使用单纯一个命令如hi,然后直接显示想要的结构,就采用方式一实现
方式一实现
# 自定义函数可以有任意参数,可变参数、keyword-only除外
def command_dispatcher():
# 构建全局字典
cmd_tbl = {}
# 注册函数
def reg(cmd, *args, **kwargs):
def _reg(fn):
cmd_tbl[cmd] = fn, args, kwargs
return fn
return _reg
# 缺省函数
def default_func():
print('Uknown command')
# 调度器
def dispatcher():
while True:
cmd = input('please input cmd>>')
# 退出条件
if cmd.strip() == '':
return
fn, args, kwargs = cmd_tbl.get(cmd, (default_func, (), {}))
# get,当cmd不存在时,使用缺省值(defaul_func, (), {}) ,并将其解构,fn对应default_func...
fn(*args,**kwargs) # 调用cmd[0]或default_func函数
return reg,dispatcher
reg, dispatcher = command_dispatcher()
# 自定义函数
@reg('hi', z=200, y=300, x=100)
@reg('hi1', z=300, y=300, x=300)
@reg('hi2', 1, 2, 3)
def foo1(x, y, z):
print('hello',x, y, z)
@reg('py', 300, b=400)
def foo2(a, b=100):
print('python', a, b)
# 调度循环
dispatcher()
```python
## 方法二实现
自定义函数可以有任意参数,可变参数、keyword-only除外
def command_dispatcher():
# 构建全局字典
commands = {}
# 注册函数
def reg(cmd):
def _reg(fn):
commands[cmd] = fn
return fn
return _reg
# 缺省函数
def default_fn(*args,**kwargs):
print('Uknown command')
# 调度器
def dispatcher():
while True:
cmd = input('>>')
# 退出条件
if cmd.strip() == '':
break
else:
fname, *params = cmd.replace(',', ' ').split() #list
#print(params) # ['1', 'y=5']
args = []
kwargs = {}
for param in params:
x = param.split('=', maxsplit=1) # 按'='切,最大切一刀
if len(x) == 1: # 顺序传参
args.append(int(x[0]))
elif len(x) == 2: # a=1 [a,1]
kwargs[x[0]] = int(x[1])
#print(args, kwargs)
commands.get(fname, default_fn)(*args, **kwargs)
return reg, dispatcher
reg, dispatcher = command_dispatcher()
# 自定义函数
@reg('hi')
def foo1(x, y):
print('hello', x, y, x+y)
@reg('py')
def foo2(a, b=100):
print('python', a, b, a+b)
# 调度循环
dispatcher()
# >> py 200 300
# >> py 200
# >> py 200,y=200