计算机科学和Python编程导论week6
2018-08-01 本文已影响50人
瘦长的丰一禾
面向对象最重要的概念就是类(Class)和实例(Instance),类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。
参考《Python编程导论 第二版》第8章类与面向对象编程
Python3面向对象编程
8.1抽象数据类型和类
In [30]: class IntSet(object):
...: """IntSet是一个整数集合"""
...: #关于实现(不是抽象)的信息
...: #集合的值由一个整数数组self.vals表示。
...: #集合中的每个整数在self.vals中只出现一次。
...: def __init__(self):
...: """创建一个空的整数集合"""
...: self.vals = []
...: def insert(self, e):
...: """假设e是整数,将e插入self"""
...: if e not in self.vals:
...: self.vals.append(e)
...: def member(self, e):
...: """假设e是整数
...: 如果e在self中,则返回True,否则返回False"""
...: return e in self.vals
...:
...: def remove(self, e):
...: """假设e是整数,从self中删除e
...: 如果e不在self中,则抛出ValueError异常"""
...: try:
...: self.vals.remove(e)
...: except:
...: raise ValueError(str(e) + ' not found')
...: def getMembers(self):
...: """返回一个包含self中元素的列表
...: 对元素不进行排序"""
...: return self.vals[:]
...: def __str__(self):
...: """返回一个表示self的字符串"""
...: self.vals.sort()
...: result = ''
...: for e in self.vals:
...: result = result + str(e) + ','
...: return '{' + result[:-1] + '}' #-1 可以忽略最后的逗号
...:
In [31]: print(type(IntSet),type(IntSet.insert))
<class 'type'> <class 'function'>
In [32]: s = IntSet()
In [33]: s.insert(3)
In [35]: print(s.member(3))
True
In [36]: s.insert(4)
In [37]: s
Out[37]: <__main__.IntSet at 0x1101fd30>
In [41]: print(s)
{3,4}
In [40]: s.getMembers()
Out[40]: [3, 4]
8.1.2 使用类记录学生与教师
In [43]: import datetime
...: class Person(object):
...: def __init__(self, name):
...: """创建一个人"""
...: self.name = name
...: try:
...: lastBlank = name.rindex(' ')
...: self.lastName = name[lastBlank+1:]
...: except:
...: self.lastName = name
...: self.birthday = None
...: def getName(self):
...: """返回self的全名"""
...: return self.name
...: def getLastName(self):
...: """返回self的姓"""
...: return self.lastName
...: def setBirthday(self, birthdate):
...: """假设birthday是datetime.date类型
...: 将self的生日设置为birthday"""
...: self.birthday = birthdate
...: def getAge(self):
...: """返回self的当前年龄,用日表示"""
...: if self.birthday == None:
...: raise ValueError
...: return (datetime.date.today() - self.birthday).days
...: def __lt__(self, other):
...: """如果self按字母顺序位于other之前,则返回True,否则返回False。
...: 首先按照姓进行比较,如果姓相同,就按照全名比较"""
...: if self.lastName == other.lastName:
...: return self.name < other.name
...: return self.lastName < other.lastName
...: def __str__(self):
...: """返回self的全名"""
...: return self.name
...:
In [44]: me = Person('Michael Guttag')
...: him = Person('Barack Hussein Obama')
...: her = Person('Madonna')
...:
In [45]: print(him.getLastName())
...: him.setBirthday(datetime.date(1961, 8, 4))
...: her.setBirthday(datetime.date(1958, 8, 16))
...: print(him.getName(), 'is', him.getAge(), 'days old')
...:
Obama
Barack Hussein Obama is 20816 days old
In [47]: pList = [me, him, her]
...: for p in pList:
...: print(p)
...: print('----------------------------------------')
...: pList.sort()
...: for p in pList:
...: print(p)
...:
Michael Guttag
Barack Hussein Obama
Madonna
----------------------------------------
Michael Guttag
Madonna
Barack Hussein Obama
8.2 继承
In [48]: class MITPerson(Person):
...: nextIdNum = 0 #identification number
...: 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
...:
In [49]: p1 = MITPerson('Barbara Beaver')
...: print(str(p1) + '\'s id number is ' + str(p1.getIdNum()))
...:
Barbara Beaver's id number is 0
In [50]: 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)
...: print('p4 < p1 =', p4 < p1)
...:
p1 < p2 = True
p3 < p2 = False
p4 < p1 = True
In [52]: print('p1 < p4 =', p1 < p4)
Traceback (most recent call last):
File "<ipython-input-52-46143f00caa4>", line 1, in <module>
print('p1 < p4 =', p1 < p4)
File "<ipython-input-48-602df1c0e123>", line 10, in __lt__
return self.idNum < other.idNum
AttributeError: 'Person' object has no attribute 'idNum'
# 运行时系统会调用与p1的类型关联的__lt__操作符,也就是定义在MITPerson类中的函数。
# 创建student类
In [14]: class Student(object):
...: def __init__(self, name, score):
...: self.name = name
...: self.score = score
...: def print_score(self):
...: print("%s:%s" % (self.name, self.score))
...: def get_grade(self):
...: if self.score >= 90:
...: return 'A'
...: elif self.score >= 60:
...: return 'B'
...: else:
...: return 'C'
...:
In [15]: lisa = Student('Lisa', 99)
...: bart = Student('Bart', 59)
...: print(lisa.name, lisa.get_grade())
...: print(bart.name, bart.get_grade())
...:
Lisa A
Bart C
多重继承
In [53]: 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
...:
In [54]: p5 = Grad('Buzz Aldrin')
...: p6 = UG('Billy Beaver', 1984)
...: print(p5, 'is a graduate student is', type(p5) == Grad)
...: print(p5, 'is an undergraduate student is', type(p5) == UG)
...:
Buzz Aldrin is a graduate student is True
Buzz Aldrin is an undergraduate student is False
面向对象的核心思想:封装和信息隐藏。
封装是指:将数据属性和操作数据属性的方法打包在一起。信息隐藏是指:使属性在类之外不可见。
在Python 3中,可以使用命名惯例使属性在类之外不可见。当一个属性的名称以开头但不以结束时,这个属性在类外就是不可见的。如下:
In [55]: class infoHiding(object):
...: def __init__(self):
...: self.visible = 'Look at me'
...: self.__alsoVisible__ = 'Look at me too'
...: self.__invisible = 'Don\'t look at me directly'
...: def printVisible(self):
...: print(self.visible)
...: def printInvisible(self):
...: print(self.__invisible)
...: def __printInvisible(self):
...: print(self.__invisible)
...: def __printInvisible__(self):
...: print(self.__invisible)
...:
In [56]: test = infoHiding()
...: print(test.visible)
...: print(test.__alsoVisible__)
...: print(test.__invisible)
...:
Look at me
Look at me too
Traceback (most recent call last):
File "<ipython-input-56-8ba28fd4db07>", line 4, in <module>
print(test.__invisible)
AttributeError: 'infoHiding' object has no attribute '__invisible'
In [57]: test = infoHiding()
...: test.printInvisible()
...: test.__printInvisible__()
...: test.__printInvisible()
...:
Don't look at me directly
Don't look at me directly
Traceback (most recent call last):
File "<ipython-input-57-b6445e79430b>", line 4, in <module>
test.__printInvisible()
AttributeError: 'infoHiding' object has no attribute '__printInvisible'
In [58]: class subClass(infoHiding):
...: def __init__(self):
...: print('from subclass', self.__invisible)
...: testSub = subClass()
...:
Traceback (most recent call last):
File "<ipython-input-58-4a0a22384a1a>", line 4, in <module>
testSub = subClass()
File "<ipython-input-58-4a0a22384a1a>", line 3, in __init__
print('from subclass', self.__invisible)
AttributeError: 'subClass' object has no attribute '_subClass__invisible'
类的继承
In [37]: class A(object):
...: def __init__(self):
...: self.a = 1
...: def x(self):
...: print ("A.x")
...: def y(self):
...: print ("A.y")
...: def z(self):
...: print ("A.z")
...:
...: class B(A):
...: def __init__(self):
...: A.__init__(self)
...: self.a = 2
...: self.b = 3
...: def y(self):
...: print ("B.y")
...: def z(self):
...: print ("B.z")
...:
...: class C(object):
...: def __init__(self):
...: self.a = 4
...: self.c = 5
...: def y(self):
...: print ("C.y")
...: def z(self):
...: print ("C.z")
...:
...: class D(C, B):
...: def __init__(self):
...: C.__init__(self)
...: B.__init__(self)
...: self.d = 6
...: def z(self):
...: print ("D.z")
...:
In [38]: obj = D()
In [39]: obj.a
Out[39]: 2
In [40]: obj.b
Out[40]: 3
In [41]: obj.c
Out[41]: 5
In [42]: obj.d
Out[42]: 6
In [43]: obj.x()
A.x
In [44]: obj.y
Out[44]: <bound method C.y of <__main__.D object at 0x00000000113F90F0>>
In [45]: obj.y()
C.y
In [46]: obj.z()
D.z
视频试题:
In [1]: class Clock(object):
...: def __init__(self,time):
...: self.time = time
...: def print_time(self):
...: time = '6:30'
...: print (self.time)
...: clock = Clock('5:30')
...: clock.print_time()
...:
5:30
In [4]: class Clock(object):
...: def __init__(self,time):
...: self.time = time
...: def print_time(self,time):
...: print (time)
...: clock = Clock('5:30')
...: clock.print_time('10:30')
...:
10:30
In [5]: class Clock(object):
...: def __init__(self,time):
...: self.time = time
...: def print_time(self):
...: print (self.time)
...: boston_clock = Clock('5:30')
...: paris_clock = boston_clock
...: paris_clock.time = '10:30'
...: boston_clock.print_time()
...:
10:30
In [32]: class Spell(object):
...: def __init__(self, incantation, name):
...: self.name = name
...: self.incantation = incantation
...:
...: def __str__(self):
...: return self.name + ' ' + self.incantation + '\n' + self.getDescription()
...:
...: def getDescription(self):
...: return 'No description'
...:
...: def execute(self):
...: print (self.incantation)
...:
...:
...: class Accio(Spell):
...: def __init__(self):
...: Spell.__init__(self, 'Accio', 'Summoning Charm')
...:
...: class Confundo(Spell):
...: def __init__(self):
...: Spell.__init__(self, 'Confundo', 'Confundus Charm')
...:
...: def getDescription(self):
...: return 'Causes the victim to become confused and befuddled.'
...:
...: def studySpell(spell):
...: print (spell)
...:
In [33]: spell = Accio()
...: spell.execute()
...: studySpell(spell)
...: studySpell(Confundo())
...:
Accio
Summoning Charm Accio
No description
Confundus Charm Confundo
Causes the victim to become confused and befuddled.
参考链接:
6.00.1X 计算机科学和PYTHON编程导论