2009-02-28 1 views
16

クラスAのオブジェクトを生成するライブラリ関数があり、Aから継承するクラスBを作成したとします。Pythonでオブジェクトをサブクラスに変換しますか?

ライブラリ関数を使用して生成する最も簡単な方法は何ですか?クラスBのオブジェクト?私はここで、より詳細なコメントに頼まれた編集 -

は行く:

PyTablesはPythonで、階層的なデータセットを扱うパッケージです。私が最もよく使うビットは、部分的にディスク上にあるデータを管理する能力です。それは、拡張スライスにのみ付属する '配列'型を提供しますが、任意の行を選択する必要があります。 Numpyはこの機能を提供しています。あなたが選択している配列と同じ長さのブール値配列を提供することで選択できます。したがって、この新しい機能を追加するためにArrayをサブクラス化したかったのです。

より抽象的な意味では、これは私が以前考えていた問題です。通常の解決策は、すでに提案されている通りです.BのコンストラクタにAと追加の引数をとり、Bの中に挿入するAの関連ビットを取り出します。かなり基本的な問題のように見えますが、私は質問しました私が気づいていなかった標準的な解決策があるかどうかを調べる。

+0

を、あなたがやりたい理由についての詳細を追加することができますこの? – Kiv

答えて

13

ライブラリ関数はAを返すので、変更せずにBを返すことはできません。

class A: # defined by the library 
    def __init__(self, field): 
     self.field = field 

class B(A): # your fancy new class 
    def __init__(self, field, field2): 
     self.field = field 
     self.field2 = field2 # B has some fancy extra stuff 

def b_from_a(a_instance, field2): 
    """Given an instance of A, return a new instance of B.""" 
    return B(a_instance.field, field2) 


a = A("spam") # this could be your A instance from the library 
b = b_from_a(a, "ham") # make a new B which has the data from a 

print b.field, b.field2 # prints "spam ham" 

編集:あなたの状況に応じて、構図代わりの継承を行うことができます

ことの一つは、インスタンスのフィールドを取るように関数を記述し、新しいBのインスタンスにそれらをコピーしていますは良い賭けになるかもしれません。あなたのBクラスはAのインスタンスを継承するのではなく、Aのインスタンスを含むことができます:

class B2: # doesn't have to inherit from A 
    def __init__(self, a, field2): 
     self._a = a # using composition instead 
     self.field2 = field2 

    @property 
    def field(self): # pass accesses to a 
     return self._a.field 
    # could provide setter, deleter, etc 

a = A("spam") 
b = B2(a, "ham") 

print b.field, b.field2 # prints "spam ham" 
+3

Pythonオブジェクトは '.__ class__'属性を設定することによってクラスを認識します。実際には別のものに設定することができます:http://stackoverflow.com/a/29256784/1423333 –

+0

私はup.propertyを使ってself._aからデータを取得します。構成は単体テストするのがはるかに簡単な純粋な方法を書くことに役立ちます。継承は間違ったものではなく、実際にあなたのユースケースに依存します。しかし、私の経験によれば、構成は長期的に扱いやすくなる傾向があります。 – srock

1

Monkeypatch the library?例えば

import other_library 
other_library.function_or_class_to_replace = new_function 

パッと消える、それはあなたがそれを返すようにしたいものを返します。

Monkeypatch A. new Bのインスタンスを返すには?

obj = A()を呼び出した後、結果をobjに変更します。 クラス = B?

15

これは、サブクラスの初期化子がそれを処理できる場合、または明示的なアップグレードを作成した場合に実行できます。次に例を示します。

class A(object): 
    def __init__(self): 
     self.x = 1 

class B(A): 
    def __init__(self): 
     super(B, self).__init__() 
     self._init_B() 
    def _init_B(self): 
     self.x += 1 

a = A() 
b = a 
b.__class__ = B 
b._init_B() 

assert b.x == 2 
3

あなたはをやっているか知っている場合は、実際にオブジェクト.__class__属性を変更することができます。

In [1]: class A(object): 
    ...:  def foo(self): 
    ...:   return "foo" 
    ...: 

In [2]: class B(object): 
    ...:  def foo(self): 
    ...:   return "bar" 
    ...: 

In [3]: a = A() 

In [4]: a.foo() 
Out[4]: 'foo' 

In [5]: a.__class__ 
Out[5]: __main__.A 

In [6]: a.__class__ = B 

In [7]: a.foo() 
Out[7]: 'bar' 
関連する問題