gpt4 book ai didi

python - 基于值而不是类型的单一调度

转载 作者:太空狗 更新时间:2023-10-30 02:28:29 24 4
gpt4 key购买 nike

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

最佳答案

有,虽然你必须写。一种可能性是创建一个 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 :

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

请注意,这是一种基于状态的非常邪恶的调度方法,因为对于您代码的 future 读者来说,整个机制将很难理解。

另一种调度文本状态的方法是在方法名称中对状态进行编码,并根据调度函数中的状态选择正确的方法。许多 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 - 基于值而不是类型的单一调度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36836161/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com