1.面向过程编程
“面向过程”(Procedure Oriented)是一种以过程为中心的编程思想。这些都是以什么正在发生为
目标进行编程,不同于面向对象的是谁在受影响。与面向对象明显的不同就是封装、继承、类。
特性:模块化 流程化
优点:性能比面向对象高, 因为类调用时需要实例化,开销比较大,比较消耗资源;
单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
缺点:没有面向对象易维护、易复用、易扩展
2.函数式编程
函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。
主要思想: 把运算过程尽量写成一系列嵌套的函数调用。
3.面向对象编程
面向对象是按人们认识客观世界的系统思维方式,采用基于对象(实体)的概念建立模型,模拟客观世界分析、设计、实现软件的办法。通过面向对象的理念使计算机软件系统能与现实世界中的系统一一对应。
特性:抽象 封装 继承 多态
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,
可以设计出低耦合 的系统,使系统更加灵活、更加易于维护
缺点:性能比面向过程低
4.面向对象三大特征
4.1 对象和类
类(Class)是现实或思维世界中的实体在计算机中的反映,它将数据以及这些数据上的操作封装在一起。
对象(Object)是具有类类型的变量。类和对象是面向对象编程技术中的最基本的概念。
类和对象 的区别就是 鱼和三文鱼 的区别; 就是 猫和蓝猫 的区别。
类就相当于一个模板,可以实例化出许多对象。对象类有属性,有方法。
- 如何定义类? class 类(): pass
- 如何将类转换成对象?
实例化是指在面向对象的编程中,把用类创建对象的过程称为实例化。是将一个抽象的概念类,具体到该类实物的过程。实例化过程中一般由类名 对象名 = 类名(参数1,参数2…参数n)构成。
类(Class)是是创建实例的模板
对象(Object)是一个一个具体的实例
4.2 封装特性
封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
所以,在使用面向对象的封装特性时,需要:
1). 将内容封装到某处
2). 从某处调用被封装的内容
1). 通过对象直接调用被封装的内容: 对象.属性名
2). 通过self间接调用被封装的内容: self.属性名
3). 通过self间接调用被封装的内容: self.方法名()
构造方法__init__与其他普通方法不同的地方在于,当一个对象被创建后,会立即调用构造方法。自动执行构造方法里面的内容。
对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。
4.3 继承特性
- 继承
- 多继承
- 私有属性与私有方法
1.继承
在现实生活中,继承一般指的是子女继承父辈的财产,如下图:
继承描述的是事物之间的所属关系,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类、扩展类(Subclass),而被继承的class称为基类、父类或超类(Baseclass、Superclass)。
问题一: 如何让实现继承?
子类在继承的时候,在定义类时,小括号()中为父类的名字
问题二: 继承的工作机制是什么?
父类的属性、方法,会被继承给子类。 举例如下: 如果子类没有定义__init__方法,父类有,那么在子类继承父类的时候这个方法就被继承了,所以只要创建对象,就默认执行了那个继承过来的__init__方法。
重写父类方法: 就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法。
调用父类的方法:
1. 父类名.父类的方法名()
2. super(): (python2.2之后版本有)
2.多继承
多继承,即子类有多个父类,并且具有它们的特征
新式类与经典类
在Python 2及以前的版本中,由任意内置类型派生出的类,都属于“新式类”,都会获得所有“新式类”的特性;反之,即不由任意内置类型派生出的类,则称之为“经典类”。(没有标明父类,意思就是第一代,就是经典类,括号里写出它的父类就说明他不是第一代,就是新式类)
“新式类”和“经典类”的区分在Python 3之后就已经不存在,在Python 3.x之后的版本,因为所有的类都派生自内置类型object(即使没有显示的继承object类型),即所有的类都是“新式类”。
新式类和经典类区别:
最明显的区别在于继承搜索的顺序不同,即:
经典类多继承搜索顺序(深度优先算法):先深入继承树左侧查找,然后再返回,开始查找右侧。
新式类多继承搜索顺序(广度优先算法):先在水平方向查找,然后再向上查找,
3.私有属性与私有方法
默认情况下,属性在 Python 中都是“public”, 大多数 OO 语言提供“访问控制符”来限定成员函数的访问。
在 Python 中,实例的变量名如果以 __ 开头,就变成了一个私有变量/属性(private),实例的函数名如果以 __ 开头,就变成了一个私有函数/方法(private)只有内部可以访问,外部不能访问。
问题: 私有属性一定不能从外部访问吗?
python2版本不能直接访问 __属性名 是因为 Python 解释器对外把 __属性名 改成了 _类名__属性名 ,所以,仍然可以通过 _类名__属性名 来访问 __属性名 。
因为不同版本的 Python 解释器可能会把 __属性名 改成不同的变量名。
为什么要有私有属性/私有方法?
1. 确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。
2. 如果又要允许外部代码修改属性怎么办?可以给类增加专门设置属性方法。 为什么大费周折?因为在方法中,可以对参数做检查,避免传入无效的参数。
4.4 多态特性
多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。通俗来说: 同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
多态的好处就是,当我们需要传入更多的子类,只需要继承父类就可以了,而方法既可以直接不重写(即使用父类
的),也可以重写一个特有的。这就是多态的意思。调用方只管调用,不管细节,而当我们新增一种的子类时,只要
确保新方法编写正确,而不用管原来的代码。这就是著名的“开放封闭”原则:
对扩展开放(Open for extension):允许子类重写方法函数
对修改封闭(Closed for modification):不重写,直接继承父类方法函数
5. 练习
一. 队列数据结构的封装
队列类。队列(queue)是具有先进先出(FIFO)特性的数据结构。一个队
列就像是一行队伍,数据从前端被移除,从后端被加入。这个类必须支持
下面几种方法:
并实现下面的功能:
代码:
class Queue(object):
def __init__(self):
self.__queue=[]
def __len__(self):#求队列长度
return len(self.__queue)
def is_empty(self):
"""判断队列是否为空 """
return len(self.__queue) == 0
def enqueue(self,item):
"""入队操作"""
self.__queue.append(item)
print("元素[%s]入队成功" % (item))
def first(self):
"""求队头"""
if not self.is_empty():
item = self.__queue[0]
print('队头元素为:%s'%(item))
else:
raise Exception('队列为空')
def dequeue(self):
"""出队"""
if not self.is_empty():
item = self.__queue.pop(0)
print('元素%s出队成功'%(item))
else:
raise Exception('队列为空')
def Display_queue(self):
return self.__queue
Q = Queue()
Q.enqueue(5)
Q.enqueue(3)
print('队列内容为:',Q.Display_queue())
print('队长为:',len(Q))
Q.dequeue()
Q.is_empty()
Q.dequeue()
Q.is_empty()
# Q.dequeue()
Q.enqueue(7)
Q.enqueue(9)
Q.Display_queue()
Q.first()
Q.enqueue(4)
print('队长为:',len(Q))
Q.dequeue()
print('队列内容为:',Q.Display_queue())
运行结果:
二、乌龟吃鱼游戏
Pygame是跨平台Python模块,专为电子游戏设计,包含图像、声音。允许实时电子游戏研发
而无需被低级语言(如机器语言和汇编语言)束缚。
pygame安利一个博客:https://eyehere.net/2011/python-pygame-novice-professional-index/,解释的很详细。
代码:
import random
import time
import pygame
import sys
from pygame.locals import * # 导入一些常用的函数
width = 640
height = 480
pygame.init()
screen = pygame.display.set_mode([width, height])
pygame.display.set_caption('乌龟吃鱼') # 定义窗口的标题为'乌龟吃鱼'
background = pygame.image.load("./img/bg.jpg").convert()
fishImg = pygame.image.load("./img/fish.png").convert_alpha()
wuguiImg = pygame.image.load("./img/turtle.png").convert_alpha()
# 乌龟吃掉小鱼的音乐 mp3格式的不行,wav格式的
# eatsound = pygame.mixer.Sound("achievement.wav")
# 背景音乐
pygame.mixer.music.load("./img/game_music.mp3")
pygame.mixer.music.play(loops=0, start=0.0)
# 成绩文字显示
count = 0
font = pygame.font.SysFont("arial", 40)
score = font.render("score %d" % count, True, (255, 255, 255))
# 显示游戏状态
status = font.render("Gaming" , True, (255, 255, 255))
w_width = wuguiImg.get_width() - 5 # 得到乌龟图片的宽度,后面留着吃鱼的时候用
w_height = wuguiImg.get_height() - 5 # 得到乌龟图片的高度
y_width = fishImg.get_width() - 5 # 得到鱼图片的宽度
y_height = fishImg.get_height() - 5 # 得到鱼图片的高度
fpsClock = pygame.time.Clock() # 创建一个新的Clock对象,可以用来跟踪总共的时间
# 乌龟类
class Turtle:
def __init__(self):
self.power = 100 # 体力
# 乌龟坐标
self.x = random.randint(0, width - w_width)
self.y = random.randint(0, height - w_height)
# 乌龟移动的方法:移动方向均随机 第四条
def move(self, new_x, new_y):
# 判断移动后是否超出边界
if new_x < 0:
self.x = 0 - new_x
elif new_x > width:
# self.x=width-(new_x-width)
self.x = 0
else:
# 不越界则移动乌龟的位置
self.x = new_x
if new_y < 0:
self.y = 0 - new_y
elif new_y > height:
# self.y=height-(new_y-height)
self.y = 0
else:
# 不越界则移动乌龟的位置
self.y = new_y
self.power -= 1 # 乌龟每移动一次,体力消耗1
def eat(self):
self.power += 20 # 乌龟吃掉鱼,乌龟体力增加20
if self.power > 100:
self.power = 100 # 乌龟体力100(上限)
# 鱼类
class Fish:
def __init__(self):
# 鱼坐标
self.x = random.randint(0, width - y_width)
self.y = random.randint(0, height - y_height)
def move(self):
new_x = self.x + random.choice([-10])
if new_x < 0:
self.x = width
else:
self.x = new_x
# 开始测试数据
tur = Turtle() # 生成1只乌龟
fish = [] # 生成10条鱼
for item in range(10):
newfish = Fish()
fish.append(newfish) # 把生成的鱼放到鱼缸里
# pygame有一个事件循环,不断检查用户在做什么。事件循环中,如何让循环中断下来(pygame形成的窗口中右边的插号在未定义前是不起作用的)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
# 通过上下左右方向键控制乌龟的动向
if event.key == pygame.K_LEFT:
tur.move(tur.x - 20, tur.y)
if event.key == pygame.K_RIGHT:
tur.move(tur.x + 20, tur.y)
if event.key == pygame.K_UP:
tur.move(tur.x, tur.y - 20)
if event.key == pygame.K_DOWN:
tur.move(tur.x, tur.y + 20)
screen.blit(background, (0, 0)) # 绘制背景图片
screen.blit(score, (500, 20)) # 绘制分数
screen.blit(status, (0, 20)) # 绘制分数
# 绘制鱼
for item in fish:
screen.blit(fishImg, (item.x, item.y))
# pygame.time.delay(100)
item.move() # 鱼移动
screen.blit(wuguiImg, (tur.x, tur.y)) # 绘制乌龟
# 判断游戏是否结束:当乌龟体力值为0(挂掉)或者鱼儿的数量为0游戏结束
if tur.power < 0:
print("Game Over: Turtle power is 0")
# 显示游戏状态
status = font.render("Game Over: Turtle power is 0", True, (255, 255, 255))
pygame.display.update() # 更新到游戏窗口
time.sleep(1)
sys.exit(0)
elif len(fish) == 0:
status = font.render("Game Over: Fish is empty", True, (255, 255, 255))
pygame.display.update() # 更新到游戏窗口
sys.exit(0)
for item in fish:
# print("鱼", item.x, item.y, y_width, y_height)
# print("乌龟", tur.x, tur.y, w_width, w_height)
# 判断鱼和乌龟是否碰撞?
if ((tur.x < item.x + y_width) and (tur.x + w_width > item.x)
and (tur.y < item.y + y_height) and (w_height + tur.y > item.y)) :
fish.remove(item) # 鱼死掉
# 吃鱼音乐
# eatsound.play()
count = count + 1 # 累加
score = font.render("score %d" % count, True, (255, 255, 255))
# print("死了一只鱼")
# print("乌龟最新体力值为 %d" % tur.power)
pygame.display.update() # 更新到游戏窗口
fpsClock.tick(10) # 通过每帧调用一次fpsClock.tick(10),这个程序就永远不会以超过每秒10帧的速度运行
素材可以自己找
运行结果:
三、游戏改进–>双人游戏
对于上面的游戏进行改进:
**我们刚开始是两个人物, 一个玩家是你, 一个玩家是王思聪,周围都是仅剩无
几的热狗食物,为了生存两个玩家必须争夺仅有的热狗。 当热狗吃完时, 谁的得
分高, 谁就是最终的赢家。 或者其中一方玩家体力消耗仅剩 0, 另外一方玩家即
为赢家。
玩家 1:键盘方向键↑↓←→控制移动。
玩家 2:键盘 WSAD 控制控制移动。
代码:
import random
import pygame
import sys
from pygame.locals import *
width = 800
height = 400
pygame.init()
screen = pygame.display.set_mode([width,height])
pygame.display.set_caption('热狗游戏')
backgroud = pygame.image.load('./img/p1.png').convert()
fishImg = pygame.image.load('./img/m.png').convert_alpha()
wuguiImg = pygame.image.load('./img/w.png').convert_alpha()
# eatsound = pygame.mixer.Sound('')#乌龟吃鱼音乐
pygame.mixer.music.load('./img/game_music.mp3')
pygame.mixer.music.play(loops=0,start=0.0)
# fpsClock = pygame.time.Clock()
count1 = 0
count2 = 0
font = pygame.font.SysFont('arial',30)
score1 = font.render('score1 %d'%count1,True,(0,255,0))
score2 = font.render('score2 %d'%count2,True,(0,255,0))
w_width = wuguiImg.get_width() - 5
w_height = wuguiImg.get_height() - 5
y_width = fishImg.get_width() - 5
y_height = fishImg.get_height() - 5
fpsClock = pygame.time.Clock()
class Turtle:
def __init__(self):
self.power = 200
self.x = random.randint(0,width - w_width)
self.y = random.randint(0,height - w_height)
def move(self,new_x,new_y):
if new_x < 0:
self.x = 0 - new_x
elif new_x > width:
self.x = 0
else:
self.x = new_x
if new_y <0:
self.y = 0 - new_y
elif new_y > height:
self.y = 0
else:
self.y = new_y
self.power -= 10
def eat(self):
self.power += 20
if self.power > 200:
self.power = 200
class Fish:
def __init__(self):
self.x = random.randint(0,width - y_width)
self.y = random.randint(0,height - y_height)
def move(self):
new_x = self.x + random.choice([-10])
if new_x < 0:
self.x = width
else:
self.x = new_x
tur1 = Turtle()
tur2 = Turtle()
fish = []
a=random.randint(10,40)
for item in range(a):
newfish = Fish()
fish.append(newfish)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
tur1.move(tur1.x - 30 ,tur1.y)
if event.key == pygame.K_RIGHT:
tur1.move(tur1.x + 30, tur1.y)
if event.key == pygame.K_UP:
tur1.move(tur1.x , tur1.y - 30)
if event.key == pygame.K_DOWN:
tur1.move(tur1.x, tur1.y + 30)
if event.key == pygame.K_a:
tur2.move(tur2.x - 30 ,tur2.y)
if event.key == pygame.K_d:
tur2.move(tur2.x + 30, tur2.y)
if event.key == pygame.K_w:
tur2.move(tur2.x , tur2.y - 30)
if event.key == pygame.K_s:
tur2.move(tur2.x, tur2.y + 30)
screen.blit(backgroud, (0, 0))
screen.blit(score1, (100, 20))
# screen.blit(backgroud,(0,0))
screen.blit(score2,(500,20))
for item in fish:
screen.blit(fishImg,(item.x,item.y))
item.move()
screen.blit(wuguiImg,(tur1.x,tur1.y))
if tur1.power == 0 or len(fish) == 0 or tur2.power == 0:
if count1 < count2 or count1==0:
print('Game Over~')
print('玩家2获胜')
sys.exit()
if count1 > count2 or count2 == 0:
print('Game Over~')
print('玩家1获胜')
sys.exit()
for item in fish:
if ((tur1.x < item.x +y_width) and (tur1.x + w_width > item.x) and
(tur1.y < item.y + y_height) and (w_height + tur1.y > item.y)):
tur1.eat()
fish.remove(item)
count1 = count1 + 1
score1 = font.render("score1 %d" % count1, True, (0, 255, 255))
else:
for item in fish:
screen.blit(fishImg, (item.x, item.y))
item.move()
screen.blit(wuguiImg, (tur2.x, tur2.y))
if tur1.power < 0 or len(fish) == 0 or tur2.power < 0:
if count1 < count2 or count1 == 0:
print('Game Over~')
print('玩家2获胜')
sys.exit()
if count1 > count2 or count2 == 0:
print('Game Over~')
print('玩家1获胜')
sys.exit()
for item in fish:
if ((tur2.x < item.x + y_width) and (tur2.x + w_width > item.x) and
(tur2.y < item.y + y_height) and (w_height + tur2.y > item.y)):
tur2.eat()
fish.remove(item)
count2 = count2 + 1
score2 = font.render("score2 %d" %count2,True,(0,255,255))
pygame.display.update()
fpsClock.tick(10)
运行截图:
四、按奇偶排序数组
代码:
li1 = [3,1,2,4]
li2 = []
print('原列表:',li1)
#方法一:
for i in li1:
if i % 2 == 0:
li2.append(i)
else:
for i in li1:
if i % 2 != 0:
li2.append((i))
print('方法一:',li2)
#方法二:
li3=sorted(li1, key=lambda x: 0 if x % 2 == 0 else 1)
print('方法二:',li3)
运行截图:
五、电话号码的字母组合
代码:
di = {'2':['a','b','c'],
'3':['d','e','f'],
'4':['g','h','i'],
'5':['j','k','l'],
'6':['m','n','o'],
'7':['p','q','r','s'],
'8':['t','u','v'],
'9':['w','x','y','z']
}
li=[]
i = input('请输入俩位数字:')
for it1 in di:
if it1 == i[0]:
for it2 in di:
if it2 == i[1]:
for it3 in range(len(di[it1])):
for it4 in range(len(di[it2])):
li.append(di[it1][it3]+di[it2][it4])
print(li)
运行截图: