首页 > 解决方案 > 如何为修饰以更改函数返回的函数键入提示返回值?

问题描述

我正在编写一个 Python 包,它使用装饰器删除样板代码,同时自省函数以默认获取函数名称。类似于以下内容:

def make_real_instance(func: Optional[Callable] = None,
                       *, func_name: Optional[str] = None):
    def make_wrapper(in_func):
        @functools.wraps(in_func)
        def wrapper(*args, **kwargs):
            nonlocal func_name
            # Use func_name if provided
            func_name = func_name or in_func.__name__
            # Construct params for new object from function and its inputs
            stuff = in_func(*args, **kwargs)
            # Process stuff commonly
            new_object = ObjectConstructor(processed_stuff, func_name)
            return new_object
        return wrapper

    if func:
        return make_wrapper(func)
    return make_wrapper

现在,我有这样的课程:

class ObjectConstructor:
    def __init__(self, ...):
        #do stuff

    @make_real_instance
    def add_foo(self, foo_length: float):
        stuff = ... # process the input for this method
        return stuff

@make_real_instance装饰器导致调用add_foo实例的方法以ObjectConstructor返回一个实例。但是,未修饰方法的实际返回类型是元组。

我想做的是注释方法以键入提示返回作为ObjectConstructor. 即,该行:

        def add_foo(self, foo_length: float):

将变为(annotations从导入__future__):

        def add_foo(self, foo_length: float): -> ObjectConstructor

但是,我的 IDE(PyCharm,虽然在这种情况下我不一定认为这是材料)抱怨(我想是公平的)此方法的输出与提示的返回类型不匹配。

最后,我的问题是:有没有一种方法可以正确键入提示您修改使用装饰器的输出的函数调用的返回类型?还是我唯一的办法是将我的装饰器更改为我在我装饰的每个函数中调用的函数,并且func_name每次都显式传递我的参数?我的意思是:

def make_obj_from_stuff(stuff, func_name) -> ObjectConstructor:
    # process stuff commonly
    new_object = new_object = ObjectConstructor(processed_stuff, func_name)
    return new_object

class ObjectConstructor:
    def __init__(self, ...):
        #do stuff

    def add_foo(self, foo_length: float) -> ObjectConstructor:
        stuff = ... # process the input
        new_obj = make_obj_from_stuff(stuff, "add_foo")
        return new_obj

如果我想维护我创建的装饰器界面,我是否只需要接受我将无法正确键入提示而不让我的 IDE 抱怨?

标签: pythonpython-3.xpycharm

解决方案


推荐阅读