python class method, Looks like the wrong syntax - python

Sample Code:
class Mysterious:
def fake_staic():
print('fake staic')
def fake_sta_parameters(self):
print(f"fake_sta_parameters {self}")
Mysterious.fake_sta_parameters("fbc")
# output fake_sta_parameters fbc
Mysterious.fake_staic()
# output fake staic
Please define code as follows. Why can it be executed normally? Please help me explain, thanks

def fake_staic():
print('fake staic')
this function does not have self as argument and is call with class name, hence it will be treated as class method, or static method.
Whereas in second function,
def fake_sta_parameters(self):
print(f"fake_sta_parameters {self}")
you are providing it self argument, but calling it using class, and passing a value as its argument, hence self here is treated as argument and replaced with "fbc".
If you try calling this fake_sta_parameters() using object of your class, then it will give insufficient arguments error, as when a function called using object of the class, will always consider/expect function's first argument to be self reference, and hence above function will throw error as it wont have sufficient arguments to receive 'fbc' value.

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 defining an attribute in the __init__ function parameters or just initializing it the block without setting it as a parameter

I'm not sure if you need to add a parameter to the init function before you initialize it or if you can initialize it without having it as a parameter first.
Is there a difference when writing this:
class Test:
def __init__(self):
self.placeholder=placeholder
and this:
class Test:
def __init__(self, placeholder):
self.placeholder=placeholder
In the first case, it will throw a NameError: name 'placeholder' is not defined when Test().__init__() is called, unless placeholder is an already defined global variable.
When you initialize an object by writing something like test_object = Test(), the __init__() function is called. If you have placeholder in the function signature, you can pass in a value i.e. test_object = Test("placeholder string") and in the second case, this will set test_object.placeholder to "placeholder string". If you try to do the same thing with the function signature in the first example, it will raise a TypeError: __init__() takes 1 positional argument but 2 were given.
Yes.
The second will actually raise an error.
You need to pass the placeholder argument to the __init__ in order to have access to it.
__init__ works like any other function, so you need to declare its arguments inside the function parenthesis.

Get owner instance of attribute

I want to get the instance handle of an attribute when this attribute is passed to a function without its instance. To make it more clear see the example code below:
class aClass():
def __init__(self):
self.anInstanceAttribute = 'ok'
def aFunction(anInstanceAttribute):
print(anInstanceAttribute)
#how to get the instance handle ('the self') of the anInstanceAttribute?
a = aClass()
aFunction(a.anInstanceAttribute)
This is not possible without introspection/frame hacks.
aFunction(a.anInstanceAttribute)
The function arguments are fully evaluated before calling the function. So, the function receives the string object "ok" and knows nothing about the instance a. If you want the function to know something about the instance, then pass in a instead.

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?

Interesting 'takes exactly 1 argument (2 given)' Python error

For the error:
TypeError: takes exactly 1 argument (2 given)
With the following class method:
def extractAll(tag):
...
and calling it:
e.extractAll("th")
The error seems very odd when I'm giving it 1 argument, the method should take only 1 argument, but it's saying I'm not giving it 1 argument....I know the problem can be fixed by adding self into the method prototype but I wanted to know the reasoning behind the error.
Am I getting it because the act of calling it via e.extractAll("th") also passes in self as an argument? And if so, by removing the self in the call, would I be making it some kind of class method that can be called like Extractor.extractAll("th")?
The call
e.extractAll("th")
for a regular method extractAll() is indeed equivalent to
Extractor.extractAll(e, "th")
These two calls are treated the same in all regards, including the error messages you get.
If you don't need to pass the instance to a method, you can use a staticmethod:
#staticmethod
def extractAll(tag):
...
which can be called as e.extractAll("th"). But I wonder why this is a method on a class at all if you don't need to access any instance.
If a non-static method is member of a class, you have to define it like that:
def Method(self, atributes..)
So, I suppose your 'e' is instance of some class with implemented method that tries to execute and has too much arguments.
Am I getting it because the act of calling it via e.extractAll("th") also passes in self as an argument?
Yes, that's precisely it. If you like, the first parameter is the object name, e that you are calling it with.
And if so, by removing the self in the call, would I be making it some kind of class method that can be called like Extractor.extractAll("th")?
Not quite. A classmethod needs the #classmethod decorator, and that accepts the class as the first paramater (usually referenced as cls). The only sort of method that is given no automatic parameter at all is known as a staticmethod, and that again needs a decorator (unsurprisingly, it's #staticmethod). A classmethod is used when it's an operation that needs to refer to the class itself: perhaps instantiating objects of the class; a staticmethod is used when the code belongs in the class logically, but requires no access to class or instance.
But yes, both staticmethods and classmethods can be called by referencing the classname as you describe: Extractor.extractAll("th").
Yes, when you invoke e.extractAll(foo), Python munges that into extractAll(e, foo).
From http://docs.python.org/tutorial/classes.html
the special thing about methods is
that the object is passed as the first
argument of the function. In our
example, the call x.f() is exactly
equivalent to MyClass.f(x). In
general, calling a method with a list
of n arguments is equivalent to
calling the corresponding function
with an argument list that is created
by inserting the method’s object
before the first argument.
Emphasis added.
Summary (Some examples of how to define methods in classes in python)
#!/usr/bin/env python # (if running from bash)
class Class1(object):
def A(self, arg1):
print arg1
# this method requires an instance of Class1
# can access self.variable_name, and other methods in Class1
#classmethod
def B(cls, arg1):
cls.C(arg1)
# can access methods B and C in Class1
#staticmethod
def C(arg1):
print arg1
# can access methods B and C in Class1
# (i.e. via Class1.B(...) and Class1.C(...))
Example
my_obj=Class1()
my_obj.A("1")
# Class1.A("2") # TypeError: method A() must be called with Class1 instance
my_obj.B("3")
Class1.B("4")
my_obj.C("5")
Class1.C("6")`
try using:
def extractAll(self,tag):
attention to self

Categories