I'm wondering if what I have created is valid and 'nice' - or actually a mess
I have a class that has a method which calls a function in another class. However, it is only 'visible' by the fact these two classes are brought together in another child class. If somebody is just looking at this method they may wonder where this is actually located - it is not clear.
Am I doing something wrong here, or something common in Python?
class A():
def __init__(self):
pass
def register_urc(self, text):
print(text)
class B(A):
def __init__(self):
A.__init__(self)
class C():
def __init__(self):
self.register_urc("Hello World")
class Z(B, C):
def __init__(self):
B.__init__(self)
C.__init__(self)
def test(self):
print("finished")
z = Z()
z.test()
What I get is:
Hello World
finished.
I assume this is working because I'm referencing Z's 'self' and passing that down to all other classes.
Related
I am getting an error when making a third class that inherits the first two classes' attributes. The first class's function will be go through but when accessing the second class's function I am gettting an error:
class3' object has no attribute 'othernum
Here is the code:
class class1():
def __init__(self):
self.number = 10000
def getNum(self):
return self.number
class class2():
def __init__(self):
self.othernum = 1111
def displaynum(self):
return self.othernum
class class3(class1, class2):
pass
newperson = class3()
print(newperson.getNum())
print(newperson.displaynum())
Found the answer.
class class3(class1, class2):
def __init__(self):
class1.__init__(self)
class2.__init__(self)
The answer presented by #Ishaan Sathaye is indeed correct. But be aware that there are several mechanisms for initializing base classes in a multiple inheritance hierarchy. See Calling parent class init with multiple inheritance, what's the right way?, in particular the section with heading All base classes are designed for cooperative inheritance.
So, if your 3 classes were designed for cooperative inheritance, we would have:
class class1():
def __init__(self):
super().__init__()
self.number = 10000
def getNum(self):
return self.number
class class2():
def __init__(self):
super().__init__()
self.othernum = 1111
def displaynum(self):
return self.othernum
class class3(class1, class2):
def __init__(self):
super().__init__()
newperson = class3()
print(newperson.getNum())
print(newperson.displaynum())
I have a few classes set up that hold values for an application. I'd like to import them into the same class, however, the values in the last class are being ignored. Here is a simple example.
class A:
def __init__(self):
self.testA = 'A'
class B:
def __init__(self):
self.testB = 'B'
class C(A, B):
def __init__(self):
super().__init__()
print(self.testA)
print(self.testB)
test = C()
The above will work only if I do not include the print(self.testB) the variable in class 'B'. I'd like to access the data from Class B as well. How? Thank you.
I'm having a problem with multiple inheritance that I can't seem to figure out. Here is a very abstracted minimal example that reproduces my error (my code is much more complex than this).
class Thing(object):
def __init__(self, x=None):
self.x = x
class Mixin(object):
def __init__(self):
self.numbers = [1,2,3]
def children(self):
return [super().__init__(x=num) for num in self.numbers]
class CompositeThing(Mixin, Thing):
def __init__(self):
super().__init__()
def test(self):
for child in self.children():
print(child.x)
obj = CompositeThing()
obj.test()
Per this, I expect the children() method to return a list of Things built up from self.numbers. Instead, I get TypeError: super(type, obj): obj must be an instance or subtype of type. Incidentally, the same thing happens if I don't call the constructor and allow children to return super() 3 times (i.e., the uninstantiated superclass). Any ideas why this might be happening?
Thanks in advance!
In line 9 of your code, it looks like you are trying to call __init__ of object. I am assuming you meant to have Mixin inherit from Thing.
class Thing(object):
def __init__(self, x=None):
self.x = x
class Mixin(Thing):
def __init__(self):
self.numbers = [1,2,3]
def children(self):
return [super().__init__(x=num) for num in self.numbers] # Now calls Thing.__init__ instead of object.__init__
class CompositeThing(Mixin, Thing):
def __init__(self):
super().__init__()
def test(self):
for child in self.children():
print(child.x)
obj = CompositeThing()
obj.test()
Actually, I figured it out. There were two problems: (1) super() doesn't work as expected inside comprehensions because comprehensions in Py3 have their own scope - this was causing the TypeError I was experiencing. (2) What I was really trying to do was create a new instance of the parent, rather than calling a method from the parent. I have posted a new question for just the latter problem for clarity.
I am trying to create a wrapper class in Python with the following behaviour:
It should take as an argument an existing class from which it should inherit all methods and attributes
The wrapper class methods should be able to use Python super() to access methods of the superclass (the one passed as an argument)
Because of my second requirement I think the solution here will not suffice (and in any case I am having separate issues deepcopying some of the methods of the superclass' I am trying to inherit from).
I tried this but it's not correct...
class A:
def shout(self):
print("I AM A!")
class B:
def shout(self):
print("My name is B!")
class wrapper:
def __init__(self, super_class):
## Some inheritance thing here ##
# I initially tried this but no success...
super(super_class).__init__() # or similar?
def shout(self):
print('This is a wrapper')
super().shout()
And this is the behaviour I require...
my_wrapper = wrapper(A)
my_wrapper.shout()
# Expected output:
# > This is a wrapper
# > I AM A
my_wrapper = wrapper(B)
my_wrapper.shout()
# Expected output:
# > This is a wrapper
# > My name is B!
Is inheritance the correct approach here, if so am I sniffing in the right direction? Any help is appreciated, thanks :)
Edit for context:
I intend to build multiple wrappers so that all of my ML models have the same API. Generally, models from the same package (sklearn for example) have the same API and should be able to be wrapped by the same wrapper. In doing this I wish to modify/add functionality to the existing methods in these models whilst keeping the same method name.
If wrapper has to be a class then a composition solution would fit much better here.
Keep in mind that I turned the shout methods to staticmethod because in your example you pass the class to wrapper.shout, not an instance.
class A:
#staticmethod
def shout():
print("I AM A!")
class B:
#staticmethod
def shout():
print("My name is B!")
class wrapper:
def __init__(self, super_class):
self._super_class = super_class
def __getattr__(self, item):
try:
return self.__dict__[item].__func__
except KeyError:
return self._super_class.__dict__[item].__func__
def a_wrapper_method(self):
print('a wrapper attribute can still be used')
my_wrapper = wrapper(A)
my_wrapper.shout()
my_wrapper = wrapper(B)
my_wrapper.shout()
my_wrapper.a_wrapper_method()
Outputs
This is a wrapper
I AM A!
This is a wrapper
My name is B!
a wrapper attribute can still be used
So I went for a function in the end. My final solution:
class A:
def shout(self):
print("I AM A!")
class B:
def shout(self):
print("My name is B!")
def wrap_letter_class(to_wrap):
global letterWrapper
class letterWrapper(to_wrap):
def __init__(self):
super().__init__()
def shout(self):
print('This is a wrapper')
super().shout()
def __getstate__(self):
# Add the wrapper to global scope before pickling
global letterWrapper
letterWrapper = self.__class__
return self.__dict__
return letterWrapper()
Which produces the desired behaviour...
In [2]: wrapped = wrap_letter_class(A)
In [3]: wrapped.shout()
This is a wrapper
I AM A!
In [4]: wrapped = wrap_letter_class(B)
In [5]: wrapped.shout()
This is a wrapper
My name is B!
Something not mentioned in my initial question was that I intended to pickle my custom class, this is not possible if the class is not defined in the global scope, hence the __getstate__ and global additions.
Thanks!
I'm not the strongest pillar when it comes to class inheritance, so here goes my rather silly question. Following the code below, I would logically assume that after the 'super' call, the pointer arrives at self.example() which would in turn refer to the 'example' method in the same class and value 20 will be printed.
class A(object):
def __init__():
self.example()
def example(self):
print(20)
class B(A):
def __init__():
super().__init__()
def example(self):
print(10)
x = B()
Result : 10
This clearly isn't the case and 10 is printed instead. Could someone please shed some light on the mysterious world of class inheritance.
class A(object):
def __init__():
self.example()
def example(self):
print(20)
class B(A):
def __init__():
super().__init__()
x = B()
x.example()
Look for this, at example.
When you inherit B, from A, then method example is inheritated to B, you not must rewrite this to B. Of course still you can write this method for B, then you will override 'A' method, for objects of class B.
You also can use one class to Inheritance with many others:
class Base(object):
def __init__(self):
print("Base created")
class ChildA(Base):
def __init__(self):
Base.__init__(self)
class ChildB(Base):
def __init__(self):
super(ChildB, self).__init__()
ChildA()
ChildB()
ChildB have another call which is equivalent to that used in example above.