これらの「クラスを動的に作成する」という質問に「type() 関数を使用する」と答えているのを見てきました。いつかやらなければならないことは確かですが、私が無知であることはわかっています。しかし、私が見てきたことから、名前など、クラスについて何かを知っている必要があります。
私がやろうとしているのは、idl タイプのファイルを解析し、そこからメソッドと属性を持つクラスを作成することです。そのため、文字列を解析するまで、クラス名、関数、引数などが何であるかを事前に知りません。
何か案は?
これらの「クラスを動的に作成する」という質問に「type() 関数を使用する」と答えているのを見てきました。いつかやらなければならないことは確かですが、私が無知であることはわかっています。しかし、私が見てきたことから、名前など、クラスについて何かを知っている必要があります。
私がやろうとしているのは、idl タイプのファイルを解析し、そこからメソッドと属性を持つクラスを作成することです。そのため、文字列を解析するまで、クラス名、関数、引数などが何であるかを事前に知りません。
何か案は?
http://docs.python.org/library/functions.html#type
Google で検索するのは少し難しいですが、次のように検索し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
私が考えることができるその場で関数を作成する方法は 2 つあります。通常悪い方法は、コードを書いて再解析することです (正しく行えば、パフォーマンスが大幅に向上します)。適切な方法は、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 プロトタイプと docstring を含む辞書のようなものの下にある各動的クラス内に格納されます。
実際の callable については、次のようなスケルトンを作成します
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)
繰り返しますが、これらはどちらも非常に単純な例であり、この種の問題を処理する際に発生する問題やエッジ ケースの大部分をカバーしていません。これは、解決策を見つけるためのいくつかの方法の 1 つでもあります。
例:
これを「クラスを動的に作成する方法」と考えるのではなく、代わりに Python のメタプログラミング機能を使用する機会と考えてください。
私がアイデアを探す最初の場所は、標準ライブラリのソースです。具体的には、そうでなければ存在しないメソッド呼び出しをその場で処理するためxmlrpclib
にどのように使用されるかを見てください。__getattr__
Python を動的言語と呼ぶ理由は、その可能性を完全に理解するまで理解できませんでした。