Цель возвращения self python
у меня проблема с 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
Я уже видел этот вопрос возвращение проблемы с собой но я не могу понять, в чем польза return self
?
2 ответов
возвращение self
метод просто означает, что ваш метод возвращает ссылку на экземпляр объекта, на который он был вызван. Это иногда можно увидеть в использовании с объектно-ориентированными API, которые разработаны как свободно интерфейс что побуждает метод каскадного. Так, например,
>>> 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()
теперь мы можем использовать каскадный метод:
>>> c.increment().increment().decrement()
<__main__.Counter object at 0x1020c1390>
обратите внимание на последний вызов decrement()
вернулся <__main__.Counter object at 0x1020c1390>
, которым и self
.
Теперь:
>>> c.val
2
>>>
обратите внимание, вы не можете сделать это, если вы не вернули 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
>>>
обратите внимание, не все являются поклонниками "каскадного метода" дизайна. Встроенные Python не имеют тенденцию делать это, поэтому,list
например:
>>> 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'
>>>
вы do часто вижу это, когда ваш класс реализует iterator
протоколу, где iter
на итератор возвращает self
по соглашению, хотя это предложено документы:
увидев механику за протоколом итератора, легко добавьте поведение итератора в свои классы. Определите
__iter__()
способ который возвращает объект с__next__()
метод. Если класс определяет__next__()
, потом__iter__()
может просто вернуться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]
обратите внимание, что это фактически делает ваш итератор полезным только для одного прохода:
>>> 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
>>>
это бесполезно сложный код. Не обращайте на это внимания. На земле нет причин реализовывать его таким образом.
Это, как говорится, то, что он делает это:
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
Это все гораздо проще выразить как:
def fib(max_):
a, b = 0, 1
while b <= max_:
out = a
a, b = b, a+b
yield out
примеры:
>>> 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