2017-04-12 48 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