Python: how to "combine" two classes

I want to add some attributes and methods to various classes. The methods and attributes that I have to add are the same, but not the class to assign them to, so I want to build a class that assigns new methods and attributes to the class specified in the argument. I try this, but it does not work: (I know that this is a very wrong way to try to appropriate something for myself, it is just to show what I want to do)

class A: def __init__(self): self.a = 'a' def getatt(self): return self.a class B: def __init__(self, parent) : self = parent # This is working : print self.getatt() def getattB(self): return self.getatt() insta = A() instb = B(insta) # This is not working : print instb.getattB() 

Result:

 a Traceback (most recent call last): File "D:\Documents and settings\Bureau\merge.py", line 22, in <module> print instb.getattB() File "D:\Documents and settings\Bureau\merge.py", line 16, in getattB return self.getatt() AttributeError: B instance has no attribute 'getatt' 

And I was expecting to get "a" for calling instb.gettattB ()

To resume, I want to inherit class B from class A, giving class A in the argument of class B, because my class B will be a subclass of a different class, not always A.

+4
source share
5 answers

The best answer in the comments, it was useful to me, so I decided to show it in response (thanks to sr2222): The path to dynamically declaring inheritance in Python is the built-in type () function. For my example:

 class A(object) : def __init__(self, args): self.a = 'a' self.args = args def getattA(self): return self.a, self.args class B(object) : b = 'b' def __init__(self, args) : self.b_init = args def getattB(self): return self.b C = type('C', (A,B), dict(c='c')) instc = C('args') print 'attributes :', instc.a, instc.args, instc.b, instc.c print 'methodes :', instc.getattA(), instc.getattB() print instc.b_init 

Return code:

 attributes : a args bc methodes : ('a', 'args') b Traceback (most recent call last): File "D:\Documents and settings\Bureau\merge2.py", line 24, in <module> print instc.b_init AttributeError: 'C' object has no attribute 'b_init' 

My class C initializes the attributes and methods of class A and class B, and we add the attribute c. With instanciation C (instc = C ('args')) init for A is a call, but not for B.

Very useful for me, because I need to add some attributes and methods (the same) in different classes.

+3
source

I'm not sure what you are trying to do, but the code below gives me the output that I think you expect. note:

  • a is initialized outside the constructor in A
  • B is declared as a subclass of A

the code:

 class A: a='' #Initialize a def __init__(self): self.a = 'a' def getatt(self): return self.a class B(A): #Declare B as subclass def __init__(self, parent) : self = parent print self.getatt() def getattB(self): return self.getatt() insta = A() instb = B(insta) print instb.getattB() 
+1
source

Since B is not a subclass of A, there is no path to getatt () in A in B

+1
source

How about this?

 class A: def __init__(self): self.a = 'a' def getatt(self): return self.a class B: def __init__(self, parent) : self.parent = parent def __getattr__(self, attr): return getattr(self.parent, attr) def getattB(self): return self.parent.getatt() insta = A() instb = B(insta) print instb.getattB() print instb.getatt() 

But a class A method cannot access attr in class B.

Another way:

 import functools class A: def __init__(self): self.a = 'a' def getatt(self): return self.a class B: def __init__(self, parent): for attr, val in parent.__dict__.iteritems(): if attr.startswith("__"): continue self.__dict__[attr] = val for attr, val in parent.__class__.__dict__.iteritems(): if attr.startswith("__"): continue if not callable(val): continue self.__dict__[attr] = functools.partial(val, self) def getattB(self): return self.getatt() insta = A() instb = B(insta) print instb.__dict__ print instb.getattB() print instb.getatt() 

Slow init , but call fast.

+1
source

I had problems with calling different constructors, using super does not necessarily make sense in this case, I decided to inherit and call each constructor on the current object manually:

 class Foo(object): def __init__(self, foonum): super(Foo, self).__init__() self.foonum = foonum class Bar(object): def __init__(self, barnum): super(Bar, self).__init__() self.barnum = barnum class DiamondProblem(Foo, Bar): # Arg order don't matter, since we call the `__init__` ourself. def __init__(self, barnum, mynum, foonum): Foo.__init__(self, foonum) Bar.__init__(self, barnum) self.mynum = mynum 
0
source

Source: https://habr.com/ru/post/1400992/


All Articles