0

__new__を使用して、実行時にクラスの基本クラスを変更したいと思います。私は一生懸命に見えましたが、それを理解することができませんでした。

class A(object): pass

class B(object): pass

class C(B): 

    some_attribute_in_c='hello'

    def __new__(cls):
        cls.__bases=(A,) #some code here to change the base class
        return super(C,cls).__new__(A)

x=C()
x.some_attribute_in_c #return Error: x has no attribute 'some_attribute_in_c'

最後の行が「hello」を返し、xが基本クラスAのCのインスタンスになるように、__ new __()に配置する適切なコードは何ですか。

追加
私のユースケースは次のとおりです。

class Pet(object):
    some_attribute_in_pet='I\'m a pet.'

class Dog(Pet):
    some_attribute_in_species='My species is dog.'

class Cat(Pet):
    some_attribute_in_species='My species is cat.'

class PetBuyer(Pet):

    def __new__(cls,desired_animal):
        animal_bought=globals[desired_animal]
        cls.__bases=(animal_bought,) #some code here to change the base class
        return super(PetBuyer,cls).__new__(animal_bought)

    def __init__(self,desired_animal):
        print self.some_attribute_in_pet
        print self.some_attribute_in_species

x = PetBuyer('Dog')

最後の行を印刷してほしい。

私はペットです。
私の種は犬です。

私の目標は、PetBuyerで動物クラスの工場のように__new __()を使用することです。これを行う理由は、構文PetBuyer('Dog')が私のプログラムで便利だからです。

ADDED2
これを行う理由は次のとおりです。私がコーディングしなければならないことは、私にとっては複雑であり、見たところ、適切なクラス設計を推測することはできません。だから私はとにかく問題をコーディングすることに頼ります。私はそれをよりよく理解するのでリファクタリングすることができます。ただし、上記の状況では、リファクタリングするのは時期尚早です。問題のいくつかのコンポーネント間の相互作用をまだ理解していません。実行時に基本クラスを変更すると、それを行うのに役立ちます。後でリファクタリングするのがより快適になります。

4

3 に答える 3

4

そのクラスがすでに存在していることをオーバーライドする場合__new__、とにかく__new__、特定のクラスのインスタンスを作成するために使用されます。必要なことmetaclassは、クラスのファクトリのように機能する、を介して実行できます。

例えば

class A(object): pass

class B(object): pass

class M(type):
    def __new__(cls, clsname, bases, attribs):
        # change bases
        bases = (A,)
        return type(clsname, bases, attribs)

class C(B): 
    __metaclass__ = M    
    some_attribute_in_c='hello'

print C.__bases__
x = C()
print isinstance(x, A)
print x.some_attribute_in_c

出力:

(<class '__main__.A'>,)
True
hello

OPの編集を見た後、上記のすべてを忘れると言います。メタクラスは必要ありません。PetBuyer(を持っている)で構成される単純なクラスだけPetです。したがって、質問は、ペットをPetBuyerに渡すことができない理由です。

class Pet(object):
    some_attribute_in_pet='I\'m a pet.'

class Dog(Pet):
    some_attribute_in_species='My species is dog.'

class Cat(Pet):
    some_attribute_in_species='My species is cat.'

class PetBuyer(Pet):

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

        print self.pet.some_attribute_in_pet
        print self.pet.some_attribute_in_species

x = PetBuyer(Dog())

classまた、PetBuyerを変更する必要がある理由もわかりませんが、デザインが悪いIMOです。

于 2012-04-27T20:33:43.307 に答える
1

新しい情報に基づくと、型を動的に作成する必要があるようです。確かに、これらのタイプを記述するためのスイートを作成する義務はありません。関数を直接class呼び出すことにより、実行時にそれらを作成できます。type

def make_thingy(bases):
    new_thingy_class = type("???", bases, {})
    new_thingy_instance = new_thingy_class()
    print new_thingy_instance.some_attribute_in_pet
    print new_thingy_instance.some_attribute_in_species
    return new_thingy_instance

x = new_thingy(Dog)
于 2012-04-28T01:05:19.120 に答える
0

TokenMacGuyによって提供され、delnanによって示唆された私の質問に対する即時の答えは、

class Pet(object):
    pet_attribute='I\'m a pet.'

class Dog(Pet):
    species_attribute='My species is dog.'

class Cat(Pet):
    species_attribute='My species is cat.'

class NewThingy(object):

    def __new__(cls,desired_base):
        x = type(desired_base.__name__+'NewThingy',
                 (NewThingy,desired_base),{})
        return super(NewThingy,cls).__new__(x,cls)

    def __init__(self,desired_base):
        print self.pet_attribute
        print self.species_attribute

x = NewThingy(Dog)

このプリント

私はペットです。
私の種は犬です。

于 2012-04-29T17:20:53.067 に答える