Calling a class function from the same file in Python - python

How do I call a function defined in a class in Python?
import pypyodbc as pyodbc
Master_Conn = 'Driver={SQL Server};Server=server\23;Database=DBname;UID=username;PWD=password;'
Master_db = pyodbc.connect(Master_Conn)
Master_Cursor = Master_db.cursor()
class Test:
def __init__(self):
self.master_status = ""
def Getmodel(self):
self.master_status= dict(Master_Cursor.execute("select col1,col2 from tablename ").fetchall())
print (self.master_status)
Test.Getmodel()
With above code, I get
TypeError: Getmodel() missing 1 required positional argument: 'self'
So I tried Test.Getmodel(self) and it resulted in
NameError: name 'self' is not defined.
I even tried both scenarios with if __name__== '__main__': but got same errors.

You are defining Getmodel as an instance method. So it have to be called on an instance of the class Test.
To create an instance of class Test you can write
instance_of_test = Test()
Now you can call Getmodel on instance_of_test
instance_of_test.Getmodel()
You can shorten this process by writing
Test().Getmodel()
Note that self is (usually) passed hiddenly when calling an instance method; it represents the instance calling the method.
Consider the following class Pizza
class Pizza:
def __init__(self, size):
self.size = size
def get_size(self):
return self.size
First you need to create an instance of Pizza
mypizza = Pizza(42)
then you can call the instance method get_size on mypizza
mypizza.get_size()

What your doing will work if you instantiate an object of the class Test first. Instantiation just means you call the class as if it were a method which. The following should work:
Test().Getmodel()
The () is what makes the instantiation happen so now the self essentially gets passed to the Getmodel() method because an object of the class Test now exists.

Related

Finding parameters of `__init__()` or parameters needed to construct an object in python

I have scenario where I am passing a file name and checking if it has argument start as constructor if it has then I have to create instance of that class.
Consider the example where I have a file named test.py which have three class namely A,B,C now only class A has start parameter others have other different parameter or extra parameter.
#test.py
class A:
def __init__(self, start=""):
pass
class B:
def __init__(self, randomKeyword, start=""):
pass
class C:
def __init__(self):
pass
Now I want to write a script which takes test.py as an argument and create instance of A. Till now my progress is
detail = importlib.util.spec_from_file_location('test.py', '/path/to/test.py')
module = importlib.util.module_from_spec(detail)
spec.loader.exec_module(mod)
Bacially I need to write a program which finds init argument of all class in file and create an instance of file with start as init argument.
As mentioned by #deceze it's not a good idea to instantiate a class on the basis of it's init parameter as we're not sure what is there. But it's possible to do it. So I am posting this answer just so that you know how it can be done.
#test.py
class A:
def __init__(self, start=""):
pass
class B:
def __init__(self, randomKeyword, start=""):
pass
class C:
def __init__(self):
pass
One of the possibility is
#init.py
import importlib.util
from inspect import getmembers, isclass, signature
detail = importlib.util.spec_from_file_location('test.py', '/path/to/test.py')
module = importlib.util.module_from_spec(detail)
spec.loader.exec_module(module)
for name, data in getmembers(mod, isclass):
cls = getattr(mod, name)
parameter = signature(cls.__init__).parameters.keys()
# parameter start
if len(parameter) == 2 and 'start' in parameter:
object = cls(start="Whatever you want")
Ofcourse it's not the best approach so more answer are welcome and if you are in this scenario consider #deceze comment and define a builder.

Python 3 : Inheritance and the assignment of "self"

Why does this script require "self" as an argument to mssg() in line 3? PyCharm flags "self" in line 3 as, expected type "Another", got "Main" instead. This warning makes sense to me (although the code works). When "self" is omitted, Python throws an error:
TypeError: mssg() missing 1 required positional argument: 'self'
class Main():
def __init__(self):
print(Another.mssg(self))
class Another():
def __init__(self):
pass
def mssg(self):
return "Hello World"
_foo = Main()
Using your guidance, here are three different ways to prevent the TypeError:
class Main():
def __init__(self):
print(Another.mssg('asdasdsa'))
print(Another().mssg())
print(_bar.mssg())
class Another():
def __init__(self):
pass
def mssg(self):
return "Hello World"
_bar = Another()
_foo = Main()
If you use Another.mssg(self), then your are calling a class method, that is why self is taken as a parameter and you need to use exactly one argument to call the function. Try print(Another.mssg('asdasdsa')) and you will see that it works.
If your intention was using mssg(self) as an instance method, then you should call it using print(Another().mssg()), so you create your instance and then you call its method.

Unable to patch an object's attribute correctly

