如何从基类动态创建派生类

2025-02-27 09:07:00
admin
原创
66
摘要:问题描述:例如我有一个如下的基类:class BaseClass(object): def __init__(self, classtype): self._type = classtype 从此类中我派生出其他几个类,例如class TestClass(BaseClass): ...

问题描述:

例如我有一个如下的基类:

class BaseClass(object):
    def __init__(self, classtype):
        self._type = classtype

从此类中我派生出其他几个类,例如

class TestClass(BaseClass):
    def __init__(self):
        super(TestClass, self).__init__('Test')

class SpecialClass(BaseClass):
    def __init__(self):
        super(TestClass, self).__init__('Special')

有没有一种好的、pythonic 的方式可以通过函数调用来动态地创建这些类,将新类放入我当前的范围,比如:

foo(BaseClass, "My")
a = MyClass()
...

因为会有评论和问题问我为什么需要这个:派生类都具有完全相同的内部结构,不同之处在于构造函数采用许多以前未定义的参数。因此,例如,MyClass采用关键字,a而类的构造函数TestClass采用bc

inst1 = MyClass(a=4)
inst2 = MyClass(a=5)
inst3 = TestClass(b=False, c = "test")

但他们绝不应该使用类的类型作为输入参数,例如

inst1 = BaseClass(classtype = "My", a=4)

我已使此方法可行,但更喜欢另一种方式,即动态创建类对象。


解决方案 1:

这段代码允许您创建具有动态名称和参数名称的新类。__init__just 中的参数验证不允许未知参数,如果您需要其他验证(例如类型)或它们是强制性的,只需在那里添加逻辑:

class BaseClass(object):
    def __init__(self, classtype):
        self._type = classtype

def ClassFactory(name, argnames, BaseClass=BaseClass):
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            # here, the argnames variable is the one passed to the
            # ClassFactory call
            if key not in argnames:
                raise TypeError("Argument %s not valid for %s" 
                    % (key, self.__class__.__name__))
            setattr(self, key, value)
        BaseClass.__init__(self, name[:-len("Class")])
    newclass = type(name, (BaseClass,),{"__init__": __init__})
    return newclass

它的工作原理如下,例如:

>>> SpecialClass = ClassFactory("SpecialClass", "a b c".split())
>>> s = SpecialClass(a=2)
>>> s.a
2
>>> s2 = SpecialClass(d=3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in __init__
TypeError: Argument d not valid for SpecialClass

我看到你要求在命名范围中插入动态名称——现在,在 Python 中不被认为是一个好的做法——你要么有在编码时已知的变量名,要么有数据——并且在运行时学习的名称更多的是“数据”而不是“变量”——

因此,您只需将您的类别添加到字典中并从那里使用它们即可:

name = "SpecialClass"
classes = {}
classes[name] = ClassFactory(name, params)
instance = classes[name](...)

如果您的设计确实需要名称进入范围,只需执行相同的操作,但使用调用返回的字典globals()
而不是任意字典:

name = "SpecialClass"
globals()[name] = ClassFactory(name, params)
instance = SpecialClass(...)

(类工厂函数确实可以在调用者的全局范围内动态插入名称 - 但这是更糟糕的做法,并且在 Python 实现中不兼容。实现这一点的方法是通过sys._getframe(1)f_globals获取调用者的执行框架,并在其属性中的框架全局字典中设置类名)。

更新,tl;dr:这个答案已经很流行了,但它仍然非常具体到问题主体。关于如何
在 Python 中“从基类动态创建派生类”的一般答案
是简单地调用type传递新类名、包含基类的元组和__dict__新类的主体 - 如下所示:

>>> new_class = type("NewClassName", (BaseClass,), {"new_method": lambda self: ...})

更新

任何需要这个的人也应该检查dill项目 - 它声称能够像 pickle 对普通对象一样对类进行 pickle 和 unpickle 操作,并且在我的某些测试中已经实现了这一点。

解决方案 2:

type()是创建类和特定子类的函数,就像问题中的那样:

def set_x(self, value):
    self.x = value

# type() takes as argument the new class name, its base
# classes, and its attributes:
SubClass = type('SubClass', (BaseClass,), {'set_x': set_x})
# (More methods can be put in SubClass, including __init__().)

obj = SubClass()
obj.set_x(42)
print obj.x  # Prints 42
print isinstance(obj, BaseClass)  # True

解决方案 3:

就我而言:

inst3 = globals()["SpecialClass"](b=False, c = "test")

解决方案 4:

要创建具有动态属性值的类,请查看以下代码。注意:这是 Python 编程语言中的代码片段

def create_class(attribute_data, **more_data): # define a function with required attributes
    class ClassCreated(optional extensions): # define class with optional inheritance
          attribute1 = adattribute_data # set class attributes with function parameter
          attribute2 = more_data.get("attribute2")

    return ClassCreated # return the created class

# use class

myclass1 = create_class("hello") # *generates a class*
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2974  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1836  
  PLM(产品生命周期管理)系统在企业的产品研发、生产与管理过程中扮演着至关重要的角色。然而,在实际运行中,资源冲突是经常会遇到的难题。资源冲突可能导致项目进度延迟、成本增加以及产品质量下降等一系列问题,严重影响企业的效益与竞争力。因此,如何有效应对PLM系统中的资源冲突,成为众多企业关注的焦点。接下来,我们将详细探讨5...
plm项目管理系统   47  
  敏捷项目管理与产品生命周期管理(PLM)的融合,正成为企业在复杂多变的市场环境中提升研发效率、增强竞争力的关键举措。随着技术的飞速发展和市场需求的快速更迭,传统的研发流程面临着诸多挑战,而将敏捷项目管理理念融入PLM,有望在2025年实现研发流程的深度优化,为企业创造更大的价值。理解敏捷项目管理与PLM的核心概念敏捷项...
plm项目   47  
  模块化设计在现代产品开发中扮演着至关重要的角色,它能够提升产品开发效率、降低成本、增强产品的可维护性与可扩展性。而产品生命周期管理(PLM)系统作为整合产品全生命周期信息的关键平台,对模块化设计有着强大的支持能力。随着技术的不断发展,到 2025 年,PLM 系统在支持模块化设计方面将有一系列令人瞩目的技术实践。数字化...
plm软件   48  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用