class Person():
pass;
def say_hi(self):
print 'hii'
me=Person()
me.say_hi=say_hi
me.say_hi()
Isn't the self argument automatically passed in python ? why why is calling me.say_hi()
is giving a stack trace ?
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: say_hi() takes exactly 1 argument (0 given)
Use self when: you define an instance method, since it is passed automatically as the first parameter when the method is called; you reference a class or an instance attribute from inside an instance method; you want to refer to instance variables and methods from other instance methods.
self represents the instance of the class. By using the “self” we can access the attributes and methods of the class in python. It binds the attributes with the given arguments. The reason you need to use self. is because Python does not use the @ syntax to refer to instance attributes.
The “NameError: name 'self' is not defined” error is raised when you forget to specify “self” as a positional argument or when you use “self” in another argument in a list of arguments. You solve this error by making sure that all methods in a function that use “self” include “self” in their list of arguments.
The self parameter is a reference to the current instance of the class, and is used to access variables that belongs to the class.
It's not passed in the way that you are doing it.
You would have to do.
import types
me.say_hi = types.MethodType(say_hi, me, Person)
for it to work.
When python instantiates a class, it essentially carries out the above procedure for each of the class methods. When you 'monkey-patch' a method onto an object in the way that you were trying to do it, it's not a bound method and just exists as a function in instance.__dict__
. Calling it is no different than calling any other function. If you want to stick a method on an instance, you have to manually make it a method as shown above.
If you were to do
class Person(object):
pass
def say_hi(self):
print 'hii'
Person.say_hi = say_hi
me = Person()
me.say_hi()
then it would work because Python will create the method for you.
Chris Morgan put up an answer that shows this one in action. It's good stuff.
(This can act as some demonstration for aaronasterling's answer.)
Here are the definitions:
>>> class Person(object):
... def bound(self):
... print "Hi, I'm bound."
...
>>> def unbound(self):
... print "Hi, I'm unbound."
...
Note the types of these methods and functions.
>>> type(Person.bound)
<type 'instancemethod'>
>>> type(Person().bound)
<type 'instancemethod'>
>>> type(unbound)
<type 'function'>
>>> Person.unbound = unbound
When it gets set on the Person
before instantiation, it gets bound.
>>> Person().bound()
Hi, I'm bound.
>>> Person().unbound()
Hi, I'm unbound.
However, if it's set after instantiation, it's still of type 'function'.
>>> me = Person()
>>> me.rebound = unbound
>>> type(me.rebound)
<type 'function'>
>>> type(me.unbound)
<type 'instancemethod'>
>>> me.rebound
<function unbound at 0x7fa05efac9b0>
>>> me.rebound()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound() takes exactly 1 argument (0 given)
The 'instancemethod' type can be used to bind a 'function' to an object. It's in the types
module as MethodType
.
>>> import types
>>> me.rebound = types.MethodType(unbound, me, Person)
Now it's bound properly.
>>> type(me.rebound)
<type 'instancemethod'>
>>> me.rebound()
Hi, I'm unbound.
>>> # Not true any more!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With