I just noticed some unintended behaviour then tested it in an interpretor (Python 3.5.3):
>>> class SomeClass:
... def __init__(self):
... print("nothing important")
...
>>> a = SomeClass()
nothing important
>>> class SomeOtherClass(SomeClass):
... pass
...
>>> b = SomeOtherClass()
nothing important
>>>
I thought you needed to directly call the parents __init__(). What is the simplest way to write or instantiate the child class such that it does not run the __init__() from the parent class?
You can by defining an __init__ method in the child class:
class SomeOtherClass(SomeClass):
def __init__(self):
pass
I want some methods from the parent, just not that the init runs
Then your design is wrong. If you only care about code reuse but not proper subtyping (as defined by Liskov), proper designs are either composition/delegation or (probably the best in your case) multiple inheritance with mixin classes:
class CommonMixin():
def method1(self):
pass
def method2(self):
pass
class SomeClass(CommonMixin, SomeBaseClass):
def __init__(self):
print("nothing important")
class SomeOtherClass(CommonMixin, SomeOtherBaseClass):
pass
Related
I need to deliver something like this in my program
class the_class_name(Parent):
the_attribute = self.parent_class_method()
#the parent class method will return a value
#but I cannot use self here since there's no self
How can I carry this out? Is there any other alternative that can do the job for me?
I have tried using __init__ like this:
def __init__(self):
Parent.__init__(self)
self.attribute = self.the_method()
But then I have problem creating the object, it won't receive any parameters that the Parent class normally receives anymore
Sounds like you are looking for __init__:
class TheClassName(Parent):
def __init__(self):
# Set attribute to the result of the parent method
self.attribute = super(TheClassName, self).the_method()
EDIT
If your parent class has parameters in it's own __init__ function, include them in the child class:
class Parent(object):
def __init__(self, foo, bar):
...
#classmethod
def the_method(cls):
...
class TheClassName(Parent):
def __init__(self, foo, bar):
super(TheClassName, self).__init__(foo, bar)
self.attribute = super(TheClassName, self).the_method()
I don't quite understand why you don't just call the parent method on your child object when you need the value though.
There is no self at that point of the creation of the subclass, nor is there an instance of the Parent class. That means the only Parent class methods you could call would have to be either static or class methods.
To demonstrate:
class Parent(object):
#staticmethod
def static_method():
return 42
#classmethod
def class_method(cls):
return 43
class TheClassName(Parent):
the_attribute = Parent.static_method()
another_attribute = Parent.class_method()
print(TheClassName.the_attribute) # -> 42
print(TheClassName.another_attribute) # -> 43
You must use class methods, declared with the #classmethod decorator, or a #staticmethod. The #classmethod decorator is preferable so that inheritance is handled correctly, i.e. the method is invoked on the derived class (a bit of a technicality, if you are still learning this).
class Alpha(object):
#classmethod
def method1(cls):
return 'method1 has been called on {}'.format(cls)
class Beta(Alpha):
def __init__(self):
self.myattr = Beta.method1()
print(Beta().myattr)
method1 has been called on class <'__main__.Beta'>
Use
super(ClassName, self).methodname(arg)
inside a method
def child_method(self, arg):
super(ClassName, self).methodname(arg)
You cannot use self outside a method.
I'm trying to inherit attributes from a super class but they are not being initialized correctly:
class Thing(object):
def __init__(self):
self.attribute1 = "attribute1"
class OtherThing(Thing):
def __init__(self):
super(Thing, self).__init__()
print self.attribute1
This throws an error since attribute1 is not an attribute of OtherThing, even though Thing.attribute1 exists. I thought this was the correct way to inherit and extend a super class. Am I doing something wrong? I don't want to create an instance of Thing and use its attributes, I need it to inherit this for simplicity.
You have to give, as argument, the class name (where it is being called) to super():
super(OtherThing, self).__init__()
According to Python docs:
... super can be used to refer to parent classes without naming them
explicitly, thus making the code more maintainable.
so you are not supposed to give the parent class.
See this example from Python docs too:
class C(B):
def method(self, arg):
super(C, self).method(arg)
Python3 makes this easy:
#!/usr/local/cpython-3.3/bin/python
class Thing(object):
def __init__(self):
self.attribute1 = "attribute1"
class OtherThing(Thing):
def __init__(self):
#super(Thing, self).__init__()
super().__init__()
print(self.attribute1)
def main():
otherthing = OtherThing()
main()
I would like to know how to convert parent object that was return by some function to child class.
class A(object):
def __init__():
pass
class B(A):
def functionIneed():
pass
i = module.getObject() # i will get object that is class A
j = B(i) # this will return exception
j.functionIneed()
I cannot change class A. If I could I would implement functionIneed to class A, but it is impossible because of structure of code.
Python does not support "casting". You will need to write B.__init__() so that it can take an A and initialize itself appropriately.
I have a strong suspicion, nay, conviction, that there is something horribly wrong with your program design that it requires you to do this. In Python, unlike Java, very few problems require classes to solve. If there's a function you need, simply define it:
def function_i_need(a):
"""parameter a: an instance of A"""
pass # do something with 'a'
However, if I cannot dissuade you from making your function a method of the class, you can change an instance's class by setting its __class__ attribute:
>>> class A(object):
... def __init__(self):
... pass
...
>>> class B(A):
... def functionIneed(self):
... print 'functionIneed'
...
>>> a = A()
>>> a.functionIneed()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'functionIneed'
>>> a.__class__ = B
>>> a.functionIneed()
functionIneed
This will work as long as B has no __init__ method, since, obviously, that __init__ will never be called.
You said you want to implement something like this:
class B(A):
def functionIneed():
pass
But really what you would be making is something more like this (unless you had intended on making a class or static method in the first place):
class B(A):
def functionIneed(self):
pass
Then you can call B.functionIneed(instance_of_A). (This is one of the advantages of having to pass self explicitly to methods.)
You did not correctly define your classes.
Should be like this:
class A(object):
def __init__(self):
pass
class B(A):
def __init__(self):
super(B,self).__init__()
def functionIneed(self):
pass
Then you can
j=B()
j.fuctionIneed()
as expected
You forgot to refer to the ins
Just thinking outside the box:
Instead of a new class with the function you want, how about just adding the function to the class or instance you already have?
There is a good description of this in
Adding a Method to an Existing Object Instance
How about:
i = module.getObject() # i will get object that is class A
try:
i.functionIneed()
except AttributeError:
# handle case when u have a bad object
Read up on duck typing.
I have this class with an unbound method and a static class inside:
class ClassA():
class Foo():
pass
def getFoo():
return ???.Foo
Now, if I inherit a ClassB from ClassA how do I get ClassB.getFoo() to return ClassB.Foo without explicitly implementing ClassB.getFoo()? Returning super().Foo doesn't work, writing ClassA.Foo doesn't work either obviously.
Your getFoo should be a classmethod:
class ClassA():
class Foo():
pass
#classmethod
def getFoo(cls):
return cls.Foo
Class methods are passed their class as their first argument, similar to how instance methods are passed the instance as the first argument. When you subclass ClassA, the proper class is passed.
Just to add my own thoughts on this: In addition to #Ned Batchelder's answer, you can use static methods to achieve a similar goal.
class ClassA():
class Foo():
def fooTest(self):
print("Hello from {}!".format(self.__name__))
#staticmethod
def getFoo():
return ClassA.Foo
class ClassB(ClassA):
pass
And test with:
>>> Foo = ClassB.getFoo()
>>> foo = Foo()
>>> foo.fooTest()
Hello from Foo!
This to me demonstrates the beauty of the python language - there are usually multiple ways of solving the same problem...
I have the following kind of superclass / subclass setup:
class SuperClass(object):
def __init__(self):
self.do_something() # requires the do_something method always be called
def do_something(self):
raise NotImplementedError
class SubClass(SuperClass):
def __init__(self):
super(SuperClass, self).__init__() # this should do_something
def do_something(self):
print "hello"
I would like the SuperClass init to always call a not-yet-implemented do_something method. I'm using python 2.7. Perhaps ABC can do this, but it is there another way?
Thanks.
Your code is mostly correct, except for the use of super. You need to put the current class name in the super call, so it would be:
super(SubClass, self).__init__()
Since you put in the wrong class name, SuperClass.__init__ wasn't called, and as a result do_something wasn't called either.