I'm using wxpython to generate a GUI. The structure of the program I'm doing is shown below. I have a class for each section of the GUI (class1 and class2). I'm using the Panel class to create these sections. class1 and class2 are derived from another class (the Group class). I want to access the methods of a derived class from the other derived class on the fly. So when I'm in classA.method1() I want to call classB.method3(). what is the best way to do that?
class Panel(wx.Panel):
def __init__(self, parent):
class1 = ClassA()
class2 = ClassB()
class Group(wx.Panel):
def __init__(self, parent, name):
.
.
.
class ClassA(Group):
def method1(self):
....
def method2(self):
....
class ClassB(Group):
def method3(self):
....
def method4(self):
....
I's assuming you want to call the class method, not the method of an instance of that class.
From ClassA.method1(), ClassB be should be a global, so all you have to do is:
class ClassA(Group):
def method1(self):
classB.method3(someclass)
Now all you have to do is figure out what you want to put in for 'someclass'. If method3 never uses 'self' then just pass it None. If ClassA is compatible, then you can pass it 'self'. Otherwise, you need to pass it an instance of ClassB.
Related
This is probably very simple question. In a child class, which is inherited from two parent classes, I can't access variable from second parent class using super(). Here is my code:
class Core:
def __init__(self):
self.a_from_Core = 7
class Extra:
def __init__(self):
self.b_from_Extra = 90
class Trash(Core, Extra):
def __init__(self):
super().__init__()
print(self.a_from_Core) # working
print(self.b_from_Extra) # does not work
trashcan = Trash()
And here is error:
AttributeError: 'Trash' object has no attribute 'b_from_Extra'
What am I doing wrong?
Python uses "cooperative" multiple inheritance (https://rhettinger.wordpress.com/2011/05/26/super-considered-super/)
which kinda means all classes involved in the inheritance need to agree to play.
For single inheritance, it just works -- which is what lulled you into thinking it would work for multiple.
You need to add calls to super().__init__() in all classes, for example
class Core:
def __init__(self):
self.a_from_Core = 7
super().__init__() # added
class Extra:
def __init__(self):
self.b_from_Extra = 90
super().__init__() # added
class Trash(Core, Extra):
def __init__(self):
super().__init__()
print(self.a_from_Core)
print(self.b_from_Extra) # works!
trashcan = Trash()
You are inheriting from two classes, according to MRO, your first father is Core and your second father is Extra.
So when you call super, the __init__ in Core is called and the __init__ in the Extra is not called, so you don't have b_from_Extra.
As in MRO of Trash you have something like: [..., Core, Extra], if you call super in Core, the method in Extra would be called.
So you can do the following :
class Core:
def __init__(self):
self.a_from_Core = 7
super().__init__()
...
You can read about MRO.
I am experimenting with python object orientated programming. Of course I learned about inheritence and so on, but this question is very specific and I couldn't find the answer anywhere yet.
Let's say we have a class class mainClass:. In this class there is a function def func(self):. And within this function func() I want to use two custom classes. Can I and how can I use the first custom class within the second one? (Here's a example)
class custom1:
def func1(self):
#do something
class custom2:
def func2(self):
#call function func1 from class custom1 without creating another instance
class mainClass:
def func(self):
obj1 = custom1()
obj2 = custom2()
obj2.func2()
Like I said I don't want to create a second instance of custom1 within custom2. Only the one in mainClass.
Thanks for your answers :)
what about passing it via the constructor of the first class?
class custom1:
def func1(self):
#do something
class custom2:
def __init__(self, obj1):
self._obj1 = obj1
def func2(self):
self._obj1.func1()
class mainClass:
def func(self):
obj1 = custom1()
obj2 = custom2(obj1)
obj2.func2()
I'm trying to define self.data inside a class inheriting from a class
class Object():
def __init__(self):
self.data="1234"
class New_Object(Object):
# Code changing self.data here
But I ran into an issue.
class Object():
def __init__(self):
self.data="1234"
So I have the beginning class here, which is imported from elsewhere, and let's say that the class is a universal one so I can't modify the original at all.
In the original, the instance is referred to as "self" inside the class, and it is defined as self inside the definition __init__.
class New_Object(Object):
# Code changing self.data here
So if I wanted to inherit from the class Object, but define self.data inside New_Object, I thought I would have to define __init__ in New_Object, but this overrides the __init__ from New_Object
Is there any way I could do this without copypasting the __init__ from Object?
You use super to call the original implementation.
class New_Object(Object):
def __init__(self):
super(NewObject, self).__init__()
self.info = 'whatever'
That's what super is for:
class NewObject(Object):
def __init__(self):
super(NewObject, self).__init__()
# self.data exists now, and you can modify it if necessary
You can use super().__init__() to call Object.__init__() from New_Object.__init__().
What you would do:
class Object:
def __init__(self):
print("Object init")
self.data = "1234"
class New_Object(Object):
def __init__(self):
print("calling super")
super().__init__()
print("data is now", self.data)
self.data = self.data.split("3")
o = New_Object()
# calling super
# Object init
# data is now 1234
Note that you do not have to give any arguments to super(), as long as you are using Python 3.
The answer is that you call the superclass's __init__ explicitly during the subclass's __init__. This can be done either of two ways:
Object.__init__(self) # requires you to name the superclass explicitly
or
super(NewObject, self).__init__() # requires you to name the subclass explicitly
The latter also requires you to ensure that you're using "new-style" classes: in Python 3 that's always the case, but in Python 2 you must be sure to inherit from the builtin object class. In Python 3 it can actually be expressed even more simply:
super().__init__()
Personally, in most of my code the "disadvantage" of having to name the superclass explicitly is no disadvantage at all, and Object.__init__() lends transparency since it makes it absolutely clear what is being called. This is because most of my code is single-inheritance only. The super route comes into its own when you have multiple inheritance. See What does 'super' do in Python?
Python 2 example:
class Object(object):
def __init__(self):
self.data = "1234"
class NewObject:
def __init__(self):
# subclass-specific stuff
super(NewObject, self).__init__()
# more subclass-specific stuff
I know this question might be pointless but there is a reason why I am looking to do it this way. I want to call something exactly opposite to super()
class A(object):
def use_attack(self, damage, passive, spells):
#do stuff with passed parameters
#return something
def use_spell(self, name , enemy_hp):
#other code
if name == 'Enrage':
#call child method use_attack right here
class B(A):
def use_attack(self):
#bunch of code here
return super(B, self).use_attack(damage, passive, spells)
def use_spell(self, name , enemy_hp):
return super(B , self).use_attack(name ,enemy_hp)
b = B()
b.use_spell('Enrage', 100)
I have a bunch of code in class B's use_attack() method that I would not like to replicate in the parent method of use_spell() .
I would like to call the child method use_attack() in the line indicated.
I have a bunch of code in class B's use_attack() method that I would not like to replicate in the parent method of use_spell() .
Then factor that code out into a method on the parent class. This is exactly what inheritance is for. Children inherit code from parents, not the other way around.
From the python docs: "The mro attribute of the type lists the method resolution search order used by both getattr() and super()"
https://docs.python.org/3/library/functions.html#super
This should help shed some light on Inheritance and Method Resolution Order (mro).
class Foo(object):
def __init__(self):
print('Foo init called')
def call_child_method(self):
self.child_method()
class Bar(Foo):
def __init__(self):
print('Bar init called')
super().__init__()
def child_method(self):
print('Child method called')
bar = Bar()
bar.call_child_method()
class Something(object):
our_random = Something.random_thing
#staticmethod
def random_thing():
return 4
Of course, this doesn't work, becauese Something doesn't exist when I attempt to call its method. Nor does this:
class Something(object):
our_random = random_thing
#staticmethod
def random_thing():
return 4
I've "solved" this by Just placing random_thing()'s definition above the class, but I find this messy.
Call it in the .__init__() initializer then:
class Something(object):
def __init__(self):
self.our_random = Something.random_thing()
or call the static method after you defined it, but are still defining the class; because it is a static method, you'd have to access it through the __func__ attribute:
class Something(object):
#staticmethod
def random_thing():
return 4
our_random = random_thing.__func__()
If you didn't mean to call it, just create a copy of the method with a different name, just do so after you defined it:
class Something(object):
#staticmethod
def random_thing():
return 4
our_random = random_thing # our_random as an alias for random_thing
The class body is executed as a function, with the local namespace of the function then forming the class attributes. So, like a function, if you want to refer to other objects you need to make sure they are defined first.
class Something(object):
#staticmethod
def random_thing():
return 4
our_random = random_thing
Class definitions create a namespace, so you can refer to other names (class attributes) within the class body without needing to access them through the class.