一、构造方法
构造方法和其他普通方法不同之处在于,当一个对象被创建后,会立即调用构造方法。创建构造方法时只需要吧init方法修改为__init__即可:
class Foobar:
def __init__(self):
self.somevar=42
>>> f=Foobar()
>>> f.somevar
42
注意:在Python中__del__方法,也就是析构方法。它在对象就要被垃圾回收之前调用。但是发生的具体时间是不可知的,所以少用该方法。
1、重写一般方法和特殊的构造方法
如果一个方法在B类的一个实例中被调用(或者一个属性被访问)但在B类中没有找到该方法,那么就会去它的超类A里面找。
class A:
def hello(self):
print "Hello,I'm A."
class B(A):
pass
>>> a=A()
>>> b=B()
>>> a.hello()
Hello,I'm A.
>>> b.hello()
Hello,I'm A.
如果一个类的构造方法被重写,那么就需要调用超类的构造方法,否则对象可能不能正确初始化:
class Bird:
def __init__(self):
self.hungry=True
def eat(self):
if self.hungry:
print 'Aaaah....'
self.hungry=False
else:
print 'No,thanks!'
class 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 "", line 1, in
sb.eat()
File "C:/Users/Administrator.USER-20170615PK/Desktop/9/6.py", line 5, in eat
if self.hungry:
AttributeError: SongBird instance has no attribute 'hungry'
由上述代码可以看出,SongBird是bird的一个子类,它继承了eat方法,但是在调用eat方法时出现了错误。有以下两种解决方案:
1.1 调用未绑定的超类构造方法
class Bird:
def __init__(self):
self.hungry=True
def eat(self):
if self.hungry:
print 'Aaaah....'
self.hungry=False
else:
print 'No,thanks!'
class SongBird(Bird):
def __init__(self):
Bird.__init__(self)
self.sound='Squawk!'
def sing(self):
print self.sound
>>> sb=SongBird()
>>> sb.sing()
Squawk!
>>> sb.eat()
Aaaah....
>>> sb.eat()
No,thanks!
在调用一个实例的方法时,该方法的self参数会被自动绑定到实例上,这被称为绑定方法。但是如果直接调用类的方法(比如Bird.__init__)那么就没有实例会被绑定。这样就可以自由地提供需要的self参数。这样的方法称为未绑定方法。
1.2 使用super函数
super函数只能在新式类中使用。当前的类和对象可以作为super函数的参数使用,调用函数返回的对象的任何方法都是调用超类的方法,而不是当前类的方法。
__metaclass__=type#super函数只在新式类中起作用
class Bird:
def __init__(self):
self.hungry=True
def eat(self):
if self.hungry:
print 'Aaaah....'
self.hungry=False
else:
print 'No,thanks!'
class SongBird(Bird):
def __init__(self):
super(SongBird,self).__init__()
self.sound='Squawk!'
def sing(self):
print self.sound
二、成员访问
创建自己的序列或者映射需要实现所有的序列或者映射规则的方法,包括__getitem__和__setitem__这样的的特殊方法。通过子类化list(或UserList)和dict(或者UserDict)能节省很多工作。
__len__(self):该方法返回集合中所含项目的数量。
__getitem__(self,key):这个方法返回与所给键对应的值。
__setitem__(self,key,value):该方法应该按一定的方式存储和key相关的value。
__delitem__(self,key):该方法对一部分对象使用del语句时被调用,同时必须删除和键相关的键。
三、属性
1、property函数
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
>>> r=Rectangle()
>>> r.width=10
>>> r.height=5
>>> r.getSize()
(10, 5)
>>> r.setSize((150,100))
>>> r.width
150
使用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.width
150
property函数创建了一个属性,其中访问器函数被用作参数(先是取值,然后是赋值),这个属性名为size。
静态方法和类成员方法在创建时分别被装入staticmethod类型和classmethod类型的对象中。静态方法的定义没有self参数,且能够被类本身直接调用。类方法在定义时需要名为cls的类似于self的参数,类成员方法可以直接用类的具体对象调用。但cls参数是自动被绑定到类的。
使用@操作符,在方法(或函数)的上方将装饰器列出,从而指定一个或者更多的装饰器(多个装饰器在应用时的顺序与指定顺序相反)。
__metaclass__=type
class MyClass:
@staticmethod
def smeth():
print 'This is a static method'
@classmethod
def cmeth(cls):
print 'This is a class method of ',cls
3、__getattr__、__setattr__和它的朋友们
__getattribute__(self,name):当特性name被访问时自动被调用(只能在新式类中使用)。
__getattr__(self,name):当特性name被访问且对象没有相应的特性是被自动调用。
__setattr__(self,name,value):当试图给特性name赋值时会被自动调用。
__delattr__(self,name):当试图删除特性name时被自动调用。
四、迭代器
只要该对象实现了__iter__方法,就可以对该对象进行迭代。
__iter__方法会返回一个迭代器,所谓的迭代器就是具有next方法(这个方法在调用时不需要任何参数)的对象。在调用next方法时,迭代器会返回它的下一个值。如果next方法被调用,但迭代器没有值可以返回,就会引发一个StopIteration异常。
正式的说法是,一个实现了__iter__方法的对象是可迭代的,一个实现了next方法的对象则是迭代器。
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 self
五、生成器
nested=[[1,2],[3,4],[5]]
def flatten(nested):
for sublist in nested:
for element in sublist:
yield element
任何包含yield语句的函数称为生成器。它不像return那样返回值,而是每次产生多个值。每次产生一个值(使用yield语句),函数就会被冻结:即函数停在那点等待被重新唤醒。函数被唤醒后就从停止的那点开始知行。