Extend Python class's init method - python

I have a BaseClass and an AbstractClass that inherits from the BaseClass. This is the structure I have in place
class BaseClass(object):
def __init__(self, initialize=True):
self.name = 'base_class'
self.start = 0
if initialize:
self.start = 100
class AbstractClass(BaseClass):
def __init__(self):
self.name = 'asbtract_class'
super(BaseClass, self).__init__()
I want to pass the abstract class an initialize parameter that gets transferred to the base class and if True sets the object's start value to 100.
I tried using the super(BaseClass, self).__init__() but the abstract class gets no start attribute. I get an error when I try to access it.
How can I pass a value the initialize argument to the AbstractClass and use the BaseClass's __init__ method to set the start attribute on the AbstractClass.
The code I used
best = BaseClass()
abs = AbstractClass()
abs.start # AttributeError: 'AbstractClass' object has no attribute 'start'

To invoke the constructor of the super class you should use the class name of the sub class and not the super class, i.e.:
class AbstractClass(BaseClass):
def __init__(self):
super(AbstractClass, self).__init__()
self.name = 'abstract_class'
Note also that I changed the order of invoking the constructor of the super class and setting the name attribute. If you set it before calling the super, the attribute would be overridden by the constructor of the super class, which is most likely not what you intended
And as #Sraw pointed out, for python 3 the notation of calling the super no longer requires the referencing of the class name and can be simplified to
class AbstractClass(BaseClass):
def __init__(self):
super().__init__()

Related

how can I get instance list of specific class in python [duplicate]

I wrote a Python module, with several classes that inherit from a single class called MasterBlock.
I want to import this module in a script, create several instances of these classes, and then get a list of all the existing instances of all the childrens of this MasterBlock class. I found some solutions with vars()['Blocks.MasterBlock'].__subclasses__() but as the instances I have are child of child of MasterBlock, it doesn't work.
Here is some example code:
Module:
Class MasterBlock:
def main(self):
pass
Class RandomA(MasterBlock):
def __init__(self):
pass
# inherit the main function
Class AnotherRandom(MasterBlock):
def __init__(self):
pass
# inherit the main function
Script:
import module
a=module.RandomA()
b=module.AnotherRandom()
c=module.AnotherRandom()
# here I need to get list_of_instances=[a,b,c]
Th ultimate goal is to be able to do:
for instance in list_of_instances:
instance.main()
If you add a __new__() method as shown below to your base class which keeps track of all instances created in a class variable, you could make the process more-or-less automatic and not have to remember to call something in the __init__() of each subclass.
class MasterBlock(object):
instances = []
def __new__(cls, *args, **kwargs):
instance = super(MasterBlock, cls).__new__(cls, *args, **kwargs)
instance.instances.append(instance)
return instance
def main(self):
print('in main of', self.__class__.__name__) # for testing purposes
class RandomA(MasterBlock):
def __init__(self):
pass
# inherit the main function
class AnotherRandom(RandomA): # works for sub-subclasses, too
def __init__(self):
pass
# inherit the main function
a=RandomA()
b=AnotherRandom()
c=AnotherRandom()
for instance in MasterBlock.instances:
instance.main()
Output:
in main of RandomA
in main of AnotherRandom
in main of AnotherRandom
What about adding a class variable, that contains all the instances of MasterBlock? You can record them with:
Class MasterBlock(object):
all_instances = [] # All instances of MasterBlock
def __init__(self,…):
…
self.all_instances.append(self) # Not added if an exception is raised before
You get all the instances of MasterBlock with MasterBlock.all_instances (or instance.all_instances).
This works if all base classes call the __init__ of the master class (either implicitly through inheritance or explicitly through the usual super() call).
Here's a way of doing that using a class variable:
class MasterBlock(object):
instances = []
def __init__(self):
self.instances.append(self)
def main(self):
print "I am", self
class RandomA(MasterBlock):
def __init__(self):
super(RandomA, self).__init__()
# other init...
class AnotherRandom(MasterBlock):
def __init__(self):
super(AnotherRandom, self).__init__()
# other init...
a = RandomA()
b = AnotherRandom()
c = AnotherRandom()
# here I need to get list_of_instances=[a,b,c]
for instance in MasterBlock.instances:
instance.main()
(you can make it simpler if you don't need __init__ in the subclasses)
output:
I am <__main__.RandomA object at 0x7faa46683610>
I am <__main__.AnotherRandom object at 0x7faa46683650>
I am <__main__.AnotherRandom object at 0x7faa46683690>

Inheritance in Python for variable that's not parameter

In Python, I'm using inheritance for a class. The initial init for the main parent class is below:
def __init__(self, Date = None):
self.Date = Date
self.DatabaseClass = Database()
self.Connection = self.DatabaseClass.databaseConnection()
I've inherited the class into the child class, but am wondering what the correct approach would be to inherit DatabaseClass and Connection variables, i.e., what would be in def __init__?
You just need to call the inherited __init__ method from your own class's __init__ method.
class Child(Parent):
def __init__(self, Date=None, other, arguments):
super().__init__(Date)
# ...

How to find a abstract class instance and call an instance method based on the instance' attributes?

I want to call an instance method but the instance itself is unknown to me. The instance can be identified by it's attributes which I know, e.g. a unique name.
Here're my class definitions and instantiation:
from abc import ABCMeta
class MyAbstractClass():
__metaclass__ = ABCMeta
def do_something(self):
print(self.name)
class MyFirstClass(MyAbstractClass):
def __init__(self):
self.name = 'first'
class MySecondClass(MyAbstractClass):
def __init__(self):
self.name = 'second'
my_first_class_instance = MyFirstClass()
my_second_class_instance = MySecondClass()
What I want to achive is a look-up by name:
def myPrint('first'):
# should call my_first_class_instance.do_something()
def myPrint('second'):
# should call my_second_class_instance.do_something()
I looked into the built-in class methods but didn't find a way to manage the parametrization of the calls.
What's a good way of doing this?

Refer to a class outside its method?

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.

Can't access parent member variable in Python

I'm trying to access a parent member variable from an extended class. But running the following code...
class Mother(object):
def __init__(self):
self._haircolor = "Brown"
class Child(Mother):
def __init__(self):
Mother.__init__(self)
def print_haircolor(self):
print Mother._haircolor
c = Child()
c.print_haircolor()
Gets me this error:
AttributeError: type object 'Mother' has no attribute '_haircolor'
What am I doing wrong?
You're mixing up class and instance attributes.
print self._haircolor
You want the instance attribute, not the class attribute, so you should use self._haircolor.
Also, you really should use super in the __init__ in case you decide to change your inheritance to Father or something.
class Child(Mother):
def __init__(self):
super(Child, self).__init__()
def print_haircolor(self):
print self._haircolor

Categories