In the code below, I have a class (MainClass) that contains two subclasses (Class1 and Class2).
class MainClass():
def __init__(self):
self.teste = 'abcdefg'
class Class1():
def __init__(self):
self.a = 'a'
self.b = 'b'
self.c = 'c'
class Class2(Class1):
def __init__(self):
super().__init__()
self.d = 'a'
self.e = 'b'
self.f = 'c'
Class2 when receiving Class1 as inheritance, automatically inherits the variables of Class1.
Now I would like to do the same and take these other variables to my MainClass.
I managed to do some things by assigning it to a specific variable like self.values (eg: self.values.a), however, I need these variables to be inside the main class for access. (eg: self.a)
Another way that worked was, doing this workaround: `self.dict.update(self.Class2.dict)
However, I am not convinced of the method. I would like to know if there is a better way to "inherit" this subclass in my main class. Is there any way using something like super().__init__() or something like that to accept my subclass?
Thanks!
What about if instead of inheritance you use composition, by this I mean creating an instance of Class2 in you constructor (init) method inside your main class, something like this:
# Define Class1 and Class2 at global scope
class Class1():
def __init__(self):
self.a = 'a'
self.b = 'b'
self.c = 'c'
class Class2(Class1):
def __init__(self):
super().__init__()
self.d = 'a'
self.e = 'b'
self.f = 'c'
class MainClass():
def __init__(self, *args, **kwargs):
self.class_2 = Class2(*args, **kwargs)
def some_function(self):
some_operation = self.class_2.a * self.class_2.b
# Now you can access class2 variables like this (self.class_2.some_variable)
UPDATE
Whay did you nested your classes inside your main class, can't you define them at global scope?
De-indent Class1 and Class2 so that they're no longer inside MainClass. Then MainClass can inherit either of them.
class Class1:
def __init__(self):
self.a = 'a'
self.b = 'b'
self.c = 'c'
class Class2(Class1):
def __init__(self):
super().__init__()
self.d = 'a'
self.e = 'b'
self.f = 'c'
class MainClass(Class2):
def __init__(self):
super().__init__()
self.teste = 'abcdefg'
Related
I have a class and a sub-class, I'd like to pass the whole of the self of the class to the sub-class. I can pass self over to the new class explicitly easily enough, e.g.
class foo:
def __init__(self, a, b):
self.a = a
self.b = b
self.c = 'foo'
def foo_method(self):
print('a foo method')
class bar(foo):
def __init__(self, foo_object):
self.a = foo_object.a
self.b = foo_object.b
self.c = foo_object.c
def bar_method(self):
print('a bar method')
foo_object = foo(a = 'a', b = 'b')
bar_object = bar(foo_object)
bar_object.a
Is there a more succinct way to pass these over? Something like:
class bar(foo):
def __init__(self, foo_object):
self = self.foo_object
Update:
Thanks https://stackoverflow.com/users/10104112/bastien-antoine, the following solution worked:
class bar(foo):
def __init__(self, foo_object):
self.__dict__ = foo_object.__dict__.copy()
def bar_method(self):
print('a bar method with ' + str(self.c))
Have you tried the copy builtins library?
Otherwise I think you can easily implement your own .copy() method that would copy the values from the old object __dict__ to the new one. Something like this:
class MyObject:
a = None
def set_default_values(self):
self.a = 1
def copy(self, old):
if type(self) == type(old):
self.__dict__ = old.__dict__.copy()
else:
raise TypeError('Wrong type')
if __name__ == "__main__":
obj_1 = MyObject()
print(obj_1.a)
obj_1.set_default_values()
print(obj_1.a)
obj_2 = MyObject()
print(obj_2.a)
obj_2.copy(obj_1)
print(obj_2.a)
Note that I've added a type checking to be sure that you copy attributes that would exist otherwise, but I think simply self.__dict__ = old.__dict__.copy() would work fine, thought you might end up with attributes you might not suppose to have in the new object.
Hope this helps!
I think that you can do that with
class bar(foo):
def __init__(self):
super(bar, self).__init__()
with this code, you ran the init function for the subclass
Is it possible to combine the two lists by calling it from class B using the method I defined in the later class so that the results I may have are 1,2,3,4,5,6?
class A(object):
def __init__(self):
self.container = [1,2,3]
class B(A):
def __init__(self):
self.ano_containter = [4,5,6]
def join_lists(self):
for x in self.ano_containter:
print(x)
Why not just concatenate them?
class B(A):
def __init__(self):
super(A, self).__init__() # make sure you initialize your parent class properly
self.ano_container = [4,5,6]
def join_lists(self):
return self.container + self.ano_container # or print them if you wish
In python, I'm creating an object inside a class:
class A:
def __init__(self):
self.one = 1
self.two = B()
Now I define class B, and I want to access self.one from inside B()
class B()
def __init__(self):
self.three = "hello"
# here I want to change self.one from class A to self.one + 1
# how to do it without doing self.two = B(self.one) on class A
# definition?
something = A()
is there a way to reference the parent object property, or do we have to pass the value when creating the object ?
A is not a parent object, parent object is the object from which you inherit. B has no knowledge about A, you have to modify your classes structure, for example by passing reference to parent in B's constructor (which you say you do not want to do, althouth it is not entirely clear what do you mean by "without doing self.two = B(self.one)", as this would pass copy of self.one, not a reference, but this is the way to do it)
class A:
def __init__(self):
self.one = 1
self.two = B(self)
class B()
def __init__(self, parent):
self.three = "hello"
self.parent = parent
print self.parent.one # or do whatever you want with it
If you really have to do this, you can use introspection, but this is ugly, hacky, bad way of achieving the result
import inspect
class A():
def __init__(self):
self.one = 1
self.two = B()
class B():
def __init__(self):
self.three = "hello"
self.parent = inspect.currentframe().f_back.f_locals['self']
print self.parent.one
Class BigClassA:
def __init__(self):
self.a = 3
def foo(self):
self.b = self.foo1()
self.c = self.foo2()
self.d = self.foo3()
def foo1(self):
# do some work using other methods not listed here
def foo2(self):
# do some work using other methods not listed here
def foo3(self):
# do some work using other methods not listed here
Class BigClassB:
def __init__(self):
self.b = # need value of b from BigClassA
self.c = # need value of c from BigClassA
self.d = # need value of d from BigClassA
def foo(self):
self.f = self.bar()
def bar(self):
# do some work using other methods not listed here and the value of self.b, self.c, and self.d
Class BigClassC:
def __init__(self):
self.b = # need value of b from BigClassA
self.f = # need value of f from BigClassB
def foo(self):
self.g = self.baz()
def baz(self):
# do some work using other methods not listed here and the value of self.b and self.g
Question:
Basically I have 3 classes with lots of methods and they are somewhat dependent as you can see from the code. How do I share the value of instance variables self.b, self.c, self.d from BigClassA to BigClassB?
nb: these 3 classes can not be inherited from each other, since it does not make sense.
What I have in mind, is just to combine all methods into a super big class. But I don't feel this is a right way to do it.
You are correct, in your case inheritance does not make sense. But, how about explicitly passing the objects during the instantiation. This would make a lot of sense.
Something like:
Class BigClassA:
def __init__(self):
..
Class BigClassB:
def __init__(self, objA):
self.b = objA.b
self.c = objA.c
self.d = objA.d
Class BigClassC:
def __init__(self, objA, objB):
self.b = objA.b # need value of b from BigClassA
self.f = objB.f # need value of f from BigClassB
While instantiating, do:
objA = BigClassA()
..
objB = BigClassB(objA)
..
objC = BigClassC(objA, objB)
Why does c.print_a() output 'B'?
class A(object):
def __init__(self):
self.some_name = 'A'
def print_a(self):
print self.some_name
class B(object):
def __init__(self):
self.some_name = 'B'
def print_b(self):
print self.some_name
class C(A, B):
def __init__(self):
A.__init__(self)
B.__init__(self)
if __name__ == '__main__':
c = C()
c.print_a()
class A(object):
def __init__(self, some_name='A'):
self.some_name = some_name
def print_a(self):
print self.some_name
class B(object):
def __init__(self, some_name='B'):
self.some_name = some_name
def print_b(self):
print self.some_name
class C(A, B):
def __init__(self):
A.__init__(self, some_name='AAAAA')
B.__init__(self, some_name='BBBBB')
if __name__ == '__main__':
c = C()
c.print_a()
You only have a single object here; the some_name property is shared between methods from all inherited classes. You call A.__init__, which sets it to A, then B.__init__, which changes it to B.
Also note that you're calling base methods incorrectly; use super:
class A(object):
def __init__(self):
self.some_name = 'A'
super(A, self).__init__()
def print_a(self):
print self.some_name
class B(object):
def __init__(self):
self.some_name = 'B'
super(B, self).__init__()
def print_b(self):
print self.some_name
class C(A, B):
def __init__(self):
super(C, self).__init__()
if __name__ == '__main__':
c = C()
c.print_a()
There's only one self, and you're overwriting its some_name in B.__init__. Maybe you're used to C++, where there would be two separate fields, A.some_name and B.some_name. This concept doesn't apply to Python, where attributes are created dynamically on assignment.
Say you want C to set names for some objects of types A and B and later calling some print_a and print_b methods on objects of type C get these names back ?
You can get this type of behavior using C++ inheritance model, but python model is very different. Only one object with one set of fields. If you want the C++ behavior, the simplest way is probably to declare subobjects (and it looks like a common abuse of inheritance over composition).
Looks like you are trying to do something like below:
class Printable(object):
def __init__(self, name):
self.name = name
def myprint(self):
print self.name
class C(object):
def __init__(self):
self.a = Printable('A')
self.b = Printable('B')
def print_a(self):
self.a.myprint()
def print_b(self):
self.a.myprint()
if __name__ == '__main__':
c = C()
c.print_a()