Python 异常处理

发布时间:2019-07-14 10:04:39编辑:auto阅读(1562)

    写一个命令分发器
    初步要求 :

    程序员可以方便地注册函数到某一个命令, 用户输入命令时, 路由到注册的函数, 如果此命令没有对应的函数, 执行默认函数
    分析 :

    输入命令映射到一个函数, 并执行这个函数, 应该是cmd_tbl[cmd] = fn 的形式, 使用字典比较合适
    如果输入某一cmd 命令后, 没有找到函数就调用缺省的函数执行, 正好是字典的缺省参数, cmd 是字符串
    基础框架 :

    构建全局字典

    cmd_table = {}

    注册函数

    def reg(cmd, fn):
    cmd_table[cmd] = fn

    缺省函数

    def default_fun():
    print('Unknow command')

    分发器调度

    def dispatcher():
    while True:
    cmd =input('>>')

    退出条件

        if cmd.strip() == '':   
            return 
        cmd_table.get(cmd, default_fun)()

    自定义函数

    def foo1():
    print('text')
    def foo2():
    print('python')

    注册

    reg('x', foo1)
    reg('pyt', foo2)

    循环

    dispatcher()
    存在问题 :

    函数注册太难看
    函数和字典都在全局定义
    如何在此基础上改进…

    封装
    将reg函数封装成装饰器, 并用它来注册函数

    注册函数

    def reg(cmd):
    def _reg(fn):
    cmd_table[cmd] = fn
    return fn
    return _reg

    自定义函数

    @reg('x')
    def foo1():
    print('text') br/>@reg('pyt')
    def foo2():
    print('python')
    能否把字典, reg, dispatcher等也封装起来呢, 外面在使用的时候调度就可以了

    def command_dispatcher():

    构建全局字典

    cmd_table = {}
    
    # 注册函数
    def reg(cmd):
        def _reg(fn):
            cmd_table[cmd] = fn
            return fn
        return _reg
    
    # 缺省函数
    def default_func():
        print('Unknow command')
    
    # 分发器, 调度
    def dispatcher():
        while True:
            cmd = input('>>')
            # 退出条件
            if cmd.strip() == '':
                return 
            cmd_table.get(cmd, default_func)()
    return reg, dispatcher
    # 返回内层函数, 解构后外部调用

    reg, dispatcher = command_dispatcher()

    自定义函数

    @reg('x')
    def foo1():br/>print('text')
    @reg('pyt')
    def foo2():
    print('python')

    循环

    dispatcher()
    输出结果 :

    abcdef
    Unknow command
    x
    text
    pyt
    python

    符合设计预期 : 输入的cmd不存在的调用缺省函数, cmd存在则调用相应函数, 输入空格则退出
    问题
    重复注册

    如果一个函数使用同样的cmd名注册, 就等于覆盖原有cmd到fn之间的关系, 这样的判断也是合理的, 不过也可以加一个判断, 如果key 已存在, 重复注册抛出异常, 具体情况具体分析
    注销

    有注册就应该有注销, 从字典中移除.
    一般来说注销是有条件的, 什么人拥有注销权限看业务需求
    完善命令分发器
    实现函数可以带任意参数(可变参数除外), 解析参数并要求用户输入
    即实现下面的问题 :

    自定义函数

    @reg('x')
    def foo1(x, y):
    print('text', x, y)br/>@reg('pyt')
    def foo2(a, b=100):
    print('python', a, b)
    基本思路 :

    可以有以下两种方式 :
    注册的时候固定死, @reg(‘pyt’, 200, 100), 可以认为@reg(‘pyt’, 200, 100) 和 @reg(‘pyt’, 300, 100) 是不同的函数, 可以用partial 函数
    运行时,在输入cmd 的时候, 逗号或者空格分割, 获取参数, 函数验证功能在后面实现
    一般用户都喜欢使用单纯一个命令如 pyt, 然后直接显示想要的结果,采用方式一实现

    自定义函数可以是任意参数(可变参数, 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(*args, **kwargs):
        print('Unknow command')
    
    # 调度器
    def dispatcher():
        while True:
            cmd = input('Please input cmd >>')
    
            # 退出条件
            if cmd.strip() == '':
                return
    
            fn, args, kwargs = cmd_tbl.get(cmd, (default_func, (), {}))
            fn(*args, kwargs)
    return reg, dispatcher

    reg, dispatcher = command_dispatcher()

    自定义函数

    @reg('x1', z=200, y=300, x=100)
    @reg('x2', z=300, y=300, x=300)
    @reg('x3', 1, 2, 3)
    def foo1(x, y, z):
    print('text', x, y, z)

    调度循环

    dispatcher()
    输出结果 :

    Please input cmd >> x1
    text 100 300 200
    Please input cmd >> x2
    text 300 300 300
    Please input cmd >> x3
    text 1 2 3
    Please input cmd >>
    方法二 :

    def command_dispatcher():
    command = {}
    def reg(cmd):
    def _reg(fn):
    command[cmd] = fn
    return fn
    return _reg
    def default_fn(*args, kwargs):
    print('Unknow command')
    def dispatcher():
    while True:
    cmd = input('Please input cmd >>')
    if cmd.strip() == '':
    break
    else:
    fname, params = cmd.replace(',', ' ').split()
    args = []
    kwargs = {}
    for param in params:
    lis_param = param.split('=', maxsplit=1)
    if len(lis_param) == 1:
    args.append(lis_param[0])
    elif len(lis_param) == 2:
    kwargs[lis_param[0]] = lis_param[1]
    command.get(fname, default_fn)(
    args,
    kwargs)
    return reg, dispatcher
    reg, dispatcher = command_dispatcher()

    @reg('x')
    def foo1(x, y):
    print('text', x, y)

    @reg('pyt')
    def foo2(a, b=100):
    print('python', a, b)

    dispatcher()

    输出结果 :

    Please input cmd >> x 1 2
    text 1 2
    Please input cmd >> x x=1,y=4
    text 1 4
    Please input cmd >> pyt 5
    python 5 100
    Please input cmd >> pyt 4 8
    python 4 8


关键字

上一篇: Python File(文件)方法

下一篇: python面试题