I have a Python module as follows:
# src/exec.py
class A:
def run(self, stuff):
b = B(stuff.x)
class B:
def __init__(self, x):
self.obj = self.create_some_obj()
I'm trying to test a part of class A independently, for which I need to replace the obj in B with a fake object. I'm doing this as follows:
# test/test_execs.py
import exec as ex
class FakeObjForB:
def __init__(self):
# some init
class TestClass:
#patch.object(ex.B, 'obj', FakeObjForB())
def test_with_fake_obj(self):
a = ex.A()
a.run()
# assert something about the state of a that depends on the b inside its run method
Running this test gives me the error: AttributeError: <class 'B'> does not have the attribute 'obj'. I tried replacing the line with the #patch decorator with #patch.object(ex.B, 'obj', FakeObjForB(), create=True). This, however, results in b.obj using the actual definition, and not FakeObjForB, which in turn leads to a false-failure in the assertion in test_with_fake_obj. Any clues about what I'm doing incorrectly here?
In your example you're patching the B class, that's the object passed as the first argument. That class doesn't declare obj attribute on the class level and so AttributeError is raised. When you provide create=True it won't complain as that argument allows the obj attribute to be dynamically created when needed/accessed. But, that won't ever happen as the very first "access" of that attribute is its actual creation - no dynamic mocking ever happened.
A solution is to actually patch the method whose returned value would be assigned to the obj attribute, like:
#patch.object(ex.B, 'create_some_obj', FakeObjForB())

TypeError: generatecode() takes 0 positional arguments but 1 was given

I have the code below:
from tkinter import *
class Window(Frame):
def __init__(self, master = None):
Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
self.master.title("COD:WWII Codes")
self.pack(fill=BOTH, expand=1)
codeButton = Button(
self,
text="Generate Code",
command=self.generatecode
)
codeButton.place(x=0, y=0)
def generatecode(self):
f = open("C:/Programs/codes.txt", "r")
t.insert(1.0. f.red())
root = Tk()
root.geometry("400x300")
app = Window(root)
root.mainloop()
Then, I got the error below:
TypeError: generatecode() takes 0 positional arguments but 1 was given
So, how can I solve the error?
When you call a method on a class (such as generatecode() in this case), Python automatically passes self as the first argument to the function. So when you call self.my_func(), it's more like calling MyClass.my_func(self).
So when Python tells you "generatecode() takes 0 positional arguments but 1 was given", it's telling you that your method is set up to take no arguments, but the self argument is still being passed when the method is called, so in fact it is receiving one argument.
Adding self to your method definition should resolve the problem.
def generatecode(self):
pass # Do stuff here
Alternatively, you can make the method static, in which case Python will not pass self as the first argument:
#staticmethod
def generatecode():
pass # Do stuff here
I got the same error:
TypeError: test() takes 0 positional arguments but 1 was given
When defining an instance method without self and I called it as shown below:
class Person:
# ↓↓ Without "self"
def test():
print("Test")
obj = Person()
obj.test() # Here
So, I put self to the instance method and called it:
class Person:
# ↓↓ Put "self"
def test(self):
print("Test")
obj = Person()
obj.test() # Here
Then, the error was solved:
Test
In addition, even if defining an instance method with self, we cannot call it directly by class name as shown below:
class Person:
# Here
def test(self):
print("Test")
Person.test() # Cannot call it directly by class name
Then, the error below occurs:
TypeError: test() missing 1 required positional argument: 'self'
But, if defining an instance method without self, we can call it directly by class name as shown below:
class Person:
# ↓↓ Without "self"
def test():
print("Test")
Person.test() # Can call it directly by class name
Then, we can get the result below without any errors:
Test
In detail, I explain about instance method in my answer for What is an "instance method" in Python? and also explain about #staticmethod and #classmethod in my answer for #classmethod vs #staticmethod in Python.
The most upvoted answer does solve this issue,
And just in case anyone is doing this inside of a jupyternotebook. You must restart the kernel of the jupyternotebook in order for changes to update in the notebook

My classes think that "self" is an argument that needs a value assigned

I'm not sure why this is happening. It seems to think that "self" requires an argument, which doesn't make any sense.
Here's my code:
class Animal:
def __init__(self):
self.quality = 1
class Bear(Animal):
def __init__(self):
Animal.__init__(self)
def getImage(self):
return "bear.ppm"
class Fish(Animal):
def __init__(self):
Animal.__init__(self)
def getImage(self):
return "fish.ppm"
And the error I get is:
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
Bear.getImage()
TypeError: getImage() takes exactly 1 argument (0 given)
You have to instantiate Bear before you call getImage():
b = Bear()
b.getImage()
getImage is an instance method, so it is only designed to be called on a specific instance of the Bear class. The state of that instance is what is passed as the self variable to getImage. Calling b.getImage() is equivalent to this:
b = Bear()
Bear.getImage(b)
So, without an instance of Bear, there is nothing that can be used for the self argument, which is why you see that exception when you called Bear.getImage(). See the documentation on Python instance methods for more information.
If you want to be able to call getImage on the class Bear rather than on a specific instance, you need to make it a static method, using the #staticmethod decorator:
class Bear(Animal):
def __init__(self):
Animal.__init__(self)
#staticmethod
def getImage():
return "bear.ppm"
Then you could call Bear.getImage().
getImage() is an instance method, so it can only be called with a instantiation of Bear class. So here is how you can do it:
Bear().getImage()
or
be = Bear()
be.getImage()

Categories