Python 3.1.1 Class Question - python

I'm a new Python programmer who is having a little trouble using 'self' in classes. For example:
class data:
def __init__(self):
self.table = []
def add(self, file):
self.table.append(file)
data.add('yes')
In this function I want to have table be a variable stored in the class data and use add to modify it. However, when I run this script it gives me the error:
Traceback (most recent call last):
File "/Projects/Python/sfdfs.py", line 7, in <module>
data.add('yes')
TypeError: add() takes exactly 2 positional arguments (1 given)
I assume that I am trying to call the function the wrong way in this instance, as this syntax is very similar to an example in the python documentation: http://docs.python.org/3.1/tutorial/classes.html

You first need to make an instance of the class:
mydata = data()
then you can call the method -- on the instance, of course, not on the class:
mydata.add('yes')

You need to instantiate the class before you can call methods on it:
mydata = Data()
mydata.add('yes')

you are calling the add method on the class object not an instance of the class.
It looks like what you want to do is:
classInst = data() #make an instance
classInst.add("stuff") #call the method
When add is invoked on an instance object, the instance object is passed as the self argument to the method. Having the self argument differentiates class methods from instance methods.

You are trying to call data.add() somewhat like you would call a static method in Java.
Try doing this instead:
d = data()
d.add('yes')
The self parameter tells the method that it operates on an object of type data.

Related

Why does Python complains about the number of parameters in __init__?

i don't understand this error in Python. I read about "self" and "__init__" in this previous question , where says that Python does not pass transparently the instance to the constructor. So I tried a simple class definition and then declare a new instance.
#Basic class
class Testing:
atr1 = 33
def __init__():
pass
def sayHi():
print("Hello world")
When I try to declare a new instance of this class, Jupyter throws this error:
t1 = Testing()
TypeError Traceback (most recent call last)
<ipython-input-6-0019e8f92b90> in <module>
----> 1 t1 = Testing()
TypeError: __init__() takes 0 positional arguments but 1 was given
So for me, this error doesn't make sense, otherwise, Python would be actually passing the instance itself as an argument when initializes the new instance and because i'm not giving an explicit argument.
The solution is quite simple: just write "self" as an argument of init method, but i'm still confused about the error.
Hope somebody can explain me this weird error message u.u
The first parameter to an object method is a reference to the object itself. Traditionally its called self but really you could name it anything you want. In the end, a method is really just a function assigned to a class. That's what happened when you did
class Testing:
def __init__():
pass
The def caused python to compile a function and assign it to __init__. Because __init__ is in the Testing class namespace, it assigned it to the class. You could just as easily have done
class Testing:
pass
def whatever():
pass
Testing.__init__ = whatever
So, the idea of python just magically creating the self parameter on methods doesn't work. It would be a crazy rule for regular functions.
__init__ is an initializer, not a constructor. The object has been constructed to the point that it has a functioning self by the time __init__ has been called. Classes also have a __new__ that can be used to construct the object.

Unable to call function with self

I'm writing a simple code snippet here, but unable to run the code
class test:
def __init__(self):
pass
def functiona(self, a):
b = a+0
print(b)
def functionb(self):
a = 5
self.functiona(a)
test.functionb('abc')
It errors out with "AttributeError: 'str' object has no attribute 'functiona'" Unable to call it with self. However, if I provide test.functiona(a) it works fine.
Few of other code samples works with self.function, how to solve this issue
test.functionb('abc') is a function call on the class, not on an instance.
I suppose it works if you do test().functionb('abc')?
The difference is:
In your case, you call the function object on the class. As it is not a staticmethod or classmethod, it is called with self = 'abc', a string. This string hasn't a method functiona().
In my case, the call operates on a class instance. Here, self is set to the instance you just created – and you get an error because it doesn't know where to pass the 'abc'.
Problem lies in the call test.functionb('abc'). You are not using object of the class to call the method. So, the self parameter is not passed.
Python considers, the first parameter to be self, and you passed 'abc' which is a string.
Use it like test().functionb('abc') , then the default first argument becomes the object of test - like functionb(test_ob, 'abc').
you can add the decorator #classmethod and then call it like you did
class test:
def __init__(self):
pass
#classmethod
def functiona(self, a):
b = a+0
print(b)
#classmethod
def functionb(self):
a = 5
self.functiona(a)
>>> test.functiona(1001)
>>> 1001
>>> test.functionb()
>>> 5
Problem lies in the call test.functionb('abc'). You are not using object of the class to call the method. So, the self parameter is not passed. Python considers, the first parameter to be self, and you passed 'abc' which is a string.
Use it like test().functionb('abc') , then the default first argument becomes the object of test - like functionb(test_ob, 'abc').

How to call a method that requires "self" in Python?

