继续第十二章 类与对象(多态及多重继承、type和instance、特殊属性__doc__和__name__、特殊方法__str()__、__repr()__、__iter()__)
一、多态。之前已经有说明基类与衍生类有相同方法名称的实例,其实那就是本节欲说明的多态(polymorphism)的基本观念,但是多态的概念是不局限在必须有父子关系的类中的。可以将多态想成方法多功能化,相同的函数名称,放入不同类型的对象可以产生不同的结果:
class Animals():
def which(self):
return 'It is animal'
class Dogs(Animals):
#继承动物类
def which(self):
return 'It is dog'
class Monkeys(Animals):
#继承动物类
def which(self):
return 'It is monkey'
def doing(obj): #可传递不同对象参数的函数
print(obj.which()) #根据不同对象调用不同方法
#以下为主程序
animal = Animals()
doing(animal)
dog = Dogs()
doing(dog)
monkey = Monkeys()
doing(monkey)
在面向对象的程序设计中,也常会发生一个类继承多个类的应用,此时子类也同时继承了多个类的方法。在这个时候,读者应该了解当多个父类拥有相同名称的方法时,应该先执行哪一个父类的方法。在程序中可用下列语法代表继承多个类:class 类名称(父类名称1, ..., 父类名称n):
class Grandfather():
""" 祖父类 """
def action1(self):
print("Grandfather")
class Father(Grandfather):
""" 父亲类 """
def action2(self):
print("Father")
class Uncle(Grandfather):
""" 叔叔类 """
def action2(self):
print("Uncle")
class Son(Uncle, Father):
""" 子类 """
def action3(self):
print("Son")
son = Son()
son.action3()
son.action2() #多继续父类中有同名方法,优先调用在前面定义的父类方法
son.action1()
二、type和instance。可以使用type( )函数得到某一对象变量的类型:
class Grandfather():
""" 祖父类 """
pass
class Father(Grandfather):
""" 父亲类 """
pass
class Son(Father):
""" 子类 """
def action(self):
pass
grandfather = Grandfather()
father = Father()
son = Son()
print("grandfather对象类型:", type(grandfather))
print("father对象类型:", type(father))
print("son对象类型:", type(son))
print("son对象中acion方法类型:", type(son.action))
isinstance( )函数可以传回对象的类是否属于某一类,它包含2个参数,它的语法如下:isinstance(对象, 类)。如果对象的类是属于第2个参数类或属于第2个参数的子类,则传回True,否则传回False。
三、特殊属性和特殊方法。当设计或是看到别人设计的Python程序时,若是遇到__xx__类的字符串就要特别留意了,这些大多数是特殊属性或方法。
1、文档字符串_doc__。文档字符串的英文原意是文档字符串(docstring),Python鼓励程序设计师在设计函数或类时,尽量为函数或类增加文档的批注,未来可以使用__doc__特殊属性列出此文档批注:
class Myclass:
'''文档字符串示例
Myclass类别的应用'''
def __init__(self, x):
self.x = x
def printMe(self):
'''文档字符串示例
Myclass类内printMe方法的应用'''
print(self.x)
def getMax(x, y):
'''文档字符串示例
建议x, y是整数
这个函数将返回最大值'''
return x if int(x)>int(y) else y
data = Myclass(100)
data.printMe()
print(data.__doc__) #打印类对象的文档字符串
print(data.printMe.__doc__) #打印类对象中方法的文档字符串
print(getMax(2, 3))
print(getMax.__doc__) #打印函数的文档字符串
2、__name__属性。__name__可以判别这个程序是自己执行或是被其他程序import导入当成模块使用。如果程序是自己执行,__name__就是__main__。如果是被import到另一个程序,则__name__是本身的文件名。
if __name__ == '__main__':
print("It is main routine")
3、__str()__方法。这是类的特殊方法,可以协助返回易读取的字符串:
class A():
def __init__(self, name):
self.name = name
class B():
def __init__(self, name):
self.name = name
def __str__(self):
return "%s" % self.name
a = A('huang')
#类A未定义__str__(),输出内存地址
print(a)
b = B('huang')
#类B有定义__str__(),输出对应字符串
print(b)
4、__repr()__方法。上述类B定义了__str__( )方法后,就得到一个适合阅读的结果了。但是如果我们在Python Shell窗口输入b,一样获得不容易阅读的结果。上述原因是,如果只是在Python Shell窗口输入类变量b,系统是调用__repr__( )方法做响应,为了要获得容易阅读的结果,我们也需定义此方法。定义__repr__( )方法,其实此方法内容与__str__( )相同,所以可以用等号取代。
class B():
def __init__(self, name):
self.name = name
def __str__(self):
return "%s" % self.name
__repr__ = __str__
5、__iter__()方法。建立类的时候也可以将类定义成一个迭代对象,类似列表或元组,供for … in循环内使用,这时类需设计next( )方法,取得下一个值,直到达到结束条件,可以使用raise StopIteration(第15章会解说,raise)终止循环
class Fib():
#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
for i in Fib(100):
print(i)