第7章 类和Iterators
(1)定义类,只要以保留字class开头,然后跟随“类名”就可以:
class PapayaWhip: ①
pass
②
- 类名PapayaWhip,并且它没有继承任何其它类。通常类名大写单词首字母,这是个习俗不是语法要求。
- 类中的的语句都要缩进,第一句没有缩进的语句,代表类的结束。pass是一个占位关键字,不执行任何操作。
(2)C++程序员可能会感觉奇怪,这个类中没有构造函数也没有析构函数,但是在python中有另一个类似的方法:__init__()
class Fib:
'''iterator that yields numbers in the Fibonacci sequence''' ①
def __init__(self, max): ②
- 类和模块、函数一样可以有docstring
- __init__()方法在实例建立后会被立即调用。技术上讲不应该手动调用这个方法。
- 每一个类的方法中的第一个参数(包含__init__()方法),一直是类实例的引用——根据习俗被命名为self。这个参数占据了c++和java的this保留字的位置,但是self在python中并不是一个保留字,仅仅是一个命名习惯。(注:非常强硬的习俗,不要用别的,只用self,记住)
- 在__init__()方法中self指向一个新建对象;在类的其它方法中它指向调用方法的实例。虽然在定义方法时要显示的写self,但在调用方法的时候不用显示的写self。
(3)实例化一个类,就像使用函数一样,写上__init__()所需的参数就可以:
>>> import fibonacci2
>>> fib = fibonacci2.Fib(100) ①
>>> fib ②
<fibonacci2.Fib object at 0x00DB8810>
>>> fib.__class__ ③
<class 'fibonacci2.Fib'>
>>> fib.__doc__ ④
'iterator that yields numbers in the Fibonacci sequence'
- 创建了一Fib类的实例(fibonacci2模块包),新建的实例分配到变量fib上。所传的参数正是__init__()方法的第二个参数。
- 现在fib是Fib类的一个实例了。
- 每个类实例都有一个内建属性__class__——它指明对象的类。
- 可以访问类的docstring,一个类的所有实例共享相同的docstring.
(4)实例变量
定义在类内部的变量,归属于类
(5)Iterator——迭代器
- 迭代器就是类中定义的__iter__()方法。
- 在类上调用next()时,类中的__next__()方法会被调用。不要在__next__()方法里使用yield返回值,用return代替。
- 以for n in Fib(1000)为例解释其中发生了什么:
首先,Fib(1000)建立了一个实例,假设名为fib_inst;
其次,for循环会调用iter(fib_inst),它会执行fib__inst.__iter__(),返回一个迭代器对象——假设名为fib_iter。
然后,for循环会调用next(fib_iter)——fib_iter.__next__(),for循环会得到这个调用的返回值,并把它赋给n,然后再进入循环体。
最后,当__next__()引发一个StopIteration异常时,循环停止。
def __iter__(self):
self.a=0
self.b=1
return self
def __next__(self):
fib=self.a
if ifb > self.max:
raise StopIteration
self.a, self.b = self.b, self.a+self.b
return fib