python and using 'self' in methods - python

From what I read/understand, the 'self' parameter is similiar to 'this'.
Is that true?
If its optional, what would you do if self wasnt' passed into the method?

Yes, it's used in similar ways. Note that it's a positional parameter and you can call it what you want; however there is a strong convention to call it self (not this or anything else). Some positional parameter must be there for a usable instance method; it is not optional.

The joy of Python
That is true to some extend. Methods are bound to the object instance they are a part of. When you see
def some_func(self, foo, bar)
The passing of self is sometimes implicit when you call, for example:
obj.some_func(foo_val, bar_val)
Which is equal (presuming obj is of class MyClass) to
MyClass.some_func(obj, foo_val, bar_val)
Because the method is bound to obj, the self argument gets populated. This is part of Python being explicit with what it means. In other languages, this just pops into scope, with Python there is some exposure of how this happens.
You can also pass methods around, and manually pass them self when not calling from a bound context.
The Python docs do a good Job:
xf = x.f
while True:
print xf()
will continue to print hello world until the end of time.
What exactly happens when a method is called? You may have noticed that x.f() was called >without an argument above, even though the function definition for f() specified an >argument. What happened to the argument? Surely Python raises an exception when a function >that requires an argument is called without any — even if the argument isn’t actually >used...
Actually, you may have guessed the answer: 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.

self is this, just you have to explicitly pass it and explicitly use it to refer to class methods/properties.
It isn't optional in class methods. You will get a TypeError if you try to define a classmethod without at least one argument (i.e., the self parameter).
However, you can call it something other than self, but I have never seen otherwise.

self refers to the object on which the method was called, much like this in C++. But it is important that self is merely a convention, you can name it as you like and pass instances of subclasses.

In classes a self variable (or cls for classmethods) is required. What you want to call it is your decision though. If you prefer you could call it this instead.
A classmethod is a method that gets the class as a first argument instead of a instance. It can be called without passing an instance.
i.e. with a classmethod you can do:
SomeObject.some_class_method()
while a normal method would require you to do
SomeObject().some_normal_method()
or
SomeObject.some_normal_method(instance)

self is definitely similar to this, however, in Python, the name self is just a convention, and could be named anything else. The variable is named after whatever you call it in the function's prototype (def function(whatever, params...):).
For instance methods, self IS actually required. For class or static methods, you need to specify that they should be treated as such, and then self is not required. For example:
def type_to_display(type):
"""Converts a pass type to the full written pass type."""
return list((pair[1] for pair in Pass.TYPE_CHOICES if pair[0] ==
type[0:1].upper()))[0]
type_to_display = staticmethod(type_to_display)
You will never be able to use an instance method in such a way that self is not passed in. For example, if I have an instance my_car of a Car class, and I use the Car class's drive instance method, the my_car instance will be implicitly passed into the drive method as the first parameter (self).
class Car:
def drive(self):
self.do_some_stuff()
my_car = Car()
my_car.drive() # actually calls Car.drive(my_car)

Related

Calling a method of a class before creating an object

Let's say we have a class, and we are calling it's method before creating an object:
class ParentClass:
def MyMethod(self):
self.a=5
print("I am Method")
ParentClass.MyMethod(ParentClass)
Why do we get a result?
Also, why hasattr(ParentClass,'a') is showing that instance variable is created?
You get a result because you ParentClass.MyMethod evaluates to a regular function that takes one argument, which you supplied. The function doesn't care what the type of self is, as long as you can define an attribute named a for it. The result of ParentClass.MyMethod(ParentClass) is to add an attribute named a to ParentClass.
ParentClass().MyMethod, on the other hand, produces an instance of method that wraps the function, due to the descriptor protocol. The method, when called, simply calls the function with the instance as the first argument and the rest of its own arguments. Because the function doesn't expect any more arguments, you would get a TypeError.

Are all methods are preceded by a dot(.) or just some of them. How do we define it needs a dot or not?

