2017-04-12 31 views
-1

我有一個問題「迴歸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 problem,但我不明白什麼是利益」迴歸自我「

請我需要一個簡單的答案,因爲我會說一點英語

+0

定義好處? –

+0

[文檔中的'__iter__'](https://docs.python.org/3/reference/datamodel.html#object.__iter__)。你可以開始閱讀。簡短回答:'__iter__'返回'self',因爲它需要迭代器。 – Matthias

+0

@艾略特羅伯茨什麼是使用? – AmrElgendy

回答

1

從返回self方法僅僅意味着你的方法返回一個對它被調用的實例對象的引用。有時候可以看到這種方法在面向對象的API中使用,這些API設計爲fluent interface,鼓勵method cascading。因此,例如,

>>> 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' 
>>> 

的一個地方,你經常看到這是當你的類實現了iterator協議,在一個迭代器,其中iter通過返回self約定,雖然這是由the docs建議:

在看到迭代器協議背後的機制,很容易 添加迭代器行爲的類。定義一個__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 
>>> 
+0

謝謝,很好的解釋 – AmrElgendy

+0

@AmrElgendy歡迎您。我在最後添加了一點信息,所以請查看最新的編輯。 –

1

這是不必要的複雜代碼。很少關注它。地球上沒有理由以這種方式實施它。

話雖這麼說,他們做的是這樣的:

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 
+0

是指'self.a = 0 self.b = 1'是否會執行一次? – AmrElgendy

+0

@AmrElgendy'__iter__'運行一次以初始化一個迭代器(也就是說,一個帶有__next__方法的對象),並在'__next__'方法中使用'self.a'和'self.b'。這是一個愚蠢的方式來實現該對象。 –

+0

對不起,這是最後一個問題 我的理解是'__iter__'函數從'__next__'調用它的一次是正確的? – AmrElgendy