为每个方法创建具有特定参数的动态 class

Create Dynamic class with specific parameter for each methods

我想在 Class 中创建一个动态方法,但每个方法都有特定的文档字符串和参数。我了解创建动态方法的过程,但我不知道如何创建我的特定参数和我的文档字符串

我这样写:

class Test_Class:
    def __init__(self):
        self.a = 'Test'

def my_new_method(self, a) -> str:
    """
        Something ...

    Args:
        a ([type]): [description]

    Returns:
        str : [description]
    """
    headers = []
    name_params = ''
    return str(a)


for i in ['test_A', 'test_B']:
    setattr(Test_Class, i, my_new_method)

Foo().test_A(54)

我想要这种格式:

class Test_Class:
    def __init__(self):
        self.a = 'Test'
    def test_A(self, a):
        """
            Test A

        Args:
            a ([type]): [description]

        Returns:
            str : [description]
        """
        headers = [1,2,3,4]
        name_params = 'Something'
        return str(a)
    def test_B(self, a):
        """
            Test B

        Args:
            a ([type]): [description]

        Returns:
            str : [description]
        """
        headers = [57,218,78,6]
        name_params = 'Another'
        return str(a)

您可以使用 descriptor protocol:

class MyNewMethod:
    def __init__(self, headers, params):
        self.headers = headers
        self.params = params

    def __set_name__(self, owner, name):
        self.public_name = name  # "test_A, test_B"

    def __get__(self, obj, objtype=None):
        def func(a):
            # a: method parameter
            # obj: instance the method is called on (aka self)
            # self: descriptor instance with access to custom params/headers
            return str(obj.a) + str(a) + str(self.headers) + str(self.params)
        func.__doc__ = "super dynamic stuff using " + self.public_name
        # more mimicking:
        # func.__name__ = self.public_name
        # func.__qualname__ = f"{objtype.__name__}.{self.public_name}"
        return func

class _Base:
    def __init__(self, a):
        self.a = a

现在您可以使用描述符 class 创建带有属性的动态 classes(通过 setattr 附加属性不会调用 __set_name__ 挂钩):

A = type("A", (_Base,), {"test": MyNewMethod(3, 4)})

a = A(1)
a.test(2)
# 1234

help(A.test)
# ...
# test(a)
#     super dynamic stuff using test