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)
# ...
Related
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>
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__()
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 need to override __import__ function in python when I dynamically import a derived class. (I only have access to the base class code). For example:
Servers=[]
class ServerBase(object):
name='' #name of the specific server class, for each server class
def __init__(self):
self.connected = False
self.name = self.__class__.__module__.capitalize()
Servers.append(self)
When a derived class is imported I need to call __init__ of the base class to add it to Servers[] list, so when in the main module I call:
__import__('DerivedClassName')
Base __init__ will be called
I ended up metaclassing the Servers class:
Servers=[]
''' Servers Metaclass that handles addition of servers to the list '''
class MetaServer(type):
def __init__(self, name, bases, attrs):
self.name = name.capitalize()
Servers.append(self)
super(MetaServer, self).__init__(name, bases, attrs)
class ServerBase:
__metaclass__ = MetaServer
name='' #name of the specific server class, for each server class
def __init__(self):
self.connected = False
That way every time a derived class was imported meta-init got called.
Exactly what I wanted.
Thanks #MartijnPieters
I am trying to understand a certain OAuth2/web2py integration, but some quirks in the python class model are making it difficult for me to grasp. Specifically, I have this web2py controller:
def google():
if 'state' in request.vars and request.vars.state == 'google':
session.state = request.vars.state
person = Person("google")
print person.render()
return person.render()
So we have are using the Person class here. The implementation is like this:
class Person(Base):
No __init__ is present in the Person class. The Base class has an __init__ function:
class Base(object):
def __init__(
self,
hooks=[],
theme="%(name)s/",
view="app/generic",
meta=None,
context=None
):
from gluon.storage import Storage
self.meta = meta or Storage()
self.context = context or Storage()
self.context.alerts = []
self.context.content_types = []
self.context.categories = []
self.context.menus = []
self.context.internalpages = []
self.theme = theme
self.view = view
# hooks call
self.start()
self.build()
self.pre_render()
# aditional hooks
if not isinstance(hooks, list):
hooks = [hooks]
for hook in hooks:
self.__getattribute__(hook)()
So my questions is as follows: If Person is not explicitly calling Base.__init__, will it be called at all?
Or, to make it more general: will the base class __init__ function be called if the derived class has no __init__ function? And if the derived class has an __init__ function but does not explicitly call the base class __init__ function?
If the derived class has no __init__ function, the parent's class __init__ will be inherited and called.
If the derived class has an __init__ function which does not call the parent's __init__, the parent's __init__ will not be called.