7

我已经看到了这些“动态创建类”的问题,这些问题的回答是“使用 type() 函数”。我确定我必须在某个时候这样做,但我知道我一无所知。但是从我所见,您必须已经知道该类的一些信息,例如名称。

我要做的是解析一个 idl 类型的文件,并从中创建一个具有方法和属性的类。所以在我解析字符串之前,我不知道类名、函数、参数或任何东西是什么。

有任何想法吗?

4

3 回答 3

15

http://docs.python.org/library/functions.html#type

谷歌有点难,但你可以搜索python type(name, bases, dict) function examples得到:

http://www.voidspace.org.uk/python/articles/metaclasses.shtml

上面的摘录,它触及了你问题的核心:


以下基本上是等价的:

def __init__(self, x):
    self.x = x

def printX(self):
    print self.x

Test = type('Test', (object,), {'__init__': __init__, 'printX': printX})

和:

class Test(object):
    def __init__(self, x):
        self.x = x

    def printX(self):
        print self.x

我能想到的动态创建函数的方法有两种。通常不好的方法是编写代码并重新解析它(虽然做得正确,但这可以大大提高性能)。理智的方法是实现一个解释你的 IDL 的函数。这称为高阶函数:http ://effbot.org/pyfaq/how-do-you-make-a-higher-order-function-in-python.htm

如果您找不到 IDL 的解释器(如果它是自定义 IDL),您将编写的示例类似于上面的链接,例如:

def makeMethod(idlCode):
    syntax = MyIDL.parse(idlCode)

    def newMethod(*args, **kw):
        if syntax.statementType == MyIDL.IF_STATEMENT:
            if secureLookup(mySyntaxTree.IF):
               return secureLookup(args[0]) 
            else:
               return secureLookup(args[1])
        ...

    return (syntax.methodName, newMethod)

如果您在 IDL 的构造与 *args 和 **kw 的语法之间建立映射,则有许多更优雅的方法可以扩展此方法,但这为您提供了最大的灵活性,并且是我能做到的最直接和基本的方法考虑到。

然后你会传入:

class DynamicIdlClass(object):
    ...

for idlObject in idlCode:
    methods = dict(makeMethod(clause) for clause in idlObject.clauses})
    methods['__init__'] = makeInitMethod(idlObject.initClause)
    idlObject = type('Test', (DynamicIdlClass,), methods)

    yield idlObject  # or idlObjectsList.push(idlObject), etc.
于 2012-05-11T17:25:02.203 回答
1

在我们的项目中,我们创建了一个对象,该对象公开了一个能够添加可调用属性的具体方法。我们为模式解析大量 yaml 文件并动态组装这些对象。

类似的东西

def add_method(name, callable):
    setattr(self,name,callable)

但这是一个非常幼稚的例子,但你明白了。模式存储在每个动态类中,类似于__schema包含 kwarg 原型和文档字符串的字典。

对于实际的可调用对象,请制作一个类似的骨架

def skel(self, *args, **kwargs):
    if '_schema' in kwargs:
        parse_yml, add control statements
    handle args and kwargs based on schema

some_instance.add_method('blah',skel)

同样,这些都是非常幼稚的例子,并没有涵盖处理此类问题时出现的大多数问题和边缘情况。这也是寻找解决方案的几种方法之一。

例子:

离子对象

对象模型生成器

于 2012-05-11T17:28:11.613 回答
0

与其将其视为“我如何动态创建一个类”,不如将其视为一个使用 Python 元编程功能的机会。

我要寻找想法的第一个地方是标准库源代码xmlrpclib——特别是看看它是如何动态__getattr__处理其他不存在的方法调用的。

我知道在我完全接受这些可能性之前,我并不真正理解他们为什么称 Python 为动态语言。

于 2012-05-11T17:53:36.237 回答