在实例化对象时,是否有可能传入一个对象应该派生自的类?
例如:
class Red(object):
def x(self):
print '#F00'
class Blue(object):
def x(self):
print '#00F'
class Circle(object):
def __init__(self, parent):
# here, we set Bar's parent to `parent`
self.x()
class Square(object):
def __init__(self, parent):
# here, we set Bar's parent to `parent`
self.x()
self.sides = 4
red_circle = Circle(parent=Red)
blue_circle = Circle(parent=Blue)
blue_square = Square(parent=Blue)
其效果类似:
class Circle(Red):
def __init__(self):
self.x()
但是,不影响Circle
的其他实例。
答案 0 :(得分:7)
也许您正在寻找的是一个班级工厂:
#!/usr/bin/env python
class Foo(object):
def x(self):
print('y')
def Bar(parent=Foo):
class Adoptee(parent):
def __init__(self):
self.x()
return Adoptee()
obj=Bar(parent=Foo)
答案 1 :(得分:4)
我同意@AntsAasma。您应该考虑使用dependency injection。至少在给出的示例中(我肯定会大大简化以说明您的问题),通过has-a relationship而不是is-a relationship来更好地表示形状的颜色。
您可以通过将所需的颜色对象传递给构造函数,存储对它的引用以及将函数调用委托给此对象来实现此目的。这极大地简化了实现,同时仍保留了所需的行为。请看这里的例子:
class Red(object):
def x(self):
print '#F00'
class Blue(object):
def x(self):
print '#00F'
class Shape(object):
def __init__(self,color):
self._color=color
def x(self):
return self._color.x()
class Circle(Shape):
def __init__(self, color):
Shape.__init__(self,color)
self.x()
class Square(Shape):
def __init__(self, color):
Shape.__init__(self,color)
self.x()
self.sides = 4
red_circle = Circle(color=Red())
blue_circle = Circle(color=Blue())
blue_square = Square(color=Blue())
编辑:修复了示例代码中构造函数参数的名称
答案 2 :(得分:1)
听起来你正试图将继承用于不适合的事情。如果您想解释为什么要这样做,可能会找到一种更加惯用且有效的方法来实现您的目标。
答案 3 :(得分:0)
如果你真的需要它,那么你可以使用type
构造函数,例如在工厂函数内(或在__new__
方法内,但这可能是更安全的方法):
class Foo(object):
def x(self):
print 'y'
class Bar(object):
def __init__(self):
self.x()
def magic(cls, parent, *args, **kwargs):
new = type(cls.__name__, (parent,), cls.__dict__.copy())
return new(*args, **kwargs)
obj = magic(Bar, parent = Foo)
答案 4 :(得分:0)
正如其他人所说,这是一个非常奇怪的用法,但是,如果你真的想要它,它肯定是可行的(除了神秘的Bar
,你在评论中茫然;-)。例如:
class Circle(object):
def __init__(self, parent):
self.__class__ = type('Circle', (self.__class__, parent), {})
self.x()
这为Circle
的每个实例提供了自己的个人类(全部名为Circle
,但都不同) - 这部分实际上是这个成语有时非常有用的关键原因(当你想要一个使用新式类的“每实例自定义特殊方法”:由于特殊方法总是在类上查找,要按实例自定义它,您需要每个实例都有一个不同的类! - )。如果您希望尽可能多地进行类共享,您可能需要一些备忘录工厂功能来帮助:
_memo = {}
def classFor(*bases):
if bases in _memo: return _memo[bases]
name = '_'.join(c.__name__ for c in bases)
c = _memo[bases] = type(name, bases, {})
return c
(这里我也使用不同的方法来生成类的名称,使用Circle_Red
和Circle_Blue
等类名作为示例,而不仅仅是Circle
)。然后:
class Circle(object):
def __init__(self, parent):
self.__class__ = classFor(Circle, parent)
self.x()
所以这项技术非常流畅,但我仍然认为它与你举例说明的用例不相符。但是,它可能在其他用例中很有用,所以我正在展示它。