准备工作
>>> class NewStyle(object):
more_code_here
>>> class OldStyle:
more_code_here
在这两个类中,NewStyle是新式的类,OldStyle是旧式的类,如果文件以__metaclass__ = type
开始,那么两个类都是新式类。
构造方法
构造方法,当一个对象被创建后,会立即调用构造方法。Python中创建一个构造方法,只要把init方法的名字从简单的init修改成__init__
:
>>> class Foobar:
def __init__(self):
self.somevar = 42>>> f = Foobar()
>>> f.somevar
42
- 重写一般方法和特殊的构造方法
每个类都可能拥有一个或者多个超类,它们会从超类那里继承行为方式。如果一个方法在B类的一个实例中被调用,但在B类中没有找到该方法,那么就会去它的超类A里面找。考虑下面的两个类:class A:
def hello(self):
print "Hello, A!"class B(A):
passA类定义了一个叫做hello的方法,被B类继承:
>>> a=A()
>>> b = B()
>>> a.hello()
Hello, A!
>>> b.hello()
Hello, A!使用这个定义,b.hello()能产生一个不同的结果
>>> class B(A):
def hello(self):
print "B">>> b = B()
>>> b.hello()
B重写是继承机制中一个重要内容。
下例:
class Bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print ‘Aaaaah...‘
self.hungry = False
else:
print ‘No thx!‘
passclass SongBird(Bird):
def __init__(self):self.sound = ‘Squawk!‘
def sing(self):
print self.sound运行:
>>> sb = SongBird()
>>> sb.sing()
Squawk!
>>> sb.eat()Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
sb.eat()
File "C:/Users/User/Desktop/Python_Demo/c_3.py", line 5, in eat
if self.hungry:
AttributeError: SongBird instance has no attribute ‘hungry‘异常很清楚地说明了错误:SongBird没有hungry特性。原因是在SongBird中,构造方法被重写,没有初始化hungry特性的代码。
- 调用未绑定的超类构造方法
写解决上例的问题,代码如下:class Bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print ‘Aaaaah...‘
self.hungry = False
else:
print ‘No thx!‘
passclass SongBird(Bird):
def __init__(self):
Bird.__init__(self) #banding method
self.sound = ‘Squawk!‘
def sing(self):
print self.sound运行结果:
>>> sb = SongBird()
>>> sb.eat()
Aaaaah...
>>> sb.eat()
No thx!为什么会有注意的结果?在调用一个实例的方法时,该方法的self参数会被自动绑定到实例上(这被称为绑定方法)。但如果直接调用类的方法(比如Bird.__init__),那么就没有实例会被绑定。这样就可以自由地提供需要的self参数。这样的方法称为未绑定(unbound)方法。
- 使用super函数
__metaclass__ = type
class Bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print ‘Aaaaah...‘
self.hungry = False
else:
print ‘No thx!‘
passclass SongBird(Bird):
def __init__(self):
super(SongBird,self).__init__()
self.sound = ‘Squawk!‘
def sing(self):
print self.sound运行结果如下:
>>> sb = SongBird()
>>> sb.eat()
Aaaaah...
>>> sb.eat()
No thx!
成员访问
- 基本的序列和映射规则
序列和映射是对象的集合。为了实现它们基本的行为,如果对象是不可变的,那么就需要使用两个魔法方法,如果是可变的则需要使用4个。
__len__(self):这个方法应该返回集合中所含项目的数量。(序列:返回个数;映射:返回键-值对的数量;返回0,对象会被当做一个布尔变量中的假值进行处理)
__getitem__(self.key):这个方法返回与所给键对应的值。对于一个序列,键应该是一个0~n-1的整数(也可能是负数,n是序列的长度);对于映射来说,可以使用任何种类的键。
__setitem__(self,key,value):这个方法应该按一定的方式存储和key相关的value,该值随后可使用__getitem__来获取。
__delitem__(self,key):这个方法对一部分对象使用del语句时被调用,同事必须删除和元素相关的键。 - 子类化列表、字典和字符串
属性
- property 函数
__metaclass__ = type
class Rectangle:
def __init__(self):
self.width = 0
self.height = 0
def setSize(self,size):
self.width,self.height = size
def getSize(self):
return self.width,self.height
size = property(getSize,setSize)运行结果:
>>> r = Rectangle()
>>> r.width = 10
>>> r.height = 5
>>> r.size
(10, 5)
>>> r.size = 150,100
>>> r.height
100size特性仍然取决于getSize和setSize中的计算。
迭代器
- 迭代器规则
迭代的意思是重复做一些事很多次。
__iter__方法返回一个迭代器(iterator),所谓的迭代器就是具有next方法的对象。在调用next方法时,迭代器会返回它的下一个值。如果next方法被调用,但迭代器没有值可以返回,就会引发一个StopIteration异常。class Fibs:
def __init__(self):
self.a = 0
self.b = 1
def next(self):
self.a,self.b = self.b,self.a + self.b
return self.a
def __iter__(self):
return selffibs = Fibs()
for f in fibs:
if f>1000:
print f
break - 从迭代器得到序列
除了在迭代器和可迭代对象上进行迭代外,还能把它们转换为序列:class TestIterator:
value = 0
def next(self):
self.value += 1
if self.value >10:raise StopIteration
return self.value
def __iter__(self):
return self运行结果:
>>> ti = TestIterator()
>>> list(ti)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
生成器
生成器也叫简单生成器。
生成器是一种用普通的函数语法定义的迭代器。
- 创建生成器
>>> nested = [[1,2],[3,4],[5]]
>>> def flatten(nested):
for sublist in nested:
for element in sublist:
yield element>>> for num in flatten(nested):
print num1
2
3
4
5任何包含yield语句的函数称为生成器。
- 递归生成器
- 通用生成器
生成器是由两部分组成:生成器的函数和生成器的迭代器。
生成器的函数是用def语句定义的,包含yield的部分,生成器的迭代器是这个函数的返回部分 - 生成器方法
- 模拟生成器
(目前难以结合实例来学习,故此文档笔记暂时高于段落,每天开始研究自动化测试,Python核心编程课后习题)
《Python基础教程(第二版)》学习笔记 -> 第九章 魔法方法、属性和迭代器,布布扣,bubuko.com