我想在运行时使用__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实例。
ADDED
我的用例如下。
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
我这样做的原因如下。对于我而言,我所需要的代码很复杂,因为根据看,我无法推断出正确的类设计。因此,无论如何,我都会使用代码来解决问题,因为我可以更好地理解它。但是,由于上面出现的情况,对我来说重构还为时过早。我还没有理解我的问题的一些组件之间的交互,并在运行时更改基类将帮助我做到这一点。之后我会更适合重构。
答案 0 :(得分:3)
当你覆盖__new__
该类已经存在时,无论如何__new__
用于创建给定类的实例,您可以通过metaclass
完成所需的操作。可以像工厂一样表现
e.g。
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){{组成1}},所以问题是为什么你不能把宠物传递给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())
,是不好的设计IMO
答案 1 :(得分: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)
答案 2 :(得分: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)
打印
我是宠物 我的物种是狗。