2011-02-01 9 views
11

パラメータxを渡し、新しいクラスCを返す関数を作成しようとしています。 Cは、固定基本クラスAのサブクラスである必要があります。追加するのは1つだけです。特定のクラス属性が追加され、xに設定されています。言い換えればpython 3:class "template"(パラメータ化されたクラスを返す関数)

class C(A): 
    C.p = x # x is the parameter passed to the factory function 

が行うのは、これは使いやすいですか?私が知っておくべき問題がありますか?

答えて

9

最初に、「クラスファクトリ」という用語は、Pythonではやや古いものです。動的に型指定されたクラスのインスタンスを返す関数のために、C++のような言語で使用されています。それはC++で際立つので、名前があります。稀ではありませんが、パターンに名前を付けると便利です。しかし、Pythonでは、これは絶えず行われています。それは誰も特別な名前を付けなくてはいけないという基本的な操作です。

また、クラスファクトリは、クラス自体ではなく、クラスのインスタンスを返します。クラスの新しいインスタンスではなく、 "新しいクラス"を返すと言ったのですが、これはC++のような言語のものであり、クラス専用のオブジェクトを返す概念はないからです。

これは、ローカルクラスを作成し、それを返すために些細です:

def make_class(x): 
    class C(A): 
     p = x 
    return C 
+0

ありがとう、私は私の質問から 'factory'への参照を削除しました。この関数を使用すると、名前の競合に問題がありますか、関数が復帰するまでに 'C 'を忘れてしまいますか? – max

+0

私が上記のコメントで言ったように、名前が記録されている* 2つの場所があります。 Glennの例では、名前 "C"はクラスの内部名(クラスの永続プロパティ)とローカル変数名 "C"の両方です。関数が戻るとき、ローカル変数 "C"は忘れられますが、クラスは内部名 "C"を保持します。しかし、私が上で述べたように、内部クラス名の名前の衝突はないので、これは問題ではありません。 – mgiuca

+0

クラス自体は単なるオブジェクトです。それは 'C = 1; Cを返す。 (名前 "C"はオブジェクトに 'C .__ name__'として格納されていますが、デバッグや化粧の目的にのみ使用されます) –

5

type関数には、新しいクラスを動的に構築する3引数バージョンがあります。 の名前,ベースdictにクラスの属性とメソッドを含めて渡します。あなたのケースでは

def class_factory(x): 
    return type("C", (A,), {"p": x}) 

あなたは明らかに動的に「C」、クラスの名前を設定しますが、クラスはパブリックにアクセスできるようにするために、あなたはまたの結果を代入する必要があることに注意してくださいすることができます関数を変数に変換します。 globals()["C"] = ...を使って動的に行うことも、クラスを辞書に割り当てることもできます。

+1

嫌、ありません。クラスが必要な場合は、クラスを定義するだけです。 –

+0

関数が異なるパラメータで呼び出されたときに名前の競合が発生しませんか?おそらくそれを避けるためにクラス名に余分なテキストを追加する必要がありますか? – max

+0

@Glenn Maynard興味深い。私はこれらを試してみて、どちらもほぼ同じことを作るようです。クラスが動的に作成されているので、私の方法はよりクリーンであると思われます。クラスを動的に作成するように設計された関数を呼び出すこともできます。 1つは、クラスの* name *またはそれが由来する* base *クラスを動的にカスタマイズしたい場合、Glennのメソッドは機能しないため、私のほうがより一般的です。とにかく、私はちょうどこの例を使って "タイプ"がどのように動作するかを示すマニュアル(上にリンクされています)に行きます。 – mgiuca

関連する問題