Python: Unbound method __init__() from import.class - python

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

Related

Unable to access instantiated data member in python

I'm having problem accessing the data member in python. Not sure why.
These are my files:
# main.py
from myprocess import DataProcess as dp
myprocess = dp('apple')
myprocess.process_files()
Now for the file where i have a class
#myprocess.py
class DataProcess:
def __init__(self, file1):
self.file1=file1
#classmethod
def process_files():
print(self.file1)
In the process_files method, I have an error :
Class 'DataProcess' has no 'file1' member
Where have I gone wrong?
You can't use self parameter inside a classmethod. The idea of class method is that the method belongs to the class itself, and not to an instance of the class. Hence if you delete the #classmethod decorator, your code should work

Python: Call derived class method from another class

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()

Unittest + Selenium - __init__() takes 1 positional argument but 2 were given

I'm working with unittest and selenium for the first time but thats also my first bigger code in python. I found some answers for this problem but there was no explaination for classes with __ init __ inheritance and method super().__ init __()
TL;DR
I have classes that inherits one by one. The first class StartInstance that creates chrome instance inherits from unittest.TestCase and the problem is with inheritance and super().init() in other classes, becouse when i remove it test normaly starts
All looks like:
class StartInstance(unittest.TestCase):
#classmethod
def setUpClass(cls): pass
class A(StartInstance):
def __init__(self):
super().__init__() adding variables etc to init
class B(A):
def __init__(self):
super().__init__() adding variables etc to init
class C(A):
def __init__(self):
super().__init__() adding variables etc to init
class PrepareTests(B, C, D):
def all tests(self):
self.tests_B
self.tests_C
self.tests_D
class Tests(PrepareTests):
def test_click:
click()
all_tests()
#and finally somewhere a test runner
suite = loader.loadTestsFromTestCase(Tests)
runner.run(suite())
#when i run this i get this error and it only raises when i
add classes with their own init
#heh TL;DR almost as long as normal text sorry :(
ALL:
FULL ERROR MESSAGE:
Traceback (most recent call last):
File "xyz\main_test.py", line 24,
in <module>
runner.run(suite())
File "xyz\main_test.py", line 11,
in suite
about_us = loader.loadTestsFromTestCase(AboutUs)
File
"xyz\Python36\lib\unittest\loader.py", line 92, in loadTestsFromTestCase
loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames))
File "xyz\Python36\lib\unittest\suite.py", line 24, in __init__
self.addTests(tests)
File "xyz\Python36\lib\unittest\suite.py", line 57, in addTests
for test in tests:
TypeError: __init__() takes 1 positional argument but 2 were given
Thats my code:
I have a settings.py file with variables in dict of dicts accessed by settings.xyz["layer1"]["KEY"]
setup.py - setup class for selenium
class StartInstance(unittest.TestCase):
#classmethod
def setUpClass(cls):
cls.driver = webdriver.Chrome()
cls.driver.get(settings.URLS['MAIN_URL'])
cls.driver.implicitly_wait(2)
cls.driver.maximize_window()
#classmethod
def tearDownClass(cls):
cls.driver.quit()
main_tests_config.py - next layer - now very basic configs
class MainTestConfig(StartInstance):
def __init__(self):
super().__init__()
self.language = settings.TEST_LANGUAGE
self.currency = settings.TEST_CURRENCY
header.py (got few more files like this) - next layer translates code from config.py to class variables, inherits from previous classes becouse it needs global language
class HeaderPath(MainTestConfig):
def __init__(self):
super().__init__()
self.logo_path = settings.PAGE_PATHS["HEADER"]["LOGO"]
self.business_path = settings.PAGE_PATHS["HEADER"]["BUSINESS"]
class HeaderText(MainTestConfig):
def __init__(self):
super().__init__()
self.business_text = settings.PAGE_CONTENT[self.language]["HEADER"]["BUSINESS"]
self.cart_text = settings.PAGE_CONTENT[self.language]["HEADER"]["CART"]
header_tests.py - next layer, inherits variables(HeadetText, HeaderPath, Urls(class Urls it is class with page urls variables)), language(from MainTestConfig), and selenium driver (from first class StartInstance), example build of class
class HeaderStaticTest(HeaderText, HeaderPath, Urls):
def header_static(self):
self.logo_display()
self.method2()
# etc..
def logo_display(self):
self.driver.find_element_by_xpath(self.logo_path)
def self.method2(self):
pass
static_display.py - next layer, class that inherits all classes with tests like previous one and uses their methods that runs all tests but not as test_
class StaticDisplay(HeaderStaticTest, HorizontalStaticTest, VerticalStaticTest):
def static_display(self):
self.header_static()
self.horizontal_static()
self.vertical_static()
test_about_us.py - next layer, a normal unittest testcase it inherits only a previous one but in general it inherits all prevous classes that i wrote, now i can test all "static views" on page that dont change when i click on button
class AboutUs(StaticDisplay):
def test_horizontal_menu_click(self):
about_us_element = self.driver.find_element_by_id(self.hor_about_path)
about_us_element.click()
self.assertIn(
self.about_url,
self.driver.current_url
)
def test_check_static_after_horizontal(self):
self.static_display()
(finally)
main_cases.py - runner with this error, and it only raises when I add classes with their own init... have no idea how to repair it... please help
def suite():
loader = unittest.TestLoader()
about_us = loader.loadTestsFromTestCase(AboutUs)
return unittest.TestSuite([about_us])
if __name__ == '__main__':
runner = unittest.TextTestRunner()
runner.run(suite())
As i said there is somewhere problem with this new def __ init __ and super().__ init __() in new classes... where I'm making a mistake?
When i start this test case i get an error:
TypeError: __ init __() takes 1 positional argument but 2 were given Full error message above, probably it is needed
Can someone help me please?
TestCase instances take an optional keyword argument methodName; I'm guessing the unittest module passes this explicitly behind the scenes at some point. Typically when I'm subclassing classes I didn't make myself I'll use this pattern; this should fix your problem:
class SubClass(SupClass):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Especially when you're not passing any arguments to your __init__ method, passing through the arguments in this manner is a good way to avoid the error you're getting. If you do want to pass something custom to your __init__ method, you can do something like this:
class SubClass(SupClass):
def __init__(self, myarg, *args, **kwargs):
super().__init__(*args, **kwargs)
# do something with your custom argument
Ok, I found the problem... It is something else than you wrote the solution that you wrote is good too and I also used It in my code.
Problem from my question was here:
suite = loader.loadTestsFromTestCase(Tests)
runner.run(suite())
I should change to:
something = Tests
suite = loader.loadTestsFromTestCase(something)
runner.run(suite())
BUT another thing is that I had to rebuild it completly to work properly
At start: inheritance __ init __ from previous class with super was stupid becouse I didn't have acces to the class before... so I couldn't access my variables. So I've changed:
class SubClass(SupClass):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
with:
class SubClass(SupClass):
def __init__(self, *args, **kwargs):
super(SubClass, self).setUpClass(*args, **kwargs)
Then I understood that __ init __ inheritance from unittest.TestCase is impossible. To imagine what happened...
My new way to start test cases:
something = Tests
it was creating a new error... that said i have to use Tests() but when I used this form I got and previous error so both ways was bad.
So I just created class with variables, but with no __ init __ and no super()
class Something(StartInstance):
a = thing1
b = thing2
c = thing3
I'm writing this becouse maybe someone in future will try to use __ init __ with unittest... It doesn't work... or I just didn't find the solution, but I'm new :P

