I have a question about the instantiation process of a child class with multiple inheritance from parent class A without arg and parent class B with kwargs respectively.
In the code below, I don't know why ParentB's set_kwargs()method is executed while ParentA is inited when a Child instance is created.
(Expecially, why does the results show Child receive {}? How can I avoid this results?)
Any help would be really appreciated.
Thanks!
class GrandParent:
def __init__(self):
print(f"{self.__class__.__name__} initialized")
class ParentA(GrandParent):
def __init__(self):
super().__init__()
class ParentB(GrandParent):
def __init__(self, **kwargs):
super().__init__()
self.set_kwargs(**kwargs)
def set_kwargs(self, **kwargs):
print(f"{self.__class__.__name__} receive {kwargs}")
self.content = kwargs.get('content')
class Child(ParentA, ParentB):
def __init__(self, **kwargs):
ParentA.__init__(self)
ParentB.__init__(self, **kwargs)
c = Child(content = 3)
results:
Child initialized
Child receive {}
Child initialized
Child receive {'content': 3}
For most cases of multiple inheritance, you will want the superclass methods to be called in sequence by the Python runtime itself.
To do that, just place a call to the target method in the return of super().
In your case, the most derived class' init should read like this:
class Child(ParentA, ParentB):
def __init__(self, **kwargs):
super().__init__(self, **kwargs)
And all three superclasses __init__ methods will be correctly run. Note that for that to take place, they have to be built to be able to work cooperatively in a class hierarchy like this - for which two things are needed: one is that each method in any of the superclasses place itself a class to super().method()- and this is ok in your code. The other is that if parameters are to be passed to these methods, which not all classes will know, the method in each superclass should extract only the parameters it does know about, and pass the remaining parameters in its own super() call.
So the correct form is actually:
class GrandParent:
def __init__(self):
print(f"{self.__class__.__name__} initialized")
class ParentA(GrandParent):
def __init__(self, **kwargs):
super().__init__(**kwargs)
class ParentB(GrandParent):
def __init__(self, **kwargs):
content = kwargs.pop('content')
super().__init__(**kwargs)
self.set_kwargs(content)
def set_kwargs(self, content):
print(f"{self.__class__.__name__} receive {content}")
self.content = content
class Child(ParentA, ParentB):
def __init__(self, **kwargs):
super.__init__(**kwargs)
c = Child(content = 3)
The class which will be called next when you place a super() call is calculated by Python when you create a class with multiple parents - so, even though both "ParentA" and "ParentB" inherit directly from grandparent, when the super() call chain bubbles up from "Child", Python will "know" that from within "ParentA" the next superclass is "ClassB" and call its __init__ instead.
The algorithm for finding the "method resolution order" is quite complicated, and it just "works as it should" for most, if not all, usecases. It's exact description can be found here: https://www.python.org/download/releases/2.3/mro/ (really - you don't have to understand it all - there are so many corner cases it handles - just get the "feeling" of it.)
I have searched all the related this stackoverflow question but its not satisfied my issue.
BaseHandler.py
class BaseHandler(object):
def __init__(self, rHandler, path, param):
self._rHandler = rHandler
self._server = self._rHandler.server
self._path = path
self._param = param
def _getElement(self, name):
return name + "append"
MyClass.py
class MyClass(BaseHandler.BaseHandler):
def getA(self):
print "Some info"
def getB(self):
el = self._getElement("T") #baseclass method
print ebl
I wanted to call getB from the below class.
RThread.py
import MyClass
class RThread(object):
def someMethod(self):
clr = MyClass.MyClass
clr.getB()
I am getting the following error:
TypeError: unbound method getB() must be called with MyClass instance as first argument (got nothing instead)
When I try the following:
clr = MyClass.MyClass()
I am getting the following error:
init() takes exactly 4 arguments (1 given)
So kindly help me how to call this method from different class.
You need to instantiate the class in order to call a method on it.
def someMethod(self):
clr = MyClass.MyClass(*args)
clr.getB()
In the case you want the method to be callable from the class you need to use either #staticmethod or #classmethod
#staticmethod
def getB():
return self._getElement("T")
However, you are using the self. notation which requires an instance. So you would need to flag the _getElement method with #staticmethod as well. Static methods do not have access to the parent class. You can use the #classmethod decorator to do so.
#classmethod
def getB(cls):
return cls._getElement("T")
You're not calling the method correctly; you need to create an object. This is how you create an object, which is what you were doing, except you weren't passing in enough parameters.
clr = MyClass.MyClass()
Since MyClass inherits from BaseHandler and you did not override its constructor, you're using the constructor from BaseHandler, which has four arguments, one of which is self.
def __init__(self, rHandler, path, param):
...
So, try something like this:
clr = MyClass.MyClass(arg1, arg2, arg3)
clr.getB()
I'm trying to subclass a class from another python script.
I've done the following when subclassing from within the same file, and it works.
widge.py
class widget(object):
def __init__(self,bob):
#do something
class evenWidgetier(widget):
def __init__(self, bob):
widget.__init__(self,bob)
#do something
But once I add in inheritance from another file..
superWidget.py
import widge
class superWidgety(widge.evenWidgetier):
def __init__(self, bob):
widge.widget.__init__(self,bob)
#do something
I get an error:
unbound method __init__() must be called with widget instance as first argument
Is there a way I can subclass a class from another package that works?
.
And out of curiosity, what's the deal?
Substantively this looks identical to me. I can call a class from another file by using the widge.widget(), so that method seems established. And I can subclass when the class is in the same file by referencing the class in the declaration. What is it about using a class from an import in a declaration that breaks? Why does it see itself as the right method when in the same file, but sees itself as an unbound method when imported?
The specifically, my code is this (stripping the parts that shouldn't affect this.
Attributor.py
class Tracker(object):
def __init__(self, nodeName=None, dag=None):
#Tracking stuff
class Transform(Tracker):
#Does stuff with inherited class
timeline_tab.py
import Attributor as attr
class timeline(attr.Transform):
#some vars
def __init__(self, nodeName=None):
attr.Transform.__init__(self,nodeName=nodeName)
#Additional init stuff, but doesn't happen because error on previous line
In superWidget.py change the SuperWidget to use super
import widge
class superWidgety(widge.evenWidgetier):
def __init__(self, bob):
super(SuperWidget,self).__init__(bob)
#do something
I am almost sure that there is a proper term for what I want to do but since I'm not familiar with it, I will try to describe the whole idea explicitly. So what I have is a collection of classes that all inherit from one base class. All the classes consist almost entirely of different methods that are relevant within each class only. However, there are several methods that share similar name, general functionality and also some logic but their implementation is still mostly different. So what I want to know is whether it's possible to create a method in a base class that will execute some logic that is similar to all the methods but still continue the execution in the class specific method. Hopefully that makes sense but I will try to give a basic example of what I want.
So consider a base class that looks something like that:
class App(object):
def __init__(self, testName):
self.localLog = logging.getLogger(testName)
def access(self):
LOGIC_SHARED
And an example of a derived class:
class App1(App):
def __init__(self, testName):
. . .
super(App1, self).__init__(testName)
def access(self):
LOGIC_SPECIFIC
So what I'd like to achieve is that the LOGIC_SHARED part in base class access method to be executed when calling the access method of any App class before executing the LOGIC_SPECIFIC part which is(as it says) specific for each access method of all derived classes.
If that makes any difference, the LOGIC_SHARED mostly consists of logging and maintenance tasks.
Hope that is clear enough and the idea makes sense.
NOTE 1:
There are class specific parameters which are being used in the LOGIC_SHARED section.
NOTE 2:
It is important to implement that behavior using only Python built-in functions and modules.
NOTE 3:
The LOGIC_SHARED part looks something like that:
try:
self.localLog.info("Checking the actual link for %s", self.application)
self.link = self.checkLink(self.application)
self.localLog.info("Actual link found!: %s", self.link)
except:
self.localLog.info("No links found. Going to use the default link: %s", self.link)
So, there are plenty of specific class instance attributes that I use and I'm not sure how to use these attributes from the base class.
Sure, just put the specific logic in its own "private" function, which can overridden by the derived classes, and leave access in the Base.
class Base(object):
def access(self):
# Shared logic 1
self._specific_logic()
# Shared logic 2
def _specific_logic(self):
# Nothing special to do in the base class
pass
# Or you could even raise an exception
raise Exception('Called access on Base class instance')
class DerivedA(Base):
# overrides Base implementation
def _specific_logic(self):
# DerivedA specific logic
class DerivedB(Base):
# overrides Base implementation
def _specific_logic(self):
# DerivedB specific logic
def test():
x = Base()
x.access() # Shared logic 1
# Shared logic 2
a = DerivedA()
a.access() # Shared logic 1
# Derived A specific logic
# Shared logic 2
b = DerivedB()
b.access() # Shared logic 1
# Derived B specific logic
# Shared logic 2
The easiest method to do what you want is to simply call the parent's class access method inside the child's access method.
class App(object):
def __init__(self, testName):
self.localLog = logging.getLogger(testName)
def access(self):
LOGIC_SHARED
class App1(App):
def __init__(self, testName):
super(App1, self).__init__(testName)
def access(self):
App.access(self)
# or use super
super(App1, self).access()
However, your shared functionality is mostly logging and maintenance. Unless there is a pressing reason to put this inside the parent class, you may want to consider is to refactor the shared functionality into a decorator function. This is particularly useful if you want to reuse similar logging and maintenance functionality for a range of methods inside your class.
You can read more about function decorators here: http://www.artima.com/weblogs/viewpost.jsp?thread=240808, or here on Stack Overflow: How to make a chain of function decorators?.
def decorated(method):
def decorated_method(self, *args, **kwargs):
LOGIC_SHARED
method(self, *args, **kwargs)
return decorated_method
Remember than in python, functions are first class objects. That means that you can take a function and pass it as a parameter to another function. A decorator function make use of this. The decorator function takes another function as a parameter (here called method) and then creates a new function (here called decorated_method) that takes the place of the original function.
Your App1 class then would look like this:
class App1(App):
#logged
def access(self):
LOGIC_SPECIFIC
This really is shorthand for this:
class App1(App):
def access(self):
LOGIC_SPECIFIC
decorated_access = logged(App.access)
App.access = decorated_access
I would find this more elegant than adding methods to the superclass to capture shared functionality.
If I understand well this commment (How to execute BaseClass method before it gets overridden by DerivedClass method in Python) you want that additional arguments passed to the parent class used in derived class
based on Jonathon Reinhart's answer
it's how you could do
class Base(object):
def access(self,
param1 ,param2, #first common parameters
*args, #second positional parameters
**kwargs #third keyword arguments
):
# Shared logic 1
self._specific_logic(param1, param2, *args, **kwargs)
# Shared logic 2
def _specific_logic(self, param1, param2, *args, **kwargs):
# Nothing special to do in the base class
pass
# Or you could even raise an exception
raise Exception('Called access on Base class instance')
class DerivedA(Base):
# overrides Base implementation
def _specific_logic(self, param1, param2, param3):
# DerivedA specific logic
class DerivedB(Base):
# overrides Base implementation
def _specific_logic(self, param1, param2, param4):
# DerivedB specific logic
def test():
x = Base()
a = DerivedA()
a.access("param1", "param2", "param3") # Shared logic 1
# Derived A specific logic
# Shared logic 2
b = DerivedB()
b.access("param1", "param2", param4="param4") # Shared logic 1
# Derived B specific logic
# Shared logic 2
I personally prefer Jonathon Reinhart's answer, but seeing as you seem to want more options, here's two more. I would probably never use the metaclass one, as cool as it is, but I might consider the second one with decorators.
With Metaclasses
This method uses a metaclass for the base class that will force the base class's access method to be called first, without having a separate private function, and without having to explicitly call super or anything like that. End result: no extra work/code goes into inheriting classes.
Plus, it works like maaaagiiiiic </spongebob>
Below is the code that will do this. Here http://dbgr.cc/W you can step through the code live and see how it works :
#!/usr/bin/env python
class ForceBaseClassFirst(type):
def __new__(cls, name, bases, attrs):
"""
"""
print("Creating class '%s'" % name)
def wrap_function(fn_name, base_fn, other_fn):
def new_fn(*args, **kwargs):
print("calling base '%s' function" % fn_name)
base_fn(*args, **kwargs)
print("calling other '%s' function" % fn_name)
other_fn(*args, **kwargs)
new_fn.__name__ = "wrapped_%s" % fn_name
return new_fn
if name != "BaseClass":
print("setting attrs['access'] to wrapped function")
attrs["access"] = wrap_function(
"access",
getattr(bases[0], "access", lambda: None),
attrs.setdefault("access", lambda: None)
)
return type.__new__(cls, name, bases, attrs)
class BaseClass(object):
__metaclass__ = ForceBaseClassFirst
def access(self):
print("in BaseClass access function")
class OtherClass(BaseClass):
def access(self):
print("in OtherClass access function")
print("OtherClass attributes:")
for k,v in OtherClass.__dict__.iteritems():
print("%15s: %r" % (k, v))
o = OtherClass()
print("Calling access on OtherClass instance")
print("-------------------------------------")
o.access()
This uses a metaclass to replace OtherClass's access function with a function that wraps a call to BaseClass's access function and a call to OtherClass's access function. See the best explanation of metaclasses here https://stackoverflow.com/a/6581949.
Stepping through the code should really help you understand the order of things.
With Decorators
This functionality could also easily be put into a decorator, as shown below. Again, a steppable/debuggable/runnable version of the code below can be found here http://dbgr.cc/0
#!/usr/bin/env python
def superfy(some_func):
def wrapped(self, *args, **kwargs):
# NOTE might need to be changed when dealing with
# multiple inheritance
base_fn = getattr(self.__class__.__bases__[0], some_func.__name__, lambda *args, **kwargs: None)
# bind the parent class' function and call it
base_fn.__get__(self, self.__class__)(*args, **kwargs)
# call the child class' function
some_func(self, *args, **kwargs)
wrapped.__name__ = "superfy(%s)" % some_func.__name__
return wrapped
class BaseClass(object):
def access(self):
print("in BaseClass access function")
class OtherClass(BaseClass):
#superfy
def access(self):
print("in OtherClass access function")
print("OtherClass attributes")
print("----------------------")
for k,v in OtherClass.__dict__.iteritems():
print("%15s: %r" % (k, v))
print("")
o = OtherClass()
print("Calling access on OtherClass instance")
print("-------------------------------------")
o.access()
The decorator above retrieves the BaseClass' function of the same name, and calls that first before calling the OtherClass' function.
May this simple approach can help.
class App:
def __init__(self, testName):
self.localLog = logging.getLogger(testName)
self.application = None
self.link = None
def access(self):
print('There is something BaseClass must do')
print('The application is ', self.application)
print('The link is ', self.link)
class App1(App):
def __init__(self, testName):
# ...
super(App1, self).__init__(testName)
def access(self):
self.application = 'Application created by App1'
self.link = 'Link created by App1'
super(App1, self).access()
print('There is something App1 must do')
class App2(App):
def __init__(self, testName):
# ...
super(App2, self).__init__(testName)
def access(self):
self.application = 'Application created by App2'
self.link = 'Link created by App2'
super(App2, self).access()
print('There is something App2 must do')
and the test result:
>>>
>>> app = App('Baseclass')
>>> app.access()
There is something BaseClass must do
The application is None
The link is None
>>> app1 = App1('App1 test')
>>> app1.access()
There is something BaseClass must do
The application is Application created by App1
The link is Link created by App1
There is something App1 must do
>>> app2 = App2('App2 text')
>>> app2.access()
There is something BaseClass must do
The application is Application created by App2
The link is Link created by App2
There is something App2 must do
>>>
Adding a combine function we can combine two functions and execute them one after other as bellow
def combine(*fun):
def new(*s):
for i in fun:
i(*s)
return new
class base():
def x(self,i):
print 'i',i
class derived(base):
def x(self,i):
print 'i*i',i*i
x=combine(base.x,x)
new_obj=derived():
new_obj.x(3)
Output Bellow
i 3
i*i 9
it need not be single level hierarchy it can have any number of levels or nested
I'm trying to implement an integration test framework using nose. At the core, I'd like a base class that all test classes inherit. I'd like to have a class setup function that is called as well as the per test setup function. When I use nosetests a_file.py -vs where a_file.py looks like this:
from nose import tools
class BaseClass(object):
def __init__(self):
print 'Initialize Base Class'
def setup(self):
print "\nBase Setup"
def teardown(self):
print "Base Teardown"
#tools.nottest
def a_test(self):
return 'This is a test.'
#tools.nottest
def another_test(self):
return 'This is another test'
class TestSomeStuff(BaseClass):
def __init__(self):
BaseClass.__init__(self)
print 'Initialize Inherited Class'
def setup(self):
BaseClass.setup(self)
print "Inherited Setup"
def teardown(self):
BaseClass.teardown(self)
print 'Inherited Teardown'
def test1(self):
print self.a_test()
def test2(self):
print self.another_test()
Outputs this:
Initialize Base Class
Initialize Inherited Class
Initialize Base Class
Initialize Inherited Class
cases.nose.class_super.TestSomeStuff.test1 ...
Base Setup
Inherited Setup
This is a test.
Base Teardown
Inherited Teardown
ok
cases.nose.class_super.TestSomeStuff.test2 ...
Base Setup
Inherited Setup
This is another test
Base Teardown
Inherited Teardown
ok
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
How do I make the __init__, setup, and teardown functions class methods? When I attempt this:
from nose import tools
class BaseClass(object):
def __init__(self):
print 'Initialize Base Class'
#classmethod
def setup_class(self):
print "\nBase Setup"
#classmethod
def teardown_class(self):
print "Base Teardown"
#tools.nottest
def a_test(self):
return 'This is a test.'
#tools.nottest
def another_test(self):
return 'This is another test'
class TestSomeStuff(BaseClass):
def __init__(self):
BaseClass.__init__(self)
print 'Initialize Inherited Class'
#classmethod
def setup_class(self):
BaseClass.setup_class(self)
print "Inherited Setup"
#classmethod
def teardown_class(self):
BaseClass.teardown_class(self)
print 'Inherited Teardown'
def test1(self):
print self.a_test()
def test2(self):
print self.another_test()
I get this:
Initialize Base Class
Initialize Inherited Class
Initialize Base Class
Initialize Inherited Class
ERROR
======================================================================
ERROR: test suite for <class 'cases.nose.class_super.TestSomeStuff'>
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/nose/suite.py", line 208, in run
self.setUp()
File "/usr/lib/python2.7/dist-packages/nose/suite.py", line 291, in setUp
self.setupContext(ancestor)
File "/usr/lib/python2.7/dist-packages/nose/suite.py", line 314, in setupContext
try_run(context, names)
File "/usr/lib/python2.7/dist-packages/nose/util.py", line 478, in try_run
return func()
File "/home/ryan/project/python_testbed/cases/nose/class_super.py", line 30, in setup_class
BaseClass.setup_class(self)
TypeError: setup_class() takes exactly 1 argument (2 given)
----------------------------------------------------------------------
Ran 0 tests in 0.001s
FAILED (errors=1)
Removing the self from the super class calls (BaseClass.setup_class(self) -> BaseClass.setup_class()) seems to fix it...which I don't understand:
Initialize Base Class
Initialize Inherited Class
Initialize Base Class
Initialize Inherited Class
Base Setup
Inherited Setup
cases.nose.class_super.TestSomeStuff.test1 ... This is a test.
ok
cases.nose.class_super.TestSomeStuff.test2 ... This is another test
ok
Base Teardown
Inherited Teardown
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
However, this doesn't help with the __init__ function. How can I make this a class method? Why does passing in self to the super class fail?
Does anyone have some info on this?
Class methods take a single implicit argument, (called cls by convention, although you have called it self too), like instance methods take self.
When you call
BaseClass.setup_class(self)
It's really more like
BaseClass.setup_class(BaseClass, self)
hence the warning over two arguments. Therefore it's fixed when you ditch self; as a reminder, change the definitions:
#classmethod
def setup_class(cls):
Oh, and __init__ makes no sense as a #classmethod; it's for setting up instances.
Looks like #Jonrsharpe already beat me, but yeah. I'll post it anyway.
This one might explain the setup_class() error. It is passing in an instance of BaseClass as well as 'self' (or TestSomeStuff) when you include the self. Nose must be hard coded to not allow more then 1 parameter in that function (or Unittest, not sure which one has that requirement).
As for the init part, after reading through the Unittest documentation, it appears that the code would be better printed as:
def __init__(self):
print 'Initialize Base Class Object'
And:
def __init__(self):
BaseClass.__init__(self)
print 'Initialize Inherited Class Object'
Since it's basically creating an object for every test case and running that init function to make sure the test case is ready.