I was learning Python by using Python Crash Course and came upon this String and Method thing: It only said that the dot(.) after name in name.title() tells Python to make the title() method act on the variable name.
Not always, you can create a method dynamically:
from types import MethodType
def fn(x):
return x.var
class A:
def __init__(self):
self.var = 20
obj = A()
method_ = MethodType(fn, obj)
print(method_)
print(method_())
output :
<bound method fn of <__main__.A object at 0x000001C5E3F01FD0>>
20
A method is an instance of type MethodType and also it has an object bound to it, when method gets called, it's first parameter will always get filled with that object. Here fn() function's first parameter (x) will be filled with obj object.
The above answer is precise but i wanted to add to it.
Actually methods are functions that take objects as arguments and then return values based on that and as python is an Object Oriented Language therefore everything in python is an object.
When you call name.title():
then, python search for the title() method for the name object.And as all methods are designated to take the object as an argument:
`def title(self):
...+
`
This is what a method definition look like inside a class and the self argument here stands for the object calling the method.
And we do not have to specify it explicitly it is recognised by the python interpreter.
As in your case: name.title() the object calling the method title() is the name variable therefore here self is assigned the value of name that is the function call name.title() is equivalent to title(name) but the former is the correct syntax of calling the method whereas the latter one is for comprehesion purpose.
If you run title(name) it surely gonna raise an error.
But, as the title() method belongs to the str class you can always call str.title(name).
Hope i didn't confuse you instead of making it clearer...Happy coding..:)

how self can be passed while inheritance?

class Trout(Fish):
def __init__(self, water = "freshwater"):
self.water = water
super().__init__(self)
In this line super().__init__(self) how is the self parameter passed to the function?
Say you have the code
f = Trout()
Behind the scenes, this is roughly equivalent to
f = Trout.__new__()
Trout.__init__(f)
Inside Trout.__init__, super() returns a proxy object that represents the appropriate class in the method resolution order of Trout; you don't actually have to pass self as an explicit argument; super().__init__ defaults to a bound method with self already present.
The object calling the method is implicitly (automatically) the first argument to the method. This is an agreement the language makes with itself.
In practical terms, assume you have an object obj of some type that has a method stuff that takes a simple Boolean argument. You invoke the method as
obj.stuff(True)
If this were a "normal" function, you would invoke it as
stuff(obj, True)
... but that's not how the syntax of classes and objects works. In any case, the function/method header looks the same:
def stuff(self, flag):
The difference here is that the each object class can have a method stuff, and we don't have to give them different names. When we use class methods, the compiler knows which one to use by looking at the class of the invoking object.
In the specific case of the __init__ method, the object is created immediately upon entry and assigned to self. This is another automatic agreement the language makes with itself: this specially-named function includes an invisible creation of a default object when you enter.

Explicit passing of Self when calling super class's __init__ in python

