ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python – 基于值而不是类型的Singledispatch

2019-06-08 21:44:32  阅读:245  来源: 互联网

标签:python django


我在Django上构建SPA,我有一个巨大的函数,有很多if语句用于检查我的对象字段的状态名称.像这样:

if self.state == 'new':
    do some logic
if self.state == 'archive':
    do some logic

等等.我现在阅读好书“Fluent python”,我提到了@singledispatch装饰器,它看起来很棒,但它只能用不同类型的参数如str,int等覆盖函数.
问题是,如果在python或Django方式中分离逻辑就像在我的庞大函数中使用像singledispatch那样的重叠函数吗?

解决方法:

有,但你必须写它.一种可能性是创建一个基于instance.state或任何选择的state_attr进行调度的descriptor

class StateDispatcher(object):

    def __init__(self, state_attr='state'):
        self.registry = {}
        self._state_attr = state_attr

    def __get__(self, instance, owner):
        if instance is None:
            return self

        method = self.registry[getattr(instance, self._state_attr)]
        return method.__get__(instance, owner)

    def register(self, state):
        def decorator(method):
            self.registry[state] = method
            return method

        return decorator

https://docs.python.org/3/howto/descriptor.html#functions-and-methods

To support method calls, functions include the __get__() method for binding methods during attribute access. This means that all functions are non-data descriptors which return bound or unbound methods depending whether they are invoked from an object or a class.

在您的有状态类中,您可以创建一个调度程序并注册方法:

class StateMachine(object):

    dispatcher = StateDispatcher()
    state = None

    @dispatcher.register('test')
    def test(self):
        print('Hello, World!', self.state)

    @dispatcher.register('working')
    def do_work(self):
        print('Working hard, or hardly working?', self.state)

让我们看看它的实际效果:

>>> sm = StateMachine()
>>> sm.state = 'test'
>>> sm.dispatcher()
Hello, World! test
>>> sm.state = 'working'
>>> sm.dispatcher()
Working hard, or hardly working? working
>>> sm.state = None
>>> sm.dispatcher()
Traceback (most recent call last):
  ...
  File "dispatcher.py", line 11, in __get__
    method = self.registry[getattr(instance, self._state_attr)]
KeyError: None

请注意,这是一种基于状态调度的非常恶劣的方法,因为对于未来的代码读者来说,整个机制将很难遵循.

另一种调度文本状态的方法是对方法名称中的状态进行编码,并在调度函数中根据该方法选择正确的方法.许多python类使用此模式(例如ast.NodeVisitor):

class StateMachine(object):

    def dispatch(self, *args, **kwgs):
        getattr(self, 'do_{}'.format(self.state))(*args, **kwgs)

    def do_new(self):
        print('new')

    def do_archive(self):
        print('archive')


sm = StateMachine()
sm.state = 'new'
sm.dispatch()
sm.state = 'archive'
sm.dispatch()

标签:python,django
来源: https://codeday.me/bug/20190608/1200588.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有