Purpose of return self python

2024/11/19 22:47:43

I have a problem with return self

class Fib: def __init__(self, max):self.max = maxdef __iter__(self): self.a = 0self.b = 1return selfdef __next__(self):fib = self.aif fib > self.max:raise StopIterationself.a, self.b = self.b, self.a + self.breturn fib

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

Answer

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 toadd iterator behavior to your classes. Define an __iter__() methodwhich returns an object with a __next__() method. If the classdefines __next__(), then __iter__() can just return self:

class Reverse:"""Iterator for looping over a sequence backwards."""def __init__(self, data):self.data = dataself.index = len(data)def __iter__(self):return selfdef __next__(self):if self.index == 0:raise StopIterationself.index = self.index - 1return 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
>>>
https://en.xdnf.cn/q/26309.html

Related Q&A

tempfile.TemporaryDirectory context manager in Python 2.7

Is there a way to create a temporary directory in a context manager with Python 2.7?with tempfile.TemporaryDirectory() as temp_dir:# modify files in this dir# here the temporary diretory does not exis…

Matplotlib returning a plot object

I have a function that wraps pyplot.plt so I can quickly create graphs with oft-used defaults:def plot_signal(time, signal, title=, xlab=, ylab=,line_width=1, alpha=1, color=k,subplots=False, show_grid…

Where is the history file for ipython

I can not determine where the ipython is storing its history.a. There is no ~/.pythonhistory:12:49:00/dashboards $ll ~/.py* ls: /Users/steve/.py*: No such file or directoryb. Nothing special in the pyt…

How do I find what is using memory in a Python process in a production system?

My production system occasionally exhibits a memory leak I have not been able to reproduce in a development environment. Ive used a Python memory profiler (specifically, Heapy) with some success in th…

In Django is there a way to display choices as checkboxes?

In the admin interface and newforms there is the brilliant helper of being able to define choices. You can use code like this:APPROVAL_CHOICES = ((yes, Yes),(no, No),(cancelled, Cancelled), )client_app…

How to get the first 2 letters of a string in Python?

Lets say I have a string str1 = "TN 81 NZ 0025" two = first2(str1) print(two) # -> TNHow do I get the first two letters of this string? I need the first2 function for this.

Python sqlite3 version

Python 2.6.2 (r262:71605, Apr 14 2009, 22:40:02) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >…

Python debugger (pdb) stopped handlying up/down arrows, shows ^[[A instead

I am using python 2.6 in a virtualenv on an Ubuntu Linux 11.04 (natty) machine. I have this code in my (django) python code:import pdb ; pdb.set_trace()in order to launch the python debugger (pdb).Up u…

Un-persisting all dataframes in (py)spark

I am a spark application with several points where I would like to persist the current state. This is usually after a large step, or caching a state that I would like to use multiple times. It appears …

Can pip (or setuptools, distribute etc...) list the license used by each installed package?

Im trying to audit a Python project with a large number of dependencies and while I can manually look up each projects homepage/license terms, it seems like most OSS packages should already contain the…