如何动态更改子类中方法的签名? [英] How to dynamically change signatures of method in subclass?

查看:96
本文介绍了如何动态更改子类中方法的签名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 classmethod 动态更改子类中的方法时,如何动态更改方法的签名?

When using classmethod to dynamic change the method in subclass, how to dynamic change signatures of method?

示例

import inspect

class ModelBase(object):

    @classmethod
    def method_one(cls, *args):
        raise NotImplementedError

    @classmethod
    def method_two(cls, *args):
        return cls.method_one(*args) + 1

class SubClass(ModelBase):
    @staticmethod
    def method_one(a, b):
        return a + b

test = SubClass()

try:
    print(inspect.signature(test.method_two))
except AttributeError:
    print(inspect.getargspec(test.method_two).args)

我要 test.method_two 获取 test.method_one 的签名。如何重写父类 ModelBase

I want test.method_two to get the signatures of test.method_one. How to rewrite parent class ModelBase?

我已阅读有关保留装饰功能的签名。在python3.4 +中, functools.wraps 有助于保留修饰函数的签名。我想将其应用于类方法。

I have read about Preserving signatures of decorated functions. In python3.4 +, functools.wraps helps to preserve signatures of decorated functions. I want to apply it to class method.

当使用 functools.wraps 时,我需要分配装饰方法的名称。但是在这种情况下,如何在 classmethod 之外访问修饰方法?

when uses functools.wraps, I need to assign decorated method's name. But how to access decorated method outside classmethod in this situation?

from functools import wraps

class ModelBase(object):

    @classmethod
    def method_one(cls, *args):
        raise NotImplementedError

    @classmethod
    def method_two(cls):
        @wraps(cls.method_one)
        def fun(*args):
            return cls.method_one(*args) + 1
        return fun

method_two 返回包装的函数,但我必须将其与 test.method_two()(* arg)一起使用。这种方法不是直接的。

method_two returns a wrapped function, but I must use it with test.method_two()(*arg). This method is not directly.

推荐答案

如果这只是出于自省目的,则可以覆盖 __ getattribute __ ModelBase 上的code>,每次访问 method_two 时,我们返回一个具有<$签名的函数c $ c> method_one 。

If this is only for introspection purpose you could override __getattribute__ on ModelBase and every time method_two is accessed we return a function that has the signature of method_one.

import inspect

def copy_signature(frm, to):
    def wrapper(*args, **kwargs):
        return to(*args, **kwargs)
    wrapper.__signature__ = inspect.signature(frm)
    return wrapper


class ModelBase(object):

    @classmethod
    def method_one(cls, *args):
        raise NotImplementedError

    @classmethod
    def method_two(cls, *args):
        return cls.method_one(*args) + 1

    def __getattribute__(self, attr):
        value = object.__getattribute__(self, attr)
        if attr == 'method_two':
            value = copy_signature(frm=self.method_one, to=value)
        return value


class SubClass(ModelBase):
    @staticmethod
    def method_one(a, b):
        return a + b


class SubClass2(ModelBase):
    @staticmethod
    def method_one(a, b, c, *arg):
        return a + b

演示:

>>> test1 = SubClass()
>>> print(inspect.signature(test1.method_two))
(a, b)
>>> test2 = SubClass2()
>>> print(inspect.signature(test2.method_two))
(a, b, c, *arg)

这篇关于如何动态更改子类中方法的签名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