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

  • Post author:
  • Post category:python


我在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

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()

来源:http://www.icode9.com/content-1-231851.html



版权声明:本文为weixin_35890512原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。