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'

放入 __new__() 的正确代码是什么,以便最后一行返回“hello”,x 是基类 A 的 C 实例。

添加
了我的用例如下。

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__用于创建给定类的实例,您想要的可以通过 a 完成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由 (has a) 组成的简单类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())

我也不明白为什么你需要改变classPetBuyer,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 回答