资讯专栏INFORMATION COLUMN

Python Switch Case 最佳实践

sorra / 1185人阅读

摘要:事实上,凡是能通过逻辑语句来选择的事物,都可以通过查表来选择。对简单的情况而言,使用逻辑语句更为容易和直白。但随着逻辑链的越来越复杂,查表法也就愈发显得更具吸引力。

优美胜于丑陋
import this
博客地址:Specific-Dispatch
前言

表驱动法是一种编辑模式(Scheme)——从表里面查找信息而不使用逻辑语句(ifcase)。事实上,凡是能通过逻辑语句来选择的事物,都可以通过查表来选择。

对简单的情况而言,使用逻辑语句更为容易和直白。但随着逻辑链的越来越复杂,查表法也就愈发显得更具吸引力。

Python的switch case

由于Python中没有switch case关键词,所以对于每一种情况的逻辑语句只能用if,elif,else来实现,显得很不Pythonic.

def handle_case(case):
    if case == 1:
        print("case 1")
    elif case == 2:
        print("case 2")
    else:
        print("default case")

而受到PEP-443: Single-dispatch generic functions的启发,很容易就能实现如下装饰器:

from functools import update_wrapper
from types import MappingProxyType
from typing import Hashable, Callable, Union


def specificdispatch(key: Union[int, str] = 0) -> Callable:
    """specific-dispatch generic function decorator.

    Transforms a function into a generic function, which can have different
    behaviours depending upon the value of its key of arguments or key of keyword arguments.
    The decorated function acts as the default implementation, and additional
    implementations can be registered using the register() attribute of the
    generic function.
    """

    def decorate(func: Callable) -> Callable:
        registry = {}

        def dispatch(key: Hashable) -> Callable:
            """
            Runs the dispatch algorithm to return the best available implementation
            for the given *key* registered on *generic_func*.
            """
            try:
                impl = registry[key]
            except KeyError:
                impl = registry[object]
            return impl

        def register(key: Hashable, func: Callable=None) -> Callable:
            """
            Registers a new implementation for the given *key* on a *generic_func*.
            """
            if func is None:
                return lambda f: register(key, f)

            registry[key] = func
            return func

        def wrapper_index(*args, **kw):
            return dispatch(args[key])(*args, **kw)

        def wrapper_keyword(*args, **kw):
            return dispatch(kw[key])(*args, **kw)

        registry[object] = func
        if isinstance(key, int):
            wrapper = wrapper_index
        elif isinstance(key, str):
            wrapper = wrapper_keyword
        else:
            raise KeyError("The key must be int or str")
        wrapper.register = register
        wrapper.dispatch = dispatch
        wrapper.registry = MappingProxyType(registry)
        update_wrapper(wrapper, func)

        return wrapper

    return decorate

而之前的代码就能很优美的重构成这样:

@specificdispatch(key=0)
def handle_case(case):
    print("default case")

@handle_case.register(1)
def _(case):
    print("case 1")

@handle_case.register(2)
def _(case):
    print("case 2")

handle_case(1) # case 1
handle_case(0) # default case

而对于这样的架构,即易于扩展也利于维护。

更多实例
class Test:
    @specificdispatch(key=1)
    def test_dispatch(self, message, *args, **kw):
        print(f"default: {message} args:{args} kw:{kw}")

    @test_dispatch.register("test")
    def _(self, message, *args, **kw):
        print(f"test: {message} args:{args} kw:{kw}")

test = Test()
# default: default args:(1,) kw:{"test": True}
test.test_dispatch("default", 1, test=True)
# test: test args:(1,) kw:{"test": True}
test.test_dispatch("test", 1, test=True)

@specificdispatch(key="case")
def handle_case(case):
    print("default case")

@handle_case.register(1)
def _(case):
    print("case 1")

@handle_case.register(2)
def _(case):
    print("case 2")

handle_case(case=1)  # case 1
handle_case(case=0)  # default case

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44771.html

相关文章

  • 45 个实用的 JavaScript 技巧、窍门和最佳实践

    摘要:使用闭包实现私有变量译者添加未在构造函数中初始化的属性在语句结尾处使用分号在语句结尾处使用分号是一个很好的实践。总结我知道还有很多其他的技巧,窍门和最佳实践,所以如果你有其他想要添加或者对我分享的这些有反馈或者纠正,请在评论中指出。 showImg(http://segmentfault.com/img/bVbJnR); 如你所知,JavaScript是世界上第一的编程语言(编者注:2...

    魏宪会 评论0 收藏0
  • 最佳实践

    摘要:什么是重构字面上的理解重新组织结构为什么要重构原来的结构是什么样子的有什么问题函数逻辑结构条件判断循环操作包含关系集合关系非关系可扩展性差新的变化不能被灵活处理对象强耦合可复用性差重复代码多性能消耗太多随着技术发展新的好特性如何重构知道问题 什么是重构? 字面上的理解: 重新组织结构 为什么要重构? 原来的结构是什么样子的?有什么问题? 1. 函数逻辑结构[条件判断、循环操作]: 包...

    iamyoung001 评论0 收藏0
  • 45个实用的JavaScript小贴士、小技巧和最佳实践

    摘要:翻译正文第一次声明变量时,请不要忘记使用关键字声明使用代替空字符串转成布尔值都为每行代码的末尾最好都加上个分号最好给对象都添加上构造函数在使用和尽量小心。 翻译介绍 翻译标题:45 Useful JavaScript Tips, Tricks and Best Practices 翻译来源:http://modernweb.com/2013/12/23/45-useful-java...

    Moxmi 评论0 收藏0
  • 单页应用SPA开发最佳实践

    摘要:最近用做了个单页应用的项目,页面大概有个左右。详见链接使用自定义事件的表单输入组件优雅解决的问题的问题由来已久,在单页应用中我们免不了需要处理这样的。 最近用vue+vue-router做了个单页应用的项目,页面大概有15个左右。积累了一些开发经验在此做一些记录.本文主要从可维护性方面来考虑SPA的开发实践 全站的颜色定义放在一个less或者scss的文件里,其他组件和页面import...

    mingzhong 评论0 收藏0
  • 单页应用SPA开发最佳实践

    摘要:最近用做了个单页应用的项目,页面大概有个左右。详见链接使用自定义事件的表单输入组件优雅解决的问题的问题由来已久,在单页应用中我们免不了需要处理这样的。 最近用vue+vue-router做了个单页应用的项目,页面大概有15个左右。积累了一些开发经验在此做一些记录.本文主要从可维护性方面来考虑SPA的开发实践 全站的颜色定义放在一个less或者scss的文件里,其他组件和页面import...

    不知名网友 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<