This question is in relation to posts at What does 'super' do in Python? , How do I initialize the base (super) class? , and Python: How do I make a subclass from a superclass? which describes two ways to initialize a SuperClass from within a SubClass as
class SuperClass:
def __init__(self):
return
def superMethod(self):
return
## One version of Initiation
class SubClass(SuperClass):
def __init__(self):
SuperClass.__init__(self)
def subMethod(self):
return
or
class SuperClass:
def __init__(self):
return
def superMethod(self):
return
## Another version of Initiation
class SubClass(SuperClass):
def __init__(self):
super(SubClass, self).__init__()
def subMethod(self):
return
So I'm a little confused about needing to explicitly pass self as a parameter in
SuperClass.__init__(self)
and
super(SubClass, self).__init__().
(In fact if I call SuperClass.__init__() I get the error
TypeError: __init__() missing 1 required positional argument: 'self'
). But when calling constructors or any other class method (ie :
## Calling class constructor / initiation
c = SuperClass()
k = SubClass()
## Calling class methods
c.superMethod()
k.superMethod()
k.subMethod()
), The self parameter is passed implicitly .
My understanding of the self keyword is it is not unlike the this pointer in C++, whereas it provides a reference to the class instance. Is this correct?
If there would always be a current instance (in this case SubClass), then why does self need to be explicitly included in the call to SuperClass.__init__(self)?
Thanks
This is simply method binding, and has very little to do with super. When you can x.method(*args), Python checks the type of x for a method named method. If it finds one, it "binds" the function to x, so that when you call it, x will be passed as the first parameter, before the rest of the arguments.
When you call a (normal) method via its class, no such binding occurs. If the method expects its first argument to be an instance (e.g. self), you need to pass it in yourself.
The actual implementation of this binding behavior is pretty neat. Python objects are "descriptors" if they have a __get__ method (and/or __set__ or __delete__ methods, but those don't matter for methods). When you look up an attribute like a.b, Python checks the class of a to see if it has a attribute b that is a descriptor. If it does, it translates a.b into type(a).b.__get__(a, type(a)). If b is a function, it will have a __get__ method that implements the binding behavior I described above. Other kinds of descriptors can have different behaviors. For instance, the classmethod decorator replaces a method with a special descriptor that binds the function the class, rather than the instance.
Python's super creates special objects that handle attribute lookups differently than normal objects, but the details don't matter too much for this issue. The binding behavior of methods called through super is just like what I described in the first paragraph, so self gets passed automatically to the bound method when it is called. The only thing special about super is that it may bind a different function than you'd get lookup up the same method name on self (that's the whole point of using it).
The following example might elucidate things:
class Example:
def method(self):
pass
>>> print(Example.method)
<unbound method Example.method>
>>> print(Example().method)
<bound method Example.method of <__main__.Example instance at 0x01EDCDF0>>
When a method is bound, the instance is passed implicitly. When a method is unbound, the instance needs to be passed explicitly.
The other answers will definitely offer some more detail on the binding process, but I think it's worth showing the above snippet.
The answer is non-trivial and would probably warrant a good article. A very good explanation of how super() works is brilliantly given by Raymond Hettinger in a Pycon 2015 talk, available here and a related article.
I will attempt a short answer and if it is not sufficient I (and hopefully the community) will expand on it.
The answer has two key pieces:
Python's super() needs to have an object on which the method being overridden is called, so it is explicitly passed with self. This is not the only possible implementation and in fact, in Python 3, it is no longer required that you pass the self instance.
Python super() is not like Java, or other compiled languages, super. Python's implementation is designed to support the multiple collaborative inheritance paradigm, as explained in Hettinger's talk.
This has an interesting consequence in Python: the method resolution in super() depends not only on the parent class, but on the children classes as well (consequence of multiple inheritance). Note that Hettinger is using Python 3.
The official Python 2.7 documentation on super is also a good source of information (better understood after watching the talk, in my opinion).
Because in SuperClass.__init__(self), you're calling the method on the class, not the instance, so it cannot be passed implicitly. Similarly you cannot just call SubClass.subMethod(), but you can call SubClass.subMethod(k) and it'll be equivalent to k.subMethod(). Similarly if self refers to a SubClass then self.__init__() means SubClass.__init__(self), so if you want to call SuperClass.__init you have to call it directly.

python method as argument

So I know in python everything is an 'object' meaning that it can be passed as an argument to a method. But I'm trying to understand how exactly does this work. So I was trying out the following example:
class A:
def __init__(self):
self.value = 'a'
def my_method(self)
print self.value
class B:
def __init__(self):
self.values = 'b'
def my_method(self, method):
method()
a = A()
b = B()
b.my_method(a.my_method)
Now first this was written just to see how things work. I know I should for example check if my_method 's argument is callable. Now my question is:
How exactly is the method passed here? I mean the output I'm recieving is 'a' so I'm guessing that when a object method is passed as parameter so is the actual object ? In this case when I pass a.my_method the instance a is also passed ?
When you access a.my_method Python sees that it is an attribute of the class and that A.my_method has a method __get__() so it calls A.my_method.__get__(a), that method creates a new object (the 'bound method') which contains both a reference to A.my_method and a reference to a itself. When you call the bound method it passes the call back through to the underlying method.
This happens every time you call any method whether you call it directly or, as in your code, delay the actual call until later. You can find more description of the descriptor protocol as it is known at http://docs.python.org/reference/datamodel.html#descriptors
How exactly is the method passed here?
This is easily answered: in Python, everything is an object :) Also functions/methods, which are specific function objects which can be passed as parameters.
In this case when I pass a.my_method the instance a is also passed?
Yes, in this case the instance a is also passed, though embedded in the function object and cannot be retrieved. On the contrary you could pass the function itself and supply it with an instance. Consider the following example:
b = B()
func = A.my_method # Attention, UPPERCASE A
func(b)
This would call the A classes method my_method with an instance of B.
Functions are 'first-class objects' in Python. What that means is that a function is an object as much as a list or an integer. When you define a function, you are actually binding the function object to the name you use in the def.
Functions can be bound to other names or passed as parameters to functions (or stored in lists, or...).
source: http://mail.python.org/pipermail/tutor/2005-October/042616.html
a.my_method returns not exactly the function you defined in the class A (you can get it via A.my_method) but an object called a 'bound method' which contains both the original function (or 'unbound method' in Python 2, IIRC) and the object from which it was retrieved (the self argument).

Categories

Resources