python3 面向对象设计,__init__方法和三个列子(士兵突击,房间与 家具,)
1.首先对于什么是面向过程编程,面向对象编程,函数式编程的概念和区别,说实话我自己看了也记不得,蒙圈,想知道请自行百度(其实是默默的对自己说的)。
2.面向对象编程:
重要的是搞清楚两点:类和对象
在我们的现实世界中,拿人作比喻:先是有一个个的中国人,一个个中国人组成了中国这个大家庭,这个国家在全世界来看即为一派一类。
在程序中,则是相反,先有类,再实例化对象,类赋予对象。
根据类来创建对象被称为实例化。
3.概念:
类:把一类实物相同的特征和动作整合到一起就是类,类是一个抽象的概念。
对象:对象就是类创建的具体的事物(具体而存在的)也就是特征和动作整合到一起。
类和对象的关系:
类是模板,对象是根据类这个模板创建出来的,现有类,再有对象,类和对象是1对n。
中国是类,而每一个中国人就是中国这个类创建的对象,这个对象的共同特征有姓名,性别,年龄,名族。。。。共同的动作有学习,吃饭,睡觉,打球。。。。
所以一个类则是由属性和动作组成,特征用变量标识,动作用函数标识
4.调用类,或称为实例化,得到对象;_init_()方法,以及属性的增删改查
类的三个要素:
类名:在python中,首字母大写的名称指的是类,满足大驼峰命名法(每个单词首字母大写;单词之间没有下划线);
数据属性:这类事物具有什么样的特征;
函数属性(通常也成为方法)这类事物具有什么样的行为;
类的数据属性是所有对象共享的;
类的函数属性是绑定给对象用的。
内置的dir(类名/对象名)——查询对象的方法和属性列表
__init__()方法——构造函数或者构造方法
当使用类名()创建对象时,会自动支撑性一下操作:
为对象在内存中分配空间————创建对象;
为对象的属性设置初始值————初始化方法(__init__());
__init__是对象的内置方法;
__init__方法是专门用来定义一个类具有哪些属性的方法。
在类中添加__init__方法时,在使用类名()创建对象的时候,会自动调用初始化方法__init__;
__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法,与c++中构造函数类似。
为何必须在方法定义中包含形参self——————python在调用_init_()方法来创建实例时,将会自动传入实参self。
由于创建对象时会调用类的构造方法,如果构造函数有多个参数时,需要手动传递参数。
每个与类相关联的方法都自动传入实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
哪一个对象调用的方法,self就是 哪一个对象的引用;
self.name=name————以self为前缀的变量都可供类中的所有实例(普通)方法使用。
定义没有初始值的属性:
在定义属性是,如果不知道设置什么初始值,可以设置为None
None关键字表示什么都没有;
表示一个空对象,没有方法和属性,是一个特使的常量;
可以将None赋值给任何一个变量;
在python中针对None的比较时,建议使用is判断;
一个对象的属性可以是另外一个类创建的对象。(士兵突击)
访问实例的属性——句点法;
调用方法——句点法;
class School: School_name="成都信息工程大学" School_age=67 def __init__(self,name,level): self.level=level self.name=name print("%s是%s" %(self.name,self.level)) def play(self,number): print("%s有%s岁,有%s的人" %(self.School_name,self.School_age,number)) def test(self): print('test') s1=School("成都信息工程大学","本科")#实例化s1对象,所带的参数是__init__决定的 print(School.__dict__)#查看属性字典 # 查看实例和类的数据属性和函数属性 print(s1.name) print(s1.play) print(School.School_name) print(School.play) # 增加实例和类的属性 s1.locate="四川成都" School.teacher="liang静" print(s1.locate) print(School.teacher) # 修改实例和类的属性 s1.locate="四川成都市龙泉驿区" print(s1.locate) print(s1.__dict__) s1.School_name="成信院改成成信大" print("类的》》》》",School.School_name) print("实例化的》》》》",s1.School_name) School.play=test s1.play() School.play(s1)#修改方法 # 删除 del s1.level print(s1.__dict__) # 只能是操作类里面的属性,定义在类外部的属性不能操作。 结果: 成都信息工程大学是本科
{'__init__': <function School.__init__ at 0x0000000002EFF950>, 'School_name': '成都信息工程大学',
'__weakref__': <attribute '__weakref__' of 'School' objects>,
'play': <function School.play at 0x0000000002EFFA60>, 'School_age': 67, '__module__': '__main__',
'__doc__': None, '__dict__': <attribute '__dict__' of 'School' objects>}
成都信息工程大学
<bound method School.play of <__main__.School object at 0x0000000002EFDBA8>>
成都信息工程大学
<function School.play at 0x0000000002EFFA60>
四川成都
liang静
四川成都市龙泉驿区
{'name': '成都信息工程大学', 'level': '本科', 'locate': '四川成都市龙泉驿区'}
类的》》》》 成都信息工程大学
实例化的》》》》 成信院改成成信大
test
test
{'School_name': '成信院改成成信大', 'name': '成都信息工程大学', 'locate': '四川成都市龙泉驿区'}
提示:
在日常开发中,不推荐在类的外部给对象增加属性;
如果在运行时,没有找到属性,程序会报错;
对象应该包含有哪些属性,应该封装在类的内部。
self的简单介绍:
在python中,类方法(构造方法和实例方法)中至少要包含一个参数,但并没有规定此参数的名称(完全可以叫任意参数名),之所以将类方法的第一个参数命名为 self,只是 Python 程序员约定俗成的一种习惯,这会使程序具有更好的可读性。
同一个类可以产生多个对象,当某个对象调用类方法时,该对象会把自身的引用作为第一个参数自动传给该方法,换句话说,Python 会自动绑定类方法的第一个参数指向调用该方法的对象。如此,Python解释器就能知道到底要操作哪个对象的方法了。
感觉自身的引用就是这个self。
当 self 参数作为对象的默认引用时,程序可以像访问普通变量一样来访问这个 self 参数,甚至可以把 self 参数当成实例方法的返回值。
士兵突击:
__author__ = 'Administrator' class Gun(): def __init__(self,model): # 1.枪的型号 self.model=model # 2.子弹的数量 self.bullet_count=0 #添加子弹 def add_bullet(self,count): self.bullet_count+=count #发射子弹 def shoot(self): #1.判断子弹数量 if self.bullet_count<=0: print("%s 没有子弹" %self.model) #2.发射子弹 self.bullet_count-=1 #3.提示发射信息 print("%s发射了,还剩下%s颗子弹" %(self.model,self.bullet_count)) class Soldier(): def __init__(self,name): self.name=name #新兵没有枪 self.gun=None def fire(self,num): # 1.判断士兵是否有枪 if self.gun is None: print("%s还没有枪" %self.name) return # 2.高喊口号 print("冲啊。。。。%s" %self.name) # 3.让枪装填子弹 self.gun.add_bullet(num) #让枪发射子弹 self.gun.shoot() ak47=Gun("AK47") pig=Soldier("小猪猪") pig.gun=ak47 pig.fire(100) ########################### 冲啊。。。。小猪猪 AK47发射了,还剩下99颗子弹
房间与家具:
__author__ = 'Administrator' class Furniture(): def __init__(self,name,area): self.name=name self.area=area def __str__(self): return "[%s] 占地 %.2f"%(self.name,self.area) class House(): def __init__(self,house_type,area): self.house_type=house_type self.area=area #剩余面积 self.free_area=area #家具名称列表 self.item_list=[] def __str__(self): return ("户型:%s\n总面积:%.2f[剩余面积:%.2f]\n家具:%s" %(self.house_type,self.area,self.free_area,self.item_list)) def add_item(self,item): print("要添加%s"%item) # 1.判断家具的面积 if item.area >self.free_area: print("%s 的面积太大了,无法添加" %item.name) return # 2.讲家具的名称添加到列表中 self.item_list.append(item.name) # 3.计算剩余面积 self.free_area-=item.area #创建家具 bed=Furniture("席梦思",4) chest=Furniture("衣柜",2) table=Furniture("餐桌",1.5) print(bed) print(chest) print(table) #创建房子对象 my_home=House("三室一厅",150) my_home.add_item(bed) my_home.add_item(chest) my_home.add_item(table) print(my_home) ############################# [席梦思] 占地 4.00 [衣柜] 占地 2.00 [餐桌] 占地 1.50 要添加[席梦思] 占地 4.00 要添加[衣柜] 占地 2.00 要添加[餐桌] 占地 1.50 户型:三室一厅 总面积:150.00[剩余面积:142.50] 家具:['席梦思', '衣柜', '餐桌']
飞机大战:
(1)
pip install pygame
验证是否安装成功:
python -m pygame.examples.aliens
pygame.init()——导入并初始化所有pygame模块,使用其他模块之前,必须先调用此方法。
pygame.quit()——写在所有的pygame模块,在游戏结束之前调用。
(2) 坐标系:
原点在左上角(0,0)
x轴水平方向向右,逐渐增加;
y轴垂直方向向下,逐渐增加;
在游戏中,所有可见的元素都是以矩形区域来描述位置的;
(3) 矩形区域四要素:(x,y)(width,height)
pygame使用pygame.Rect描述矩形区域(Rect(x,y,width,height))
pygame.Rect(x,y,left,right,top,bottom,center,centerx,centery,size,width,height)——有这么属性
提示:
这个是一个特殊的类,内部知识封装了一些数字计算;
不执行pygame.init()同样能够直接使用。
(4)创建游戏窗口
pygame.display用来创建、管理游戏窗口。
pygame.display.set_mode()——初始化游戏显示窗口
pygame.display.update()——刷新屏幕内容显示
set_mode(resolution=(0,0), flags=0, depth=0) -> Surface(可以不传递参数)
resolution ——指定屏幕的 宽和高,默认创建的窗口大小和屏幕大小一致
flags——参数指定屏幕的附加选项,例如是否全屏等等,默认不需要传递
depth——参数表示颜色的位数,默认自动匹配
返回值:可以理解为创建游戏的主窗口
注意:必须使用变量记录set_mode方法的返回结果,因为后续所有的图像都会基于这个返回结果(游戏的主窗口)。
(5)游戏循环
#设置窗口一直存在
while True:
pass
(6)绘制图像的三个步骤
加载背景图像
bg=pygame.image.load("./images/background.png")
绘制在屏幕
screen.blit(bg,(0,0))
【这里在实际演示代码的时候好像不太对】
解决办法:
# 创建游戏的窗口
screen=pygame.display.set_mode((500,700))
# 步骤2.blit绘制图像
screen.blit(bg,(100,100))
更新显示
pygame.display.update()
# 绘制英雄的飞机
# 加载图像
heros=pygame.image.load("./images/me1.png")
# 绘制在屏幕
ck.blit(heros,(200,300))
# 更新显示
pygame.display.update()
【pygame.display.update(),这个更新方法在最后使用可以把所有的绘制的所有图像更新显示在屏幕上】
(7)游戏循环和游戏时钟
游戏中的动画实现原理:
游戏中的动画效果本质上就是快速的在屏幕上绘制图像;
一般在电脑上每秒绘制60次update方法,就能够达到非常联系高品质的动画效果;
每次绘制的结果叫做帧(Frame)。
游戏循环的作用:
保证游戏不会直接退出;
变化图像位置—— 动画效果
每隔 1 / 60 秒 移动一下所有图像的位置
调用 pygame.display.update() 更新屏幕显示
检测用户交互—— 按键、鼠标等...
游戏时钟:
提供了pygame.time.Click可以非常方便的设置屏幕绘制速度——刷新帧率
需要两步:
第一步:在游戏初始化创建一个时钟对象
clock=pygame.time.Clock()
第二步:在游戏循环中让时钟对象调用tick(帧率)方法
while True:
# 可以指定循环体内部代码执行的频率
clock.tick(60)
i+=1
英雄的简单动画实现:
出现残影的解决办法:
在每一次调用update()方法之前,需要把所有的背景图像都重新绘制一遍
(8)在游戏循环中的监听事件
事件:游戏启动后,用户所做的动作
监听:判断用户的具体操作,才能有针对性的作出响应
代码实现:event_list=pygame.event.get(),可以获得用户当前所做动作的事件列表
(9)监听退出事件并且推出游戏
【这段代码非常固定,几乎所有的pygame游戏都大同小异】
(10)精灵和精灵组
图像加载,图像变化,绘制图像都需要程序员编写代码分别处理,但是为了简化,pygame提供了两个类。
pygame.sprite.Sprite—— 存储图像数据 image和 位置 rect的对象
pygame.sprite.Group
派生精灵子类
新建plane_sprites.py文件
定义GameSprite 继承自 pygame.sprite.Sprite
**注意**
如果一个类的父类不是 object:
在重写初始化方法 时,一定要 先 super() 一下父类的 __init__ 方法;
保证父类中实现的 __init__ 代码能够被正常执行;
职责:
精灵:
封装图像image、位置rect和速度speed;
提供update()方法,根据游戏需求,更新位置rect。
精灵组:
包含多个精灵对象;
update方法,让精灵组中的所有精灵调用update方法更新位置;
draw(screen)方法,在screen上绘制精灵组中的所有精灵。

浙公网安备 33010602011771号