Convert superclass instance to subclass instance
- 我有一个不能触摸的外部图书馆。这个库有一个函数gena(),它返回类A的实例。
- 在我这边,我把B类定义为A类的一个子类。
- 我想在我的项目中使用类B的实例,但是该实例应该由gena()生成。
有什么标准和简单的方法可以做到这一点吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # I cannnot tweak these code def genA(): a = A return(a) class A: def __init__(): self.a = 1 # --- # code in my side class B(A): def __init__(): self.b = 2 a = genA() # like a copy-constructor, doesn't work # b = B(a) # I want to get this b.a # => 1 b.b # => 2 |
这里是一个等价的C++代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #include <iostream> // library side code class A { public: int a; // ... many members A() { a = 1; } }; void fa(A a) { std::cout << a.a << std::endl; } A genA() { A a; return a; } // /// // my code class B : public A { public: int b; B() : A() { init(); } B(A& a) : A(a) { init(); } void init() { b = 2; } }; void fb(B b) { std::cout << b.b << std::endl; } int main(void) { A a = genA(); B b(a); fa(b); // => 1 fb(b); // => 2 } |
号
您不应该使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class A(object): def __init__(self): self.a = 10 class B(A): def __new__(cls, a): a.__class__ = cls return a def __init__(self, a): self.b = 20 a = A() b = B(a) print type(b), b.a, b.b # <class '__main__.B'> 10 20 |
号
但正如我所说,不要这样做,您可能应该使用聚合,而不是在这种情况下使用子类。如果您希望制作
1 2 3 4 5 6 7 8 9 10 11 12 13 | class B(object): def __init__(self, a): self.__a = a self.b = 20 def __getattr__(self, attr): return getattr(self.__a, attr) def __setattr__(self, attr, val): if attr == '_B__a': object.__setattr__(self, attr, val) return setattr(self.__a, attr, val) |
我不明白你的密码。我认为这是错误的。首先,在EDOCX1中,A和B都没有self(0);其次,在B类中,您没有调用A的构造函数。第三,gena不返回任何对象,只引用一个类。请检查更改的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | def genA(): a = A() #<-- need () return(a) class A: def __init__(self): # <-- self missing self.a = 1 # --- # code in my side class B(A): def __init__(self, a=None): super().__init__() #<-- initialize base class if isinstance(a, A): #<-- if a is instance of base class, do copying self.a = a.a self.b = 2 a = genA() a.a = 5 b = B(a) # this works print(b.a) # => 5 print(b.b) # => 2 |
似乎没有一种标准的方法可以做到这一点,但有几种方法。如果您不想处理每个单独的属性,我建议使用以下属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 | class A(object): # Whatever class B(A): def __init__(self, a): super(B, self).__init__() for attr in dir(a): setattr(self, attr, getattr(a, attr)) # Any other specific attributes of class B can be set here # Now, B can be instantiated this way: a = A() b = B(a) |
。
如果您不想访问父级的"private"属性,可以添加
1 | if not attr.startswith('__'): |
在