Im just beginning to mess around a bit with classes; however, I am running across a problem.
class MyClass(object):
def f(self):
return 'hello world'
print MyClass.f
The previous script is returning <unbound method MyClass.f> instead of the intended value. How do I fix this?
MyClass.f refers to the function object f which is a property of MyClass. In your case, f is an instance method (has a self parameter) so its called on a particular instance. Its "unbound" because you're referring to f without specifying a specific class, kind of like referring to a steering wheel without a car.
You can create an instance of MyClass and call f from it like so:
x = MyClass()
x.f()
(This specifies which instance to call f from, so you can refer to instance variables and the like.)
You're using f as a static method. These methods aren't bound to a particular class, and can only reference their parameters.
A static method would be created and used like so:
class MyClass(object):
def f(): #no self parameter
return 'hello world'
print MyClass.f()
Create an instance of your class: m = MyClass()
then use m.f() to call the function
Now you may wonder why you don't have to pass a parameter to the function (the 'self' param). It is because the instance on which you call the function is actually passed as the first parameter.
That is, MyClass.f(m) equals m.f(), where m is an instance object of class MyClass.
Good luck!
Related
How to reference method of class in Python?
In PHP there is so called "callable", pretty much an array with two elements, where first is FQCN or object instance, second is method name e.g.:
$callable = [$this, 'methodName']
or with FQCN
$callable = [\My\Namespaced\Foo::class, 'methodName']
Following is very important for me. It is possible to invoke it later e.g. by:
call_user_func($callable);
How to get same in Python and what is the Pythonic name for it?
In Python, you can get (via the descriptor protocol) something called a bound method.
class A:
def foo(self, x):
print(x)
a = A()
f = a.foo
f(3) # Equivalent to a.foo(3)
f is a bound method, an object very much (it seems) like the array you describe in PHP. The bound method f is little more than an object that contains references to a and A.foo, so that when you call f(...), it basically just calls A.foo(a, ...) for you.
I am trying to create class that having one instance method, is it possible to create instance method without self.
class A():
def display():
print("Hi")
a = A()
a.display()
I am getting like this: Type Error: display() takes no arguments (1 given)
For an instance method, you need to add a parameter that represents the instance itself. It MUST be present and it MUST be the first parameter of the method - that's mandatory, you cannot change this. It can be called whatever you want, although self is the standard used by the community, which you should also follow.
class A():
def display(self):
print('Hi')
Now, as you probably noticed, we're not doing anything in particular with the instance in the display method. To avoid this redundancy, we need to use a different type of method.
A method which does not take an instance as an argument is called a static method and is represented by the #staticmethod decorator directy above the function definition:
class A():
#staticmethod
def display():
print('Hi')
Both snippets will run without errors and, producing the same output when you execute the following code:
a = A()
a.display()
But the second version is preferred - because explicit is better than implicit.
Using #staticmethod will work... but I won't recommend it for beginner uses
Usually function define an object behavior so you'll need the object itself using self !
As others have pointed out, an instance method must have at least one parameter, as the object itself is passed (implicitly) as the first argument. But why?
This def statement, like any other, defines a function, not a method. So where does the method come from? Let's go step by step.
class A:
def display(self):
print("Hi")
If we look directly in the dictionary that stores a class's attributes, we see that display is bound to an instance of function.
>>> type(A.__dict__['display'])
<class 'function'>
We get the same result if we try to access the attribute using the normal dot syntax:
>>> type(A.display)
<class 'function'>
But something ... different ... happens if we try to access that function via an instance of the class:
>>> type(A().display)
<class 'method'>
Where did the method come from? Anytime you access an attribute, the machinery that handles such access looks to see if the result has a __get__ method. The function type provides such a method, so instead of getting the function itself back, you get the result of calling that function's __get__ method. That is, A().display is really the same as A.display.__get__(A(), A). And what __get__ returns is an object that does two things:
Saves a reference to the instance A()
Saves a reference to the function A.display.
When you try to call this object, what it does is takes any arguments passed to it, and passes the saved reference to A() along with those arguments to the function A.display. That is,
a = A()
a.display() == A.display.__get__(a, A)(a)
An that's why display gets defined with one more argument than is seemingly necessary.
Others have also mentioned static methods. What does #staticmethod do? staticmethod is another type, whose instances wrap a function. The staticmethod definition of __get__, though, doesn't do anything other than return the underlying function, not any kind of new method object. So given
class A:
#staticmethod
def display():
print("Hi")
we can see that display is an instance of static method, not a function:
>>> >>> type(A.__dict__['display'])
<class 'staticmethod'>
and that the __get__ method returns the function itself, whether the attribute is accessed via the class
>>> type(A.display)
<class 'function'>
or an instance
>>> type(A().display)
<class 'function'>
I have following class with a function:
class A:
def myfn():
print("In myfn method.")
Here, the function does not have self as argument. It also does not have #classmethod or #staticmethod as decorator. However, it works if called with class:
A.myfn()
Output:
In myfn method.
But give an error if called from any instance:
a = A()
a.myfn()
Error output:
Traceback (most recent call last):
File "testing.py", line 16, in <module>
a.myfn()
TypeError: myfn() takes 0 positional arguments but 1 was given
probably because self was also sent as an argument.
What kind of function will this be called? Will it be a static function? Is it advisable to use function like this in classes? What is the drawback?
Edit: This function works only when called with class and not with object/instance. My main question is what is such a function called?
Edit2: It seems from the answers that this type of function, despite being the simplest form, is not accepted as legal. However, as no serious drawback is mentioned in any of many answers, I find this can be a useful construct, especially to group my own static functions in a class that I can call as needed. I would not need to create any instance of this class. In the least, it saves me from typing #staticmethod every time and makes code look less complex. It also gets derived neatly for someone to extend my class. Although all such functions can be kept at top/global level, keeping them in class is more modular. However, I feel there should be a specific name for such a simple construct which works in this specific way and it should be recognized as legal. It may also help beginners understand why self argument is needed for usual functions in a Python class. This will only add to the simplicity of this great language.
The function type implements the descriptor protocol, which means when you access myfn via the class or an instance of the class, you don't get the actual function back; you get instead the result of that function's __get__ method. That is,
A.myfn == A.myfn.__get__(None, A)
Here, myfn is an instance method, though one that hasn't been defined properly to be used as such. When accessed via the class, though, the return value of __get__ is simply the function object itself, and the function can be called the same as a static method.
Access via an instance results in a different call to __get__. If a is an instance of A, then
a.myfn() == A.myfn.__get__(a, A)
Here , __get__ tries to return, essentially, a partial application of myfn to a, but because myfn doesn't take any arguments, that fails.
You might ask, what is a static method? staticmethod is a type that wraps a function and defines its own __get__ method. That method returns the underlying function whether or not the attribute is accessed via the class or an instance. Otherwise, there is very little difference between a static method and an ordinary function.
This is not a true method. Correctly declarated instance methods should have a self argument (the name is only a convention and can be changed if you want hard to read code), and classmethods and staticmethods should be introduced by their respective decorator.
But at a lower level, def in a class declaration just creates a function and assigns it to a class member. That is exactly what happens here: A.my_fn is a function and can successfully be called as A.my_fn().
But as it was not declared with #staticmethod, it is not a true static method and it cannot be applied on a A instance. Python sees a member of that name that happens to be a function which is neither a static nor a class method, so it prepends the current instance to the list of arguments and tries to execute it.
To answer your exact question, this is not a method but just a function that happens to be assigned to a class member.
Such a function isn't the same as what #staticmethod provides, but is indeed a static method of sorts.
With #staticmethod you can also call the static method on an instance of the class. If A is a class and A.a is a static method, you'll be able to do both A.a() and A().a(). Without this decorator, only the first example will work, because for the second one, as you correctly noticed, "self [will] also [be] sent as an argument":
class A:
#staticmethod
def a():
return 1
Running this:
>>> A.a() # `A` is the class itself
1
>>> A().a() # `A()` is an instance of the class `A`
1
On the other hand:
class B:
def b():
return 2
Now, the second version doesn't work:
>>> B.b()
2
>>> B().b()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: b() takes 0 positional arguments but 1 was given
further to #chepnet's answer, if you define a class whose objects implement the descriptor protocol like:
class Descr:
def __get__(self, obj, type=None):
print('get', obj, type)
def __set__(self, obj, value):
print('set', obj, value)
def __delete__(self, obj):
print('delete', obj)
you can embed an instance of this in a class and invoke various operations on it:
class Foo:
foo = Descr()
Foo.foo
obj = Foo()
obj.foo
which outputs:
get None <class '__main__.Foo'>
get <__main__.Foo object at 0x106d4f9b0> <class '__main__.Foo'>
as functions also implement the descriptor protocol, we can replay this by doing:
def bar():
pass
print(bar)
print(bar.__get__(None, Foo))
print(bar.__get__(obj, Foo))
which outputs:
<function bar at 0x1062da730>
<function bar at 0x1062da730>
<bound method bar of <__main__.Foo object at 0x106d4f9b0>>
hopefully that complements chepnet's answer which I found a little terse/opaque
In the code below, class A has a member function which is set to point to a function defined outside the class.
in class B, the same function is set to the external pointer in the class definition.
Calling the function for an object of type A will fail, because the self does not get passed to the function. But for B, the self gets passed.
Why does the self get passed for B, but not for A?
def f1(s,a):
print s
print a
class A(object):
def __init__(self):
self.fp1 = f1
class B(object):
fp1 = f1
a=A()
b=B()
try:a.fp1("blaa")
except Exception, e: print `e`
try:b.fp1("bluu")
except Exception, e: print `e`
Output:
TypeError('f1() takes exactly 2 arguments (1 given)',)
<__main__.B object at 0x2ab0dacabed0>
bluu
When you did self.fp1 = f1 you just assigned a function to an instance variable of the class A. So when you call it you have to pass two arguments.
When you did:
class B(object):
fp1 = f1
during creation process of the class B python found a function fp1 in the class scope and created an instancemethod from it (replaced the variable with name fp1 with an instancemethod created from the function that it held before). When you call an instancemethod on an object self gets automatically passed as the first argument.
You can check this by typing:
>>> a = A()
>>> b = B()
>>> type(a.fp1)
function
>>> type(b.fp1)
instancemethod
In class A you bind a function to an instance. This could be really considered as "function pointer" so all arguments must be passed explicitly. In class B you bind the function to the class which will cause the function to work as method. You could modify class definition A to
class A(object):
def __init__(self):
A.fp1 = f1
which will give the same behavior has class B, i.e. fp1 of all instances points to f1, or you could wrap f1.
class A(object):
def __init__(self):
self.fp1 = lambda a: f1(self, a)
This will allow to change fp1 for each instance individually. The latter variant is probably what you were looking for.
The magic that makes instance.method(...) equivalent to Class.method(instance, ...) is dependent on the function object being an attribute of the class. The details vary (and with them, the ugly workaround by which you can create such a method). In Python 3, all functions are descriptors. In Python 2, there are special unbound method objects which are implicitly created to wrap functions stored as class attributes and do roughly what all functions do by themselves in Python 3.
In either case, accessing it through an instance creates a bound method which passes the instance along as first argument when called. In either case, a function accessed through an instance attribute is in no way special, it's just another object which can be passed around and used.
You can achieve similar behavior by either using partial (a bit of a leaky abstraction):
from functools import partial
# in __init__
self.fp1 = partial(f1, self)
or by creating a method which delegates:
def __init__(self):
self._fp1 = f1
def fp1(*args, **kwds):
return self._fp1(self, *args, **kwds)
In the first case you create a field in the class, that has a method object stored in it. So "a.fp1" is not a method call and therefore "a" is not put as the first argument. It's a retrieval of a method object, and then calling it.
For the second case, you can refer to the documentation:
Any function object that is a class attribute defines a method for
instances of that class.
So, for b "fp1" becomes a method for instances of class b.
You can find more detailed explanation here: method objects vs function objects , Python class instances vs class
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