0

假设我想为名为“MacroMethods”的模块中的每个类设置函数。所以我在'Fluent Python'中看到它后设置了singledispatch,如下所示:

@singledispatch
def addMethod(self, obj):
    print(f'Wrong Object {str(obj)} supplied.')
    return obj

...

@addMethod.register(MacroMethods.Wait)
def _(self, obj):
    print('adding object wait')
    obj.delay = self.waitSpin.value
    obj.onFail = None
    obj.onSuccess = None
    return obj

期望的行为是 - 当类 'MacroMethods.Wait' 的实例作为参数给出时,singledispatch 运行具有该类类型的注册函数。

相反,它运行默认功能而不是注册功能。

>>> Wrong Object <MacroMethods.Wait object at 0x0936D1A8> supplied.

但是, type() 清楚地显示实例是类“MacroMethods.Wait”,并且 dict_keys 属性也包含它。

>>> dict_keys([<class 'object'>, ..., <class 'MacroMethods.Wait'>])

我怀疑我制作的所有自定义类都算作“对象”类型,并且没有在结果中运行所需的函数。

有什么办法可以解决这个问题?完整的代码在这里


更新

我设法模仿singledispatch的动作如下:

from functools import wraps


def state_deco(func_main):
    """
    Decorator that mimics singledispatch for ease of interaction expansions.
    """

    # assuming no args are needed for interaction functions.
    func_main.dispatch_list = {}  # collect decorated functions

    @wraps(func_main)
    def wrapper(target):
        # dispatch target to destination interaction function.
        nonlocal func_main
        try:
            # find and run callable for target
            return func_main.dispatch_list[type(target)]()
        except KeyError:
            # If no matching case found, main decorated function will run instead.
            func_main()

    def register(target):
        # A decorator that register decorated function to main decorated function.
        def decorate(func_sub):
            nonlocal func_main
            func_main.dispatch_list[target] = func_sub

            def register_wrapper(*args, **kwargs):
                return func_sub(*args, **kwargs)

            return register_wrapper
        return decorate

    wrapper.register = register
    return wrapper

像这样使用:

@state_deco
def general():
    return "A's reaction to undefined others."

@general.register(StateA)
def _():
    return "A's reaction of another A"

@general.register(StateB)
def _():
    return "A's reaction of B"

但仍然不是singledispatch,所以我发现将其发布为答案可能不合适。

4

1 回答 1

1

我想做类似的事情并且遇到了同样的麻烦。看起来我们遇到了一个 python 错误。找到了描述这种情况的文章。这是 Python Bug Tracker 的链接。

Python 3.7 中断了 Python 3.6 接受的 singledispatch_function.register(pseudo_type)

于 2020-09-01T20:05:30.377 回答