下面都是我今天学习了类和继承的内容和一些学习笔记,有在学习这本书的小白同党可以看下方便更好地理解哈~
#8.1_Person类
import datetime
class Person(object):
def __init__(self, name):
"""创建一个人"""
self.name = name
try:
lastBlank = name.rindex(' ')#rindex反向索引的下标
self.lastName = name[lastBlank+1:]
except:
self.lastName = name
self.birthday = None
def getName(self):
"""返回这个人的姓名"""
return self.name
def getLastName(self):
"""返回这个人的姓"""
return self.lastName
def setBirthday(self, birthDate):
"""假定birthDate是datetime.date类型
把birthDate设定为这个人的生日"""
self.birthday = birthDate
def getAge(self):
"""返回这个人的当前年龄对应的天数"""
if self.birthday == None:
return ValueError
return (datetime.date.today() - self.birthday).days
def __lt__(self, other):#重载了<操作符
#当<的第一个参数是Person类型时,Person.__lt__会被调用
"""如果这个人的名字字典序列小于另一个人的名字返回True,否则返回False"""
if self.lastName == other.lastName:
return self.name < other.name
return self.lastName < other.lastName
def __str__(self):#__str__方法规范了输出格式
#如果没有该方法print会输出<__main__.Person object at XXXXXXX>生成器格式
"""返回这个人的名字"""
return self.name
me = Person('Michael Guttag')
him = Person('Barack Hussein Obama')
her = Person('Madonna')
print(him.getLastName())
him.setBirthday(datetime.date(1998, 10, 27))
her.setBirthday(datetime.date(1998, 11, 13))
print(him.getName(), 'is', him.getAge(), 'days old')
pList = [me, him, her]
for p in pList:
print(p)
pList.sort()
for p in pList:
print(p)
#8.2_Inheritance(继承)
class MITPerson(Person):#该类型是Person的子类,而Person是object的子类
#子类会继承所有父类的属性
nextIdNum = 0 #这就是类变量,有点类似于全局变量,这里作为身份证号
def __init__(self, name):
Person.__init__(self, name)
self.idNum = MITPerson.nextIdNum #实例变量
MITPerson.nextIdNum += 1
def getIdNum(self):
return self.idNum
def __lt__(self, other):
return self.idNum < other.idNum
def isStudent(self):
return isinstance(self, Student)
#第一个参数为任意对象,第二个参数为type类型的对象
#当且仅当第一个参数是第二个的实例时,返回True
p1 = MITPerson('Barbara Beaver')
print(str(p1) + '\'s id number is ' + str(p1.getIdNum()))
#在子类实例调用中,会首先检查子类的方法,如无再检查父类的方法
p1 = MITPerson('Mark Guttag')
p2 = MITPerson('Billy Bob Beaver')
p3 = MITPerson('Billy Bob Beaver')
p4 = Person('Billy Bob Beaver')
print('p1 < p2 =', p1 < p2)#明显的类变量和实例变量的区别
print('p3 < p2 =', p3 < p2)#每一个实例的创建,idNum都会+1,所以p2和p3会有区别
print('p4 < p1 =', p4 < p1)#<操作符通过第一个参数的类型决定调用哪个__lt__方法
#如p4 < p1,由于p4是Person类的,因而使用名字进行排序
#而p1是子类,继承了父类,因而也可以用名字排序
#print('p1 < p4 =', p1 < p4)
#调用p1的__lt__方法,但是p4作为父类并没有子类的__lt__方法,因而抛出异常
#8.2.1_MultilayerInheritance(多层继承)
class Student(MITPerson):
pass
class UG(Student):
def __init__(self, name, classYear):
MITPerson.__init__(self, name)
self.year = classYear
def getClass(self):
return self.year
class Grad(Student):
pass
p5 = Grad('Buzz Aldrin')
p6 = UG('Billy Beaver', 1984)
print(p5, 'is a graduate student is', type(p5) == Grad)
print(p5, 'is an ungraduate student is', type(p5) == UG)
print(p5, 'is a student is', p5.isStudent())
print(p6, 'is a student is', p6.isStudent())
print(p3, 'is a student is', p3.isStudent())
#注意,isinstance(p6, Student)和type(p6) == Student是不同的
#p6是UG类型的对象,UG是Student的子类,因此p6也是Student的实例,但却不是此类型
#当然,由于只有两类学生,所以也可以这样实现:
#def isStudent(self):
#return type(self) == Grad or type(self) == UG
#这样的缺点在于添加新的学生类型时需要修改isStudent,并且十分累赘
#而这个中间类Student并用isinstance内建函数则避免了这个问题
#如添加以下类:
class TransferStudent(Student):
def __init__(self, name, fromSchool):
MITPerson.__init__(self, name)
self.fromSchool = fromSchool
def getOldSchool(self):
return self.fromSchool
#这样设计程序十分的有利于程序的开发和维护
#8.2.2_里氏替换原则/替代法则
#可以看这里https://blog.csdn.net/hdhai9451/article/details/45110397
里氏替换原则是我最看不懂的一个东西,但是看了这位大神的文章感觉理解还算行了一点点,但是也就只可意会不可言传的蹩脚程度啦,大家还是自行理解吧~(狗头)