在python中将'A'类型的对象作为'B'类型的实例

时间:2012-06-24 18:55:27

标签: python python-2.7

我所问的可能看起来很奇怪,但这是一个例子:

我有课程' A'

class A:
    a=1

其他我班级' B'

class B:
    def __init__(self, obj):
        self.obj = obj # obj is any object

现在我用:

first = A()
second = B(first)
isinstance(second, A)

我希望第3步是真的。即,无论B对象是什么,它都应该对象类型的实例添加到对象中。

Python中是否可以这样?

4 个答案:

答案 0 :(得分:2)

使用继承,是的:

class B(A):
    def __init__(self, obj):
        self.obj = obj # obj is any object

答案 1 :(得分:2)

2可能性

代替isinstance(second, A)执行isinstance(second.obj, A)

第二......更糟糕的做法是做这样的事情:

class B:
    def __init__(self, obj):
        self.obj = obj # obj is any object
        self.__class__ = obj.__class__

这是hackish,因为它基本上欺骗了解释器,认为实例是一个不同的类。那是isinstance(second, B)将返回False

要回答下面提出的问题:解释器基本上就像second是一个类A,并且B中的任何类别都没有定义。例如,如果你做了类似

的事情
class B:
    b=2 #Won't be visible
    def __init__(self, obj):
        self.obj = obj # obj is any object
        self.b2 = 5 #Instance variable will be visible
        self.__class__ = obj.__class__

    def someFunc(self): #Won't be visible
        return 3

使用与上面用于初始化的相同代码,这是使用解释器的一些调用会发生的情况。通常,将删除任何类变量或方法,而是使用A'a,但是将记住任何实例变量。因为这样做self.obj = obj有点多余。基本上实例化B(obj)将或多或少地返回与obj相同的类的对象。虽然它不会调用obj的{​​{1}},但为此您需要更多的伏都教/魔法(如果您只是感兴趣的话)。

__init__

答案 2 :(得分:2)

您当然可以覆盖__new__并从type而不是object派生您的对象,从而有效地创建一个类工厂......

你最终做的非常类似于:

b = type('B', (A,), {'obj': A()})

它生成一个从A派生的class B,包含该A()的实例 - 因为这是一个函数,你可以根据你想要的任何原因传递你想要的任何东西。

答案 3 :(得分:1)

我很想提出这种情况极不可能是一个好主意,即使它可以以非黑客的方式存在。 (编辑:乔恩克莱门茨的建议让我感到最好/最少的hackish方式,但我仍然建议我的其余部分是相关的。)我还有进一步的危险,这表明这是混淆/混淆与这是一个“是一个”的关系应该是一个“有一个”的关系。除非有关OP正在努力实现的更多细节,否则无法确切知道。

无论如何,有人(Kent Beck,我认为)曾经说过(我记得这句话),继承会在代码体之间产生非常强大的耦合,伴随着维护和增强方面的困难,因此继承应该在你的一袋技巧,不应轻易使用。换句话说:在可能的情况下,首选组合(或聚合)而不是继承。