Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Purpose of return self python

Tags:

python

return

I have a problem with return self

class Fib:      def __init__(self, max):         self.max = max     def __iter__(self):          self.a = 0         self.b = 1         return self     def __next__(self):         fib = self.a         if fib > self.max:             raise StopIteration         self.a, self.b = self.b, self.a + self.b         return fib 

I have already seen this question return self problem but I can't understand what the benefit is of return self?

like image 375
AmrElgendy Avatar asked Apr 12 '17 21:04

AmrElgendy


People also ask

Why do we return self in Python?

Need for Self in Python Python uses the self parameter to refer to instance attributes and methods of the class. Unlike other programming languages, Python does not use the “@” syntax to access the instance attributes. This is the sole reason why you need to use the self variable in Python.

Is it mandatory to use self in Python?

Self is a convention and not a Python keyword . self is parameter in Instance Method and user can use another parameter name in place of it. But it is advisable to use self because it increases the readability of code, and it is also a good programming practice.

What is __ init __( self in Python?

The self in keyword in Python is used to all the instances in a class. By using the self keyword, one can easily access all the instances defined within a class, including its methods and attributes. init. __init__ is one of the reserved methods in Python. In object oriented programming, it is known as a constructor.

What is the self variable in Python?

Python self variable is used to bind the instance of the class to the instance method. We have to explicitly declare it as the first method argument to access the instance variables and methods. This variable is used only with the instance methods.

What does return self from an instance mean in Python?

Answer Wiki. Python return self from an instance method is an idiom to allow method chaining. Imagine I have a class Foo from which I instantiate an instance foo. Perhaps I want to load some data from a file, process it and save the results to a database.

What is the use of return in Python?

The Python return statement is a key component of functions and methods. You can use the return statement to make your functions send Python objects back to the caller code. These objects are known as the function’s return value. You can use them to perform further computation in your programs.

What is the purpose of using “self” in Python?

The purpose of using self is that Python does not use the ‘@’ syntax to refer to instance attributes. In Python methods do in a way that makes the instance to be passed automatically, but not received automatically.

What is the difference between Chaining and returning self in Python?

Suffice it to say, returning self is the definitive OO way to craft class methods, but Python allows for multiple return values, tuples, lists, objects, primitives, or None. Chaining, as they put it, is merely putting the answer to the last operation into the next, and the runtime of Python can optimize that kind of thing.


2 Answers

Returning self from a method simply means that your method returns a reference to the instance object on which it was called. This can sometimes be seen in use with object oriented APIs that are designed as a fluent interface that encourages method cascading. So, for example,

>>> class Counter(object): ...     def __init__(self, start=1): ...         self.val = start ...     def increment(self): ...         self.val += 1 ...         return self ...     def decrement(self): ...         self.val -= 1 ...         return self ... >>> c = Counter() 

Now we can use method cascading:

>>> c.increment().increment().decrement() <__main__.Counter object at 0x1020c1390> 

Notice, the last call to decrement() returned <__main__.Counter object at 0x1020c1390>, which is self. Now:

>>> c.val 2 >>> 

Notice, you cannot do this if you did not return self:

>>> class Counter(object): ...     def __init__(self, start=1): ...         self.val = start ...     def increment(self): ...         self.val += 1 ...         # implicitely return `None` ...     def decrement(self): ...         self.val -= 1 ...         # implicitely return `None` ... >>> c = Counter() >>> c.increment().increment() Traceback (most recent call last):   File "<stdin>", line 1, in <module> AttributeError: 'NoneType' object has no attribute 'increment' >>> c <__main__.Counter object at 0x1020c15f8> >>> c.val 2 >>> 

Notice, not everyone is a fan of "method cascading" design. Python built-ins do not tend do this, so, list for example:

>>> x = list() >>> x.append(1).append(2) Traceback (most recent call last):   File "<stdin>", line 1, in <module> AttributeError: 'NoneType' object has no attribute 'append' >>> 

The one place you do often see this is when your class implements the iterator protocol, where iter on an iterator returns self by convention, although this is suggested by the docs:

Having seen the mechanics behind the iterator protocol, it is easy to add iterator behavior to your classes. Define an __iter__() method which returns an object with a __next__() method. If the class defines __next__(), then __iter__() can just return self:

class Reverse:     """Iterator for looping over a sequence backwards."""     def __init__(self, data):         self.data = data         self.index = len(data)      def __iter__(self):         return self      def __next__(self):         if self.index == 0:             raise StopIteration         self.index = self.index - 1         return self.data[self.index] 

Notice, this in effect makes your iterator only useful for a single pass (as it should be to properly follow the iterator protocol):

>>> x = [1, 2, 3, 4] >>> it = iter(x) >>> list(it) [1, 2, 3, 4] >>> list(it) [] >>> next(it) Traceback (most recent call last):   File "<stdin>", line 1, in <module> StopIteration >>> 
like image 175
juanpa.arrivillaga Avatar answered Sep 18 '22 21:09

juanpa.arrivillaga


This is needlessly complex code. Pay little attention to it. There's no reason on earth to implement it this way.

That being said, what it does is this:

class Fib:       """Implements the Fibonacci sequence."""      def __init__(self, max_):         self.max = max_      def __iter__(self):         """Initializes and returns itself as an iterable."""          self.a = 0         self.b = 1         return self      def __next__(self):         """What gets run on each execution of that iterable."""          fib = self.a         if fib > self.max:             raise StopIteration         self.a, self.b = self.b, self.a + self.b  # increment         return fib 

This is all much easier to express as:

def fib(max_):     a, b = 0, 1     while b <= max_:         out = a         a, b = b, a+b         yield out 

Examples:

>>> fib_obj = Fib(20) >>> for n in fib_obj: ...     print(n)  >>> for n in Fib(20): ...     print(n)  >>> for n in fib(20): ...     print(n) # all give.... 0 1 1 2 3 5 8 13 
like image 27
Adam Smith Avatar answered Sep 19 '22 21:09

Adam Smith