创建一个继承自函数创建的类的python类

Posted

技术标签:

【中文标题】创建一个继承自函数创建的类的python类【英文标题】:Create a python Class inheriting from a Class created by a function 【发布时间】:2021-08-23 07:50:54 【问题描述】:

什么有效:

我正在使用模块recordtype 来为我的程序的不同功能存储全局参数。

每个参数都是一个类实例:

class Parameter(object):

    def __init__(self, name, value, info):
        self.name = name
        self.value = value
        self.info = info

那么全局结构是这样定义的:

各个参数:

parameter_1 = Parameter('param_1', 10, 'Value for the parameter 1, usage...')
parameter_2 = Parameter('param_2', 20, 'Value for the parameter 2, usage...')
...
parameter_m = Parameter('param_n', 50, 'Value for the parameter m, usage...')
parameter_n = Parameter('param_n', 100, 'Value for the parameter n, usage...')

参数子集:

parameter_set_1 = recordtype('parameter_set_1', [(parameter_1.name, parameter_1), 
(parameter_2.name, parameter_2), ...])
...
parameter_set_n = recordtype('parameter_set_n', [(parameter_m.name, parameter_m), 
(parameter_n.name, parameter_n)]

那么全局参数结构是:

GlobalParametersFunction = recordtype('GlobalParameters', [('parameter_set_1', parameter_set_1()), 
('parameter_set_2', parameter_set_2()), ('parameter_set_n', parameter_set_n())])

需要实例化:

GlobalParameters = GlobalParameterFunction()

这一切都很好,GlobalParameterFunction 创建了一个类,我可以在其中访问各个参数并更改它们的值,例如:

GlobalParameters.parameter_set_1.parameter_1.value = 20

然后我可以从GlobalParameters 类实例创建一个打印值及其名称的函数:

def print_parameter_info(GP):
    for field, val in zip(GP._asdict(), GP._asdict().values()):
        print(field, ':')
        for key, entry in zip(val._asdict(), val._asdict().values()):
            print('\t', entry.name, ':', entry.value)

这对用户有好处:

>>> print_parameter_info(GlobalParameters)

parameter_set_1 :
     parameter_1 : 10
     parameter_2 : 20
parameter_set_n :
     parameter_m : 50
     parameter_n : 100

我还想创建一个这样的函数:

change(GlobalParameters, 'name', new_value)

做:

GlobalParameters.parameter_set_1.name.value = new_value

这对于recordtype创建的类似乎很容易实现

问题:

我想从print_parameter_info() 函数为GlobalParameters 类实例创建一个类方法,这样:

GlobalParameters.print_parameter_info()

GlobalParameters.change(name, new_value)

作品

因为GlobalParametersrecordtype的类实例,所以我试过了:

class GlobalParameterClass(recordtype):
    
    def __init__(self):
        self = GlobalParameterFunction()

但是因为recordtype 是一个创建类的函数? 我收到以下错误:

TypeError: function() argument 'code' must be code, not str

我找到了这个question (2231427)

但是在尝试导入正确的东西并查看recordtype的源代码后,我想我明白recordtype没有明确定义class并通过解析一串代码来创建它?

因此我不明白如何创建一个继承自recordtype创建的类的类

我也试过

class GlobalParameterClass(object):

    def __init__(self, *args):
        self = GlobalParameterFunction(*args)

这不会引发任何错误,但创建的类实例是空的。

TLDR/结论

如何向recordtype 模块中的recordtype 函数创建的类添加自定义方法?

或者

或许有更好的方法来管理 GlobalParameters 对象?

谢谢!

【问题讨论】:

【参考方案1】:

通过创建具有所需行为的自定义类,我找到了一个不使用 recordtype 对象的解决方案:

class Parameter(object):
    """
    A class to store the individual sound parameters
    """
    def __init__(self, name, value, info):
        self.name = name
        self.value = value
        self.info = info

class ParameterSet(object):
    """
    A class to store multiple parameters as a set
    """
    def __init__(self, name, *parameters):
        self.name = name
        for parameter in parameters:
            setattr(self, parameter.name, parameter)

class GlobalParameters(object):
    """
    A class to store the parameter sets and to be used to assign parameter values to the different functions
    """
    def __init__(self, *parameter_sets):
        for parameter_set in parameter_sets:
            setattr(self, parameter_set.name, parameter_set)

GlobalParameters 类的方法如下:

    def info(self):
        for parameter_set in self.__dict__.values():
            print(parameter_set.name)
            parameters = [parameter for parameter in parameter_set_1.__dict__.values() if type(parameter) != str]
            for parameter in parameters:
                print('\t', parameter.name, ':', parameter.value)
                
    def change(self, name, value):
        for parameter_set in self.__dict__.values():
            parameters = [parameter for parameter in parameter_set_1.__dict__.values() if type(parameter) != str]
            for parameter  in parameters:
                if parameter.name == name:
                    parameter.value = value

使用此示例代码:

# Individual parameters
parameter_1 = Parameter('parameter_1', 10, 'Value for the parameter 1, usage...')
parameter_2 = Parameter('parameter_2', 20, 'Value for the parameter 2, usage...')
parameter_n = Parameter('parameter_n', 50, 'Value for the parameter n, usage...')
parameter_m = Parameter('parameter_m', 100, 'Value for the parameter m, usage...')

# Parameter sets
parameter_set_1 = ParameterSet('parameter_set_1', parameter_1, parameter_2)
parameter_set_2 = ParameterSet('parameter_set_n', parameter_n, parameter_m)

# Global parameter set
GP = GlobalParameters(parameter_set_1, parameter_set_2)

我得到了想要的行为:

>>> GP.info()
parameter_set_1
     parameter_1 : 10
     parameter_2 : 20
parameter_set_n
     parameter_1 : 10
     parameter_2 : 20

以及.change 方法:

>>> GP.parameter_set_1.parameter_1.value
10

GP.change('parameter_1', 15)

>>> GP.parameter_set_1.parameter_1.value
15

【讨论】:

以上是关于创建一个继承自函数创建的类的python类的主要内容,如果未能解决你的问题,请参考以下文章

面向对象之元类

python的类

抽象类,派生类,继承

python类的继承

C# 继承和默认构造函数

12.面向对象(继承/super/接口/抽象类)