I am very new to python and am trying to figure out what needs to be passed to this method. I'm sure this is such a noob question, but how do I create an object to pass to self?
class Bittrex(object):
def get_markets(self):
return self._api_query(path_dict={
API_V1_1: '/public/getmarkets',
API_V2_0: '/pub/Markets/GetMarkets'
}, protection=PROTECTION_PUB)
get_markets(self) //My attempt to call
Create an object of class Bittrex and then call method using .
b = Bittrex()
res = b.get_markets()

Arguments given do not match what python sees

I have a python file called sample.py with a class definition of Sample object in. This object has various variables and the following function:
def ratioDivision(numerator, denominator):
Then, in my main function (in another file), I declare a Sample object x, and attempt to call this function:
x.co2overco = x.ratioDivision(float(x.co2), float(x.co))
However, I get this error:
Traceback (most recent call last):
File "csvReader.py", line 192, in <module>
main(sys.argv[1:])
File "csvReader.py", line 79, in main
x.co2overco = x.ratioDivision(float(x.co2), float(x.co))
TypeError: ratioDivision() takes exactly 2 arguments (3 given)
I can't see how I gave three arguments? Is there a issue with the referencing?
Your method an instance method. It's first parameter should be self
def ratioDivision(self, numerator, denominator):
It sees 3 parameters, because the first parameter is the instance itself.
When an attribute lookup (ie obj.name) references a function that's an attribute of the class, then the attribute resolution mechanism yields a callable method object instead of the function. This method object is a wrapper around the function and instance, and when called it injects the instance as first argument, so in your case
x.ratioDivision(1, 2)
becomes
Sample.__dict__["ratioDivision"](x, 1, 2)
If ratioDivision doesn't need any access to the current instance nor class, you could just make it a plain function in your module (Python is not Java and doesn't require that everything lives in a class).
If you still want it to be accessible thru Sample instances (to support for class-based polymorphic dispatch or just for mere practical reasons - like not having to import both Sample and ratioDivision from your module), you can also make it a staticmethod:
class Sample(object):
#staticmethod
def ratioDivision(numerator, denominator):
return whatever
This being said, given your example use case, ie:
x.co2overco = x.ratioDivision(float(x.co2), float(x.co))
you may want to add a method to your Sample class, something like computeCo2overco() :
class Sample(object):
#staticmethod
def ratioDivision(numerator, denominator):
return whatever
def computeCo2overco(self)
self.co2overco = self.ratioDivision(float(self.co2), float(self.co))
or if ratioDivision is not expensive, just use a computed attribute:
class Sample(object):
#staticmethod
def ratioDivision(numerator, denominator):
return whatever
#property
def co2overco(self):
return self.ratioDivision(float(self.co2), float(self.co))
In which case you can just use:
whatever = x.co2coverco + something
and under the hood, it will call the co2overco() function.

How do you call an instance of a class in Python?

This is inspired by a question I just saw, "Change what is returned by calling class instance", but was quickly answered with __repr__ (and accepted, so the questioner did not actually intend to call the instance).
Now calling an instance of a class can be done like this:
instance_of_object = object()
instance_of_object()
but we'll get an error, something like TypeError: 'object' object is not callable.
This behavior is defined in the CPython source here.
So to ensure we have this question on Stackoverflow:
How do you actually call an instance of a class in Python?
You call an instance of a class as in the following:
o = object() # create our instance
o() # call the instance
But this will typically give us an error.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'object' object is not callable
How can we call the instance as intended, and perhaps get something useful out of it?
We have to implement Python special method, __call__!
class Knight(object):
def __call__(self, foo, bar, baz=None):
print(foo)
print(bar)
print(bar)
print(bar)
print(baz)
Instantiate the class:
a_knight = Knight()
Now we can call the class instance:
a_knight('ni!', 'ichi', 'pitang-zoom-boing!')
which prints:
ni!
ichi
ichi
ichi
pitang-zoom-boing!
And we have now actually, and successfully, called an instance of the class!
The short answer is that the object class has no __call__ method (you can check that with "dir(object)"). When you create an instance of a class the __init__ method is called and when you call the instance, the __call__ method is called.
Up Votes for Everyone!
Thanks for posting the question and thanks for answering.
I thought I would just share my implementation in case that helps others ...
I have a class (called RTS) and it contains an SQL Query that I access using a 'get'. The class works fine as an independent endpoint. Now I want to call that class from within the program.
Using the answer above I added the following:
class RTS(Resource):
def __call__(self):
print("In RTS")
def get(self, user_id):
try: ...
In order to call the class from elsewhere in the program I added:
getGR = RTS.get(self, user_unique_id)
Voila - I got the same info I could check on Postman returned within the program.

Categories