我已经看到了这些“动态创建类”的问题,这些问题的回答是“使用 type() 函数”。我确定我必须在某个时候这样做,但我知道我一无所知。但是从我所见,您必须已经知道该类的一些信息,例如名称。
我要做的是解析一个 idl 类型的文件,并从中创建一个具有方法和属性的类。所以在我解析字符串之前,我不知道类名、函数、参数或任何东西是什么。
有任何想法吗?
我已经看到了这些“动态创建类”的问题,这些问题的回答是“使用 type() 函数”。我确定我必须在某个时候这样做,但我知道我一无所知。但是从我所见,您必须已经知道该类的一些信息,例如名称。
我要做的是解析一个 idl 类型的文件,并从中创建一个具有方法和属性的类。所以在我解析字符串之前,我不知道类名、函数、参数或任何东西是什么。
有任何想法吗?
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.
在我们的项目中,我们创建了一个对象,该对象公开了一个能够添加可调用属性的具体方法。我们为模式解析大量 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)
同样,这些都是非常幼稚的例子,并没有涵盖处理此类问题时出现的大多数问题和边缘情况。这也是寻找解决方案的几种方法之一。
例子:
与其将其视为“我如何动态创建一个类”,不如将其视为一个使用 Python 元编程功能的机会。
我要寻找想法的第一个地方是标准库源代码xmlrpclib
——特别是看看它是如何动态__getattr__
处理其他不存在的方法调用的。
我知道在我完全接受这些可能性之前,我并不真正理解他们为什么称 Python 为动态语言。