2

我要问的可能看起来很奇怪,但这里有一个例子:

我有一个班级'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

4 回答 4

2

使用继承,是的:

class B(A):
    def __init__(self, obj):
        self.obj = obj # obj is any object
于 2012-06-24T18:58:01.033 回答
2

2 可能性

而不是isinstance(second, A)isinstance(second.obj, A)

第二......更hackish的方式是做这样的事情:

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

这是骇人听闻的,因为它基本上使解释器误以为实例是不同的类。那就是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's __init__,但为此你需要更多的巫毒/魔法(如果你有兴趣就发帖)。

>>> isinstance(second, A)
True
>>> isinstance(second, B)
False
>>> second.a
1
>>> second.b
Traceback (most recent call last):
  File "<pyshell#15>", line 1, in <module>
    second.b
AttributeError: A instance has no attribute 'b'
>>> second.someFunc()
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    second.someFunc()
AttributeError: A instance has no attribute 'someFunc'
>>> second.b2
5
>>> second.obj
<__main__.A instance at 0x0123CAF8>
于 2012-06-24T19:08:21.940 回答
2

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

你最终做的非常类似于:

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

它生成class B从 A 派生的,包含 A() 的实例 - 因为这是一个函数,您可以出于任何原因传递您喜欢的任何内容。

于 2012-06-24T19:18:38.153 回答
1

我很想暗示这不太可能是一个好主意,即使它可能以一种非黑客的方式。(编辑:乔恩克莱门茨的建议让我觉得这是最好/最不老套的方式,但我仍然建议我的帖子的其余部分是相关的。)我会进一步冒险暗示这是将“is-a”关系与什么混为一谈/混淆应该是“有”的关系。除非发布有关 OP 试图实现的目标的更多详细信息,否则无法确定。

无论如何,有人(我认为是 Kent Beck)曾经说过(据我记忆中的解释)继承在代码体之间创建了非常强大的耦合,伴随着维护和增强方面的困难,因此继承真的应该在你的技巧包中非常深入并且不应该轻易使用。换句话说:尽可能选择组合(或聚合)而不是继承。

于 2012-06-24T19:22:12.910 回答