Simple class in Python error - python

I get an error message saying something like:
TypeError: readFromFile() takes exactly 2 arguments (1 given)
This is my very first class in Python btw.
from numpy import *
from pycalfem import *
from pycalfem_utils import *
class FlowModel:
def __init__(self):
self.readFromFile()
def readFromFile(self,filename):
Inputfile=open(filename,'r')
ep=readFloat(Inputfile)
print(str(ep))
Inputfile.close()
if __name__=="__main__":
flowmodel=FlowModel()
flowmodel.readFromFile("indata.txt")

You call self.readFromFile() without arguments, when you create the FlowModel instance:
def __init__(self):
self.readFromFile()
This means that the method is only passed self, the first argument, but not the second argument filename.
Remove that line; you don't have a filename to pass in there. You already are using that method correctly outside of the __init__ method after creating the instance.

Related

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.

self lost when using partial inside a decorator

I'm trying to code a method from a class that uses a decorator from another class. The problem is that I need information stored in the Class that contains the decorator (ClassWithDecorator.decorator_param). To achieve that I'm using partial, injecting self as the first argument, but when I do that the self, from the class that uses the decorator " gets lost" somehow and I end up getting an error. Note that this does not happen if I remove partial() from my_decorator() and "self" will be correctly stored inside *args.
See the code sample:
from functools import partial
class ClassWithDecorator:
def __init__(self):
self.decorator_param = "PARAM"
def my_decorator(self, decorated_func):
def my_callable(ClassWithDecorator_instance, *args, **kwargs):
# Do something with decorator_param
print(ClassWithDecorator_instance.decorator_param)
return decorated_func(*args, **kwargs)
return partial(my_callable, self)
decorator_instance = ClassWithDecorator()
class WillCallDecorator:
def __init__(self):
self.other_param = "WillCallDecorator variable"
#decorator_instance.my_decorator
def decorated_method(self):
pass
WillCallDecorator().decorated_method()
I get
PARAM
Traceback (most recent call last):
File "****/decorator.py", line 32, in <module>
WillCallDecorator().decorated_method()
File "****/decorator.py", line 12, in my_callable
return decorated_func(*args, **kwargs)
TypeError: decorated_method() missing 1 required positional argument: 'self'
How can I pass the self corresponding to WillCallDecorator() into decorated_method() but at the same time pass information from its own class to my_callable() ?
It seems that you may want to use partialmethod instead of partial:
From the docs:
class functools.partialmethod(func, /, *args, **keywords)
When func is a non-descriptor callable, an appropriate bound method is created dynamically. This behaves like a normal Python function when used as a method: the self argument will be inserted as the first positional argument, even before the args and keywords supplied to the partialmethod constructor.
So much simpler just to use the self variable you already have. There is absolutely no reason to be using partial or partialmethod here at all:
from functools import partial
class ClassWithDecorator:
def __init__(self):
self.decorator_param = "PARAM"
def my_decorator(self, decorated_func):
def my_callable(*args, **kwargs):
# Do something with decorator_param
print(self.decorator_param)
return decorated_func(*args, **kwargs)
return my_callable
decorator_instance = ClassWithDecorator()
class WillCallDecorator:
def __init__(self):
self.other_param = "WillCallDecorator variable"
#decorator_instance.my_decorator
def decorated_method(self):
pass
WillCallDecorator().decorated_method()
Also, to answer your question about why your code didn't work, when you access something.decorated_method() the code checks whether decorated_method is a function and if so turns it internally into a call WillCallDecorator.decorated_method(something). But the value returned from partial is a functools.partial object, not a function. So the class lookup binding won't happen here.
In more detail, something.method(arg) is equivalent to SomethingClass.method.__get__(something, arg) when something doesn't have an attribute method and its type SomethingClass does have the attribute and the attribute has a method __get__ but the full set of steps for attribute lookup is quite complicated.

Calling a class function from the same file in 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.

Invoked method from Python unit test issues

I'm trying to invoke the following method, post_sample (filename index.py):
class Main(Resource):
#app.route('/sample', methods=['POST'])
def post_sample():
return 'POST received'
From the following unittest code:
def test_post():
Main().post_sample()
print 'test_here'
But when I run I get the following error, which I'm having trouble making sense of:
> Main().post_sample()
E TypeError: post_sample() takes no arguments (1 given)
tests/test_post.py:8: TypeError
TIA!
post_sample is an instance method and as such must accept at minimum one argument, a reference to the instance:
def post_sample(self):

Using methods of a class from another in python

I'm working through 'Dive Into Python' on Google App Engine and came across this error while attempting to call one class's methods from another:
ERROR __init__.py:463] create() takes exactly 1 argument (2 given)
Traceback (most recent call last):
File "main.py", line 35, in get
dal.create("sample-data");
File "dataAccess/dal.py", line 27, in create
self.data_store.create(data_dictionary);
TypeError: create() takes exactly 1 argument (2 given)
Here's my main class:
# filename: main.py
from dataAccess.dal import DataAccess
class MySampleRequestHandler(webapp.RequestHandler):
"""Configured to be invoked for a specific GET request"""
def get(self):
dal = DataAccess();
dal.create("sample-data"); # problem area
MySampleRequestHandler.get() tries to instantiate and invoke DataAccess which is defined else where:
# filename: dal.py
from dataAccess.datastore import StandardDataStore
class DataAccess:
"""Class responsible for wrapping the specific data store"""
def __init__(self):
self.data_store = None;
data_store_setting = config.SETTINGS['data_store_name'];
if data_store_setting == DataStoreTypes.SOME_CONFIG:
self.data_store = StandardDataStore();
logging.info("DataAccess init completed.");
def create(self, data_dictionary):
# Trying to access the data_store attribute declared in __init__
data_store.create(data_dictionary);
I thought I could call DataAccess.create() with 1 parameter for its argument, especially according to how Dive into Python notes about class method calls:
When defining your class methods, you must explicitly list self as the first
argument for each method, including __init__. When you call a method of an
ancestor class from within your class, you must include the self argument.
But when you call your class method from outside, you do not specify anything
for the self argument; you skip it entirely, and Python automatically adds the
instance reference for you.
In self.data_store.create(data_dictionary), the self.data_store refers to the object created by self.data_store = StandardDataStore() in the __init__ method.
It looks like the create method of a StandardDataStore object doesn't expect an additional argument.
It should be self.data_store.create(data_dictionary);

Categories