如何使用初始化程序在Python中动态创建类

时间:2016-08-02 01:20:29

标签: python

以下是一些代码:

def objectify(name, fields):
    """ Create a new object including the __init__() method. """
    def __init__(self, *argv):
        for name, val in zip(var_names, argv):
            setattr(self, name, val)

    # The following line of code is currently limited to a single dynamic class.
    # We would like to extend it to allow creating multiple classes
    # and each class should remember it's own fields.
    __init__.var_names = fields

    result = type(name, (object,), dict(__init__=__init__))

这里的挑战是找到一种方法来制作每个类的__init__()方法的唯一副本,该方法具有其变量名称的静态列表。

B计划: 我们可以使用eval()来运行函数生成的代码。但是尽可能避免eval()。这里的挑战是在没有eval()的情况下执行此操作。

编辑:在写这个问题时,我想出了一个解决方案。 (见下文。)也许这会对某人有所帮助。

EDIT2:我会使用此函数创建类似namedtuple()的内容,但它们是可变的。

Point = objectify('point', ['x', 'y'])
a = Point(1, 2)
b = Point(2, 3)
print a.__dict__
print b.__dict__

2 个答案:

答案 0 :(得分:3)

您稍后不会提及有关字段用法的任何内容。如果您只在__init__中需要它们,则根本不需要保存它们:

def objectify(name, fields):
    """ Create a new object including the __init__() method. """
    fields = fields[:]
    def __init__(self, *argv):
        for name, val in zip(fields, argv):
            setattr(self, name, val)

    result = type(name, (object,), dict(__init__=__init__))
    return result

否则,您应该查看元类 - 它们恰好是它们的用例。

更新:制作fields的副本可确保更改调用方中的列表不会影响存储的列表。值仍然可以更改...作为练习留给读者,以验证所有内容都是str

答案 1 :(得分:0)

这是一个解决方案:

def objectify(obj_name, fields):
    """ Create a new object including the __init__() method. """

    def __init__(self, *argv):
        """ Generic initializer for dynamically created classes. """
        fields = objectify.fields[self.__class__.__name__]
        for field, val in zip(fields, argv):
            setattr(self, field, val)

    result = type(obj_name, (object,), dict())
    result.__init__ = __init__

    # Save the list of fields in a static dictionary that is retrieved by class name.
    objectify.fields[obj_name] = fields

    return result

objectify.fields = {}           # A static local variable.