How to call a method that requires "self" in Python? - 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()

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.

Difference between using the decorator and the function with staticmethod

I am trying to create a class which gets given a function, which will then be run from that instance. However, when I tried to use staticmethod, I discovered that there is a difference between using the decorator and just passing staticmethod a function.
class WithDec():
def __init__(self):
pass
#staticmethod
def stat(val):
return val + 1
def OuterStat(val):
return val + 1
class WithoutDec():
def __init__(self, stat):
self.stat = staticmethod(stat)
With these two classes, the following occurs.
>>> WithDec().stat(2)
3
>>> WithoutDec(OuterStat).stat(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'staticmethod' object is not callable
What is going on, and what can I do to stop it.
Static methods still work through the descriptor protocol, meaning that when it is a class attribute, accessing it via an instance still means that the __get__ method will be called to return an object that actually gets called. That is,
WithDec().stat(2)
is equivalent to
w = WithDec()
w.stat(2)
which is equivalent to
WithDec.stat.__get__(w, WithDec)(2)
However, the descriptor protocol is not invoked when the static method is an instance attribute, as is the case with WithoutDec. In that case
WithoutDec().stat(2)
tries to call the literal staticmethod instance stat, not the the function returned by stat.__get__.
What you wanted was to use staticmethod to create a class attribute, just not via decorator syntax:
class WithoutDec():
def stat(val):
return val + 1
stat = staticmethod(stat)
You first bind stat to a regular function (it's not really an instance method until you try to use it as an instance method), then replace the function with a staticmethod instance wrapping the original function.
The problem is that you are trying to use staticmethod() inside __init__, which is used to create an instance of the class, instead of at the class level directly, which defines the class, its methods and its static methods.
This code works:
def OuterStat(val):
return val + 1
class WithoutDec():
stat = staticmethod(OuterStat)
>>> WithoutDec.stat(2)
3
Note that trying to create an instance of WithoutDec with its own, different, version of stat, is contrary to the meaning of a method being static.
I found a very inspiring solution on this thread. Indeed your code is not very pythonic, and attributes a static method to an attribute of an instance of your class. The following code works:
class WithoutDec():
stat = None
#staticmethod
def OuterStat(val):
return val + 1
then you call:
my_without_dec = WithoutDec()
my_without_dec.stat = WithotuDec.OuterStat
my_without_dec.stat(2)
later if you want to create a new method, you call:
def new_func(val):
return val+1
WithoutDec.newStat = staticmethod(new_func)
my_without_dec.stat = WithoutDec.newStat
my_without_dec.stat(2)
Yes -
In this case, you just have to add the function as an attribute of the instance, it will work as expected, no need for any decorators:
def OuterStat(val):
return val + 1
class WithoutDec():
def __init__(self, stat):
self.stat = stat
The thing is: there is a difference if a function is an attribute of the class or an attribute of the instance. When it is set inside an instance method with self.func = X, it becomes an instance attribute - Python retrieves it the way it was stored, with no modifications, and it is simply another reference to the original function that can be called.
When a function is stored as a class attibute, instead, the default behavior is that it is used as an instance method: upon retrieving the function from an instance, Python arranges things so that self will be injected as the first argument to that function. In this case, the decorators #classmethod and #staticmethod exist to modify this behavior (injetct the class for classmethod or make no injection for staticmethod).
The thing is that staticmethod does not return a function - it returns a descriptor to be used as a class attribute, so that when the decorated function is retrieved from a class, it works as a plain function.
(Internal detail: all 3 behaviors: instance method, classmethod and staticmethod are implementing by having an appropriate __get__ method on the object that is used as an attribute to the class).
NB: There were some discussions in making "staticmethod" to become itself "callable", and simply call the wrapped function - I just checked it made it into Pythonn 3.10 beta 1. This means that your example code will work as is for Python 3.10 - nonetheless, the staticmethod call there is redundant, as stated in the beggining of this answer, and should not be used.

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.

how to use a Python function with keyword "self" in arguments

i have a function that retrieve a list of stores in Python this functions is called :
class LeclercScraper(BaseScraper):
"""
This class allows scraping of Leclerc Drive website. It is the entry point for dataretrieval.
"""
def __init__(self):
LeclercDatabaseHelper = LeclercParser
super(LeclercScraper, self).__init__('http://www.leclercdrive.fr/', LeclercCrawler, LeclercParser, LeclercDatabaseHelper)
def get_list_stores(self, code):
"""
This method gets a list of stores given an area code
Input :
- code (string): from '01' to '95'
Output :
- stores :
[{
'name': '...',
'url'
}]
"""
when i try to write get_list_stores(92) i get this error :
get_list_stores(92)
TypeError: get_list_stores() takes exactly 2 arguments (1 given)
how can you help me with this ?
If the function is inside a class (a method), write it like this:
def get_list_stores(self, code):
And you have to call it over an instance of the class:
ls = LeclercScraper()
ls.get_list_stores(92)
If it's outside a class, write it without the self parameter:
def get_list_stores(code):
Now it can be called as a normal function (notice that we're not calling the function over an instance, and it's no longer a method):
get_list_stores(92)
You don't use "self" arbitrarily - self is recommended to be the first parameter to functions which are written to be methods in classes. In that case, when it is invoked as a method, like in
class A(object):
def get_list_stores(self, code):
...
a = A()
a.get_listscores(92)
Python will insert the "self" parameter automatically on the call
(and it will be the object named "a" in the outer scope)
Outside of class definitions, having a first parameter named "self" does not make
much sense - although, as it is not a keyword it is not an error per se.
In your case, most likely,t he function you are trying to call is defined in class:
you have to call it as an attribute of an instance of the class, and then you
simply omit the first parameter - just like in the example above.
If you are trying to use it in the class, access it like this:
self.get_listscores(92)
If you are trying to access it outside of the class, you need to first create an instance of LeclercScraper:
x = LeclercScraper()
y = x.get_listscores(92)
Also, self is not a keyword. It is simply the name chosen by convention to represent a class instance within itself.
Here's a good reference:
What is the purpose of self?

Python 3.1.1 Class Question

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.

Categories