鱼C论坛

 找回密码
 立即注册
查看: 1322|回复: 2

[已解决]关于【第48讲 魔法方法 迭代器】课堂例子的问题

[复制链接]
发表于 2020-6-30 01:05:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
大家好!关于48讲的笔记我有两个问题想请教大家!
以下是课堂笔记里的例子:

class Fibs:
    def __init__(self,n = 20):
        self.a = 0
        self.b = 1
        self.n = n

    def __iter__(self):
        return self

    def __next__(self): #============================>问题0
        self.a, self.b = self.b, self.a + self.b  #================>问题1
        if self.a > self.n:
            raise StopIteration #=========================>问题2
        return self.a

问题0:
__next__(self)里的这个self是不是已经不是普通的self,而是被iter了的self ?
如果我在Fibs里再定义一些其他的魔法方法,那么那些魔法方法里的self是普通的self 还是被iter了的self?

问题1:
self.a, self.b = self.b, self.a + self.b,
可不可以把这一行拆成下面这两行:
self.a = self.b            #======第一行
self.b = self.a+self.b  #======第二行
那么我的问题是 :
首先,把这一行拆成两行是100%等效的吗?
其次,第二行里的self.a其实已经在第一行里被赋值成为self.b了,那么第二行其实就是self.b = self.b + self.b了,那么这就无法构成fibs数列了,但看运算结果依然构成了fibs数列。为什么?

问题2:raise StopIteration
为什么程序跑到此处的时候不报错,而是就默默的停止了呢?raise一个错误的话不是应该出红字报错吗?

谢谢!
最佳答案
2020-6-30 08:37:43



问题0:
__next__(self)里的这个self是不是已经不是普通的self,而是被iter了的self ?
如果我在Fibs里再定义一些其他的魔法方法,那么那些魔法方法里的self是普通的self 还是被iter了的self?


self 还是那个self ,就是代表被实例化的对象,不懂你的 iter 的 self 是什么东西.... ,当你的类中定义了 __iter__ 和 __next__ 就算是一个迭代器了,你可以通过 next 来依次查看迭代器的返回结果

直接用 for 循环也行,for 循环会捕获 StopIteration 抛出错误,当这个错误抛出时,自动停止 for 循环


问题1:
首先,把这一行拆成两行是100%等效的吗?


是不能等效的, self.a, self.b = self.b, self.a + self.b  都是还未进行增加的值,进行改变,也就是 self.a 和 self.b 是同时被赋值的,而不是 self.a 先被赋值改变 然后再计算 self.b

直接拿个代码测试下你就知道:
# 第一个代码
a = 1
b = 2
a,b = b,a+1
print(a,b)

# 第二个代码
a = 1
b = 2
a = b
a = a+1

print(a,b)

其次,第二行里的self.a其实已经在第一行里被赋值成为self.b了,那么第二行其实就是self.b = self.b + self.b了,那么这就无法构成fibs数列了,但看运算结果依然构成了fibs数列。为什么?


完全是两种情况,你看下上面的问题和代码,举个例子,第一个代码是将 a = 1 b = 2 同时赋值给 等号右边的 b,a+1

而你写成两行 即:
a = b
a = a+1
是把 a 先进行改变了 在重新赋值a,就通你所说。这肯定不是斐波那契数列,运算结果并没有构成了fibs数列

问题2:raise StopIteration
为什么程序跑到此处的时候不报错,而是就默默的停止了呢?raise一个错误的话不是应该出红字报错吗?

当你用 for 循环来遍历一个迭代器时候,会捕获这个迭代器的 StopIteration 报错,来停止 for 循环

如果你没用 for 循环 而是不停的 next() 那么当迭代器没有元素可迭代了就会抛出 StopIteration 报错




想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-6-30 08:37:43 | 显示全部楼层    本楼为最佳答案   



问题0:
__next__(self)里的这个self是不是已经不是普通的self,而是被iter了的self ?
如果我在Fibs里再定义一些其他的魔法方法,那么那些魔法方法里的self是普通的self 还是被iter了的self?


self 还是那个self ,就是代表被实例化的对象,不懂你的 iter 的 self 是什么东西.... ,当你的类中定义了 __iter__ 和 __next__ 就算是一个迭代器了,你可以通过 next 来依次查看迭代器的返回结果

直接用 for 循环也行,for 循环会捕获 StopIteration 抛出错误,当这个错误抛出时,自动停止 for 循环


问题1:
首先,把这一行拆成两行是100%等效的吗?


是不能等效的, self.a, self.b = self.b, self.a + self.b  都是还未进行增加的值,进行改变,也就是 self.a 和 self.b 是同时被赋值的,而不是 self.a 先被赋值改变 然后再计算 self.b

直接拿个代码测试下你就知道:
# 第一个代码
a = 1
b = 2
a,b = b,a+1
print(a,b)

# 第二个代码
a = 1
b = 2
a = b
a = a+1

print(a,b)

其次,第二行里的self.a其实已经在第一行里被赋值成为self.b了,那么第二行其实就是self.b = self.b + self.b了,那么这就无法构成fibs数列了,但看运算结果依然构成了fibs数列。为什么?


完全是两种情况,你看下上面的问题和代码,举个例子,第一个代码是将 a = 1 b = 2 同时赋值给 等号右边的 b,a+1

而你写成两行 即:
a = b
a = a+1
是把 a 先进行改变了 在重新赋值a,就通你所说。这肯定不是斐波那契数列,运算结果并没有构成了fibs数列

问题2:raise StopIteration
为什么程序跑到此处的时候不报错,而是就默默的停止了呢?raise一个错误的话不是应该出红字报错吗?

当你用 for 循环来遍历一个迭代器时候,会捕获这个迭代器的 StopIteration 报错,来停止 for 循环

如果你没用 for 循环 而是不停的 next() 那么当迭代器没有元素可迭代了就会抛出 StopIteration 报错




想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-7-1 11:18:24 | 显示全部楼层
谢谢大神的详细讲解!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-20 04:45

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表