Day 19
一、特性
- Python也是一门面向对象的编程语言,包含面向对象的编程语言的特性:封装、继承、多态
1、封装
- 属性和方法放到类内部,通过对象访问属性或者方法,隐藏功能的实现细节,当然还可以设置访问权限。
- 类中的变量可以不预先定义;
- 实例方法一定要带self参数
- 类就是一个函数
class Human:
def introduce(self):
print('大家好,我是%s,我今年%d岁'%(self.__name,self.__age))
def setInfo(self,nm,ag):
self.__name=nm
if ag>150 or ag<0:
print('输入的年龄非法')
else:
self.__age=ag
def getInfo(self):
return self.__name,self.__age
h=Human()
#h.name,h.age,h.sex='张三',19,'男'
h.setInfo('张三',19)
h.introduce()
- 封装的意义在于保护数据,通过将数据私有化,保证数据安全,对用户隐藏数据。
- 提供公开方法来使用户可以读写数据(get和set方法),同时检测数据中的逻辑错误,确保用户输入的数据不是非法的。
- 设计类时,尽可能的封装属性,不将属性暴露给用户。
- 设计一张学生表,学生表中允许用户使用insert方法插入记录或者用delete方法删除一条数据,学生表的属性(sname,sage,ssex,sid)
class StudentRecord:
def __init__(self,sn,sa,sx,si):
self.__sname,self.__sage,self.__ssex,self.__sid=sn,sa,sx,si
def setSname(self,sn):
self.__sname=sn
def setSage(self,sa):
self.__sage=sa
def setSsex(self,sx):
self.__ssex=sx
def setSid(self,si):
self.__sid=si
def getSname(self):
return self.__sname
def getSage(self):
return self.__sage
def getSsex(self):
return self.__ssex
def getSid(self):
return self.__sid
def intro(self):
print('我是%s,几年%d岁'%(self.__sname,self.__sage))
class StudentTable:
stuList=[]
def insert(self,stu):
if isinstance(stu,StudentRecord):
self.stuList.append(stu)
else:
print('不是StudentRecord实例')
def delete(self,stu):
if isinstance(stu,StudentRecord):
self.stuList.remove(stu)
else:
print('不是StudentRecord实例')
stuTbl=StudentTable()
s1=StudentRecord('张三',19,'男',1001)
s2=StudentRecord('李四',20,'男',1002)
stuTbl.insert(s1)
stuTbl.insert(s2)
stuTbl.delete(s1)
- 在现有的学生表类的基础上,添加成绩表markTable,向成绩表中添加一些学生的选课记录(sid,cid,cmark),提供方法查询李四的平均分。
class markRecord:
def __init__(self,sid,cid,cmark):
self.__sid,self.__cid,self.__cmark=sid,cid,cmark
def getSid(self):
return self.__sid
def getCmark(self):
return self.__cmark
def getCid(self):
return self.__cid
class markTable:
__markList=list()
def insert(self,mark):
if isinstance(mark,markRecord):
self.__markList.append(mark)
else:
print('不是markRecord实例')
def avg(self,sid):
avg=0
sum=0
for mark in self.__markList:
if mark.getSid()==sid:
avg+=mark.getCmark()
sum+=1
return avg/sum
m1=markRecord(1002,2001,85)
m2=markRecord(1002,2002,90)
mTbl=markTable()
mTbl.insert(m1)
mTbl.insert(m2)
print(mTbl.avg(1002))
- 前面两个下划线是私有属性/方法,前后两个下划线是公有方法。
- get和set方法较为麻烦,python有更好的解决方式——装饰器@property
class Student(object):
@property
def score(self):
return self.__score
@score.setter
def score(self,value):
if not isinstance(value,int):
raise ValueError('score must be an integer!')
if value < 0 or value >100:
raise ValueError('score must between 0~100!')
self.__score=value
s = Student()
s.score = 60 # 实际转换为s.set_score(60)
print(s.score) # 实际转换为print(s.get_score())
2、继承
- 如果写了__init__方法,默认的__init__方法会消失。
- python中没有重载函数,一般通过可变长函数实现。
- Student类继承了Human类中的属性和方法,也可以实现重写其继承的方法
class Human(object):
@property
def name(self):
return self.__name
@name.setter
def name(self,nm):
self.__name=nm
@property
def age(self):
return self.__age
@age.setter
def age(self,ag):
seelf.__age=ag
class Student(Human):
@property
def sid(self):
return self.__sid
@score.setter
def sid(self,value):
if not isinstance(value,int):
raise ValueError('score must be an integer!')
if value < 0 or value >100:
raise ValueError('score must between 0~100!')
self.__sid=sid
@age.setter
def age(self,ag):
if ag<0 or ag>30:
raise ValueError('不是学生的年龄')
s=Student()
s.name,s.sid,s.age='张三',1001,19
print(s.name,s.age,s.sid)
#、作业
1、实现地雷小游戏的类设计
棋子类
属性:xy坐标、是否为地雷
棋盘类
属性:棋子容器、棋盘的高宽、雷的个数
方法:鼠标点击
游戏类
属性:玩家信息、游戏难度
方法:游戏初始化
1、展示游戏初始化后的地雷地图
2、根据输入返回周围的地雷数
import random
class Chess:
@property
def x(self):
return self.__x
@x.setter
def x(self,value):
self.__x=value
@property
def y(self):
return self.__y
@x.setter
def y(self,value):
self.__y=value
@property
def boom(self):
return self.__boom
@boom.setter
def boom(self,value):
if not isinstance(value,bool):
raise ValueError('属性只能为布尔值')
self.__boom=value
class ChessBoard:
__map1=list()
__map2=list()
@property
def width(self):
return self.__width
@width.setter
def width(self,value):
self.__width=value
@property
def height(self):
return self.__height
@height.setter
def height(self,value):
self.__height=value
@property
def numbers(self):
return self.__numbers
@numbers.setter
def numbers(self,value):
self.__numbers=value
def __init__(self,width,height,numbers):
self.__width,self.__height,self.__numbers=width,height,numbers
def generateMap(self):
# numbers个不重复的随机数
n = self.width * self.height
self.__s=set()
while len(self.__s)!=self.numbers:
self.__s.add(random.randint(1,n))
# 构建地雷地图
self.__map1=[[] for i in range(self.height)]
for i in range(len(self.__map1)):
for j in range(self.width):
if int(i*self.width+j+1) in self.__s:
self.__map1[i].append(1)
else:
self.__map1[i].append(0)
'''
构建提示地图
1、初始化为0
2、修改提示数字
3、修改地雷数字为*
'''
# 1
self.__map2=[[] for i in range(self.height)]
for i in range(self.height):
for j in range(self.width):
self.__map2[i].append(0)
# 2
x =self.width
for t in self.__s:
ps=[t-x-1,t-x,t-x+1,t-1,t+1,t+x-1,t+x,t+x+1]
ti=(t-1)//x
tj=(t-1)%x
for p in ps:
if p<0 or p>n:
continue
if tj==0 and (p==t-x-1 or p==t-1 or p==t+x-1):
continue
if tj==x-1 and (p==t-x+1 or p==t+1 or p==t+x+1):
continue
pi=(p-1)//x
pj=(p-1)%x
if pi<0 or pj<0 or pi>(x-1) or pj>(x-1):
continue
else:
self.__map2[pi][pj]=1+self.__map2[pi][pj]
# 3
for t in self.__s:
ti=(t-1)//x
tj=(t-1)%x
self.__map2[ti][tj]='*'
def printMap1(self):
# 打印地雷地图
for i in range(len(self.__map1)):
for j in range(len(self.__map1[i])):
print(self.__map1[i][j],end=' ')
print('')
def printMap2(self):
# 打印提示地图
for i in range(len(self.__map2)):
for j in range(len(self.__map2[i])):
print(self.__map2[i][j],end=' ')
print('')
def getNum(self,x,y):
if x<0 or x>self.width or y<0 or y>self.height:
raise ValueError('输入坐标不在棋盘中')
t=(x-1)*self.width+y
ti=(t-1)//self.width
tj=(t-1)%self.width
if t in self.__s:
print('这是一颗雷')
else:
print('这个位置周围有'+str(self.__map2[ti][tj])+'颗雷')
class Game:
def __init__(self,width,height,numbers):
self.__cb=ChessBoard(width,height,numbers)
self.__cb.generateMap()
def printMap1(self):
self.__cb.printMap1()
def printMap2(self):
self.__cb.printMap2()
def getNum(self,x,y):
self.__cb.getNum(x,y)
gm=Game(10,10,30)
gm.printMap1()
print('')
gm.printMap2()
x=int(input('请输入横坐标'))
y=int(input('请输入纵坐标'))
gm.getNum(x,y)

版权声明:本文为qq_41103187原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。