Singledispatch based on value instead of type

I am creating a SPA on Django, and I have one huge function with many operators ifto check the state of the name of my object field. Like this:

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

etc. Now I am reading the good book "Free Python", and I mention the decorator @singledispatch, it looks so great, but it can only redefine a function with various type parameters str, intetc.
The question is, is there a way in python or Django to separate the logic like in my huge function using a function like singledispatchdo?

+4
source share
1 answer

, . descriptor, instance.state state_attr:

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:

__get__() . , - , , .

stateful :

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

All Articles