How can I add to the initial definition of a python class inheriting from another class?

I'm trying to define self.data inside a class inheriting from a class
class Object():
def __init__(self):
self.data="1234"
class New_Object(Object):
# Code changing self.data here
But I ran into an issue.
class Object():
def __init__(self):
self.data="1234"
So I have the beginning class here, which is imported from elsewhere, and let's say that the class is a universal one so I can't modify the original at all.
In the original, the instance is referred to as "self" inside the class, and it is defined as self inside the definition __init__.
class New_Object(Object):
# Code changing self.data here
So if I wanted to inherit from the class Object, but define self.data inside New_Object, I thought I would have to define __init__ in New_Object, but this overrides the __init__ from New_Object
Is there any way I could do this without copypasting the __init__ from Object?
You use super to call the original implementation.
class New_Object(Object):
def __init__(self):
super(NewObject, self).__init__()
self.info = 'whatever'
That's what super is for:
class NewObject(Object):
def __init__(self):
super(NewObject, self).__init__()
# self.data exists now, and you can modify it if necessary
You can use super().__init__() to call Object.__init__() from New_Object.__init__().
What you would do:
class Object:
def __init__(self):
print("Object init")
self.data = "1234"
class New_Object(Object):
def __init__(self):
print("calling super")
super().__init__()
print("data is now", self.data)
self.data = self.data.split("3")
o = New_Object()
# calling super
# Object init
# data is now 1234
Note that you do not have to give any arguments to super(), as long as you are using Python 3.
The answer is that you call the superclass's __init__ explicitly during the subclass's __init__. This can be done either of two ways:
Object.__init__(self) # requires you to name the superclass explicitly
or
super(NewObject, self).__init__() # requires you to name the subclass explicitly
The latter also requires you to ensure that you're using "new-style" classes: in Python 3 that's always the case, but in Python 2 you must be sure to inherit from the builtin object class. In Python 3 it can actually be expressed even more simply:
super().__init__()
Personally, in most of my code the "disadvantage" of having to name the superclass explicitly is no disadvantage at all, and Object.__init__() lends transparency since it makes it absolutely clear what is being called. This is because most of my code is single-inheritance only. The super route comes into its own when you have multiple inheritance. See What does 'super' do in Python?
Python 2 example:
class Object(object):
def __init__(self):
self.data = "1234"
class NewObject:
def __init__(self):
# subclass-specific stuff
super(NewObject, self).__init__()
# more subclass-specific stuff

__init__ : Inheriting __init__ parameter (dict) to another class's __init__ method?

I am confused even after checking many questions asked in SO. I have 2 different class (2 different script) & I want to inherit super class's __init__ method's parameters.
script1.py
class MainClass():
def __init__(self,params):
self.one=params['ONE']
self.two=params['TWO']
self.three=params['THREE']
self.four=params['FOUR']
self.five=params['FIVE']
def a():
#---------
#somecode
#Initializing other class's object to access it's method.
s=SubClass() #HERE I WANT TO PASS 'PARAMS' (WHICH IS A DICTIONARY)
s.method1(....)
script2.py
class SubClass(SuperClass):
def __init__(self,params):
#Here I want all the parameters inside the 'param' in super class.
#(one,two,three...., etc).
#By checking some SO questions, I changed class SubClass() -->
#class Subclass(SuperClass) & below line:
MainClass.__init__(self,params) #But technically I don't have anything
#in param in subclass.
def method1():
#some code...
Since sub class's param doesn't have anything, It gives me an error:
self.one=params['ONE']
TypeError: 'int' object has no attribute '__getitem__'
I am not getting:
How can I access all the parameters of super class to sub class in a simplest way? I don't want to pass individual arguments (like self.one, self.two..) to the sub class.
If I am calling third class inside SubClass -> method1 --> Call 3rd class same as passing 'params'. Is it possible?
Is this what you need?
script1.py
class MainClass():
def __init__(self,params):
# Save params for use by a
self.params = params
self.one=params['ONE']
self.two=params['TWO']
...
self.five=params['FIVE']
def a():
s=SubClass(self.params)
s.method1(...)
script2.py
class SubClass(SuperClass):
def __init__(self,params):
MainClass.__init__(self,params)
def method1():
#some code...
You can pass any and all the non-keyword arguments from the subclass's __init__()to the superclass's like this:
class SubClass(SuperClass):
def __init__(self, *params):
MainClass.__init__(self, *params)
...
This same idea will work for other methods, too.

Categories

Resources