本周主要学习了类和面向对象的知识,学得容易,灵活运用却很难,还需要多加练习孰能生巧。
参数、默认值、可变参数、关键字参数、命名关键字参数
可变参数:*args
关键字参数:**kwargs
返回值
嵌套定义
高阶函数、λ函数(匿名函数)、闭包、偏函数、柯里化
标识符
print(a)
作用域
L–E–G–B
单一职责原则
开闭原则
依赖原则
里氏替换原则
接口隔离原则(x)
合成聚合复用原则
迪米特法则(最少知识原则)
#关键字参数--字典--根据参数名来决定如何执行
#可变参数--输出的是元组
def say_hello(**kwargs):
print(kwargs)
for key in kwargs:
print(key,'-->',kwargs[key])
if 'name' in kwargs:
print('你好,%s!' %kwargs['name'])
elif 'age' in kwargs:
age = kwargs['age']
if age<= 16:
print('你还是个小屁孩')
else:
print('你是个成年人')
else:
print('请提供个人信息')
def main():
say_hello(name='熊彪',age='25')
param = {'name':'王大锤','age':16,'tel':'15884550995'}
#如果希望将一个字典作为关键字参数传入 需要在参数名前放两个*
say_hello(**param)
mylist = [1,2,3,7,8]
#如果希望将一个列表或元组作为可变参数传入 需要在参数名前放一个*
#命名关键字参数
def foo (a,b,c,*,name,age):
print(a+b+c)
print(name,':',age)
foo(1,2,3,name = '熊彪',age = '25')
if __name__ == '__main__':
main()
(限定对象只能绑定某些属性)
子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态(poly-morphism)。
def my_sum(my_list):
total = 0
for val in my_list:
total += val
return total
def add(x,y):
return x*y
def calc(my_list,op):
total = my_list[0]
for index in range(1,len(my_list)):
total = op(total,my_list[index])
return total
def main():
my_list = [1,3,5,2,7,8,9]
print(calc(my_list,add))
print(my_sum(my_list))
if __name__ == '__main__':
main()
def record(fn):
def wrapper(*args,**kwargs):
print('准备执行%s函数' %fn.__name__)
print(args)
print(kwargs)
#此行代码在执行被装饰的函数
#在这行代码的前后我们可以附加其他的代码
#这些代码可以让我们在执行函数时做一些额外的工作
val = fn(*args,**kwargs)
print('%s函数执行完成' %fn.__name__)
print('返回了%d' %val)
return val
return wrapper
#通过装饰器修饰f函数 让f函数在执行过程中可以做更多额外的操作
@record
def f(n):
if n==0 or n==1:
return 1
return n*f(n-1)
if __name__ == '__main__':
print(f(5))
#奥特曼打小怪兽
from random import randint
class Ultraman(object):
__slots__ = ('_name','_hp','_mp') #对对象属性做限制,不能加别的属性
def __init__(self, name, hp, mp):
self._name = name
self._hp = hp
self._mp = mp
#属性的访问器与修改器
@property
def name(self):
return self._name
@property
def hp(self):
return self._hp
@hp.setter
def hp(self, hp):
self._hp = hp if hp >= 0 else 0
def attack(self, monster):
monster.hp -= randint(15, 25)
def huge_attack(self, monster):
if self.mp >= 50:
self.mp -= 50
injury = monster.hp * 3 // 4
injury = injury if injury >= 50 else 50
monster.hp -= injury
else:
self.attack(monster)
def magic_attack(self, monsters):
if self._mp >= 20:
self._mp -= 20
for monster in monsters:
monster.hp -= randint(10, 15)
def __str__(self):
return '%s奥特曼\n' % self._name + \
'生命值:%d\n' % self._hp + \
'魔法值:%d\n' % self._mp
class Monster(object):
__slots__ = ('_name','_hp')
def __init__(self, name, hp):
self._name = name
self._hp = hp
@property
def name(self):
return self._name
@property
def hp(self):
return self._hp
@hp.setter
def hp(self, hp):
self._hp = hp if hp >= 0 else 0
def attack(self, ultraman):
ultraman.hp -= randint(10, 20)
def __str__(self):
return '%s小怪兽\n' % self._name + \
'生命值:%d\n' % self._hp
def main():
u = Ultraman('熊彪', 1000, 200)
m1 = Monster('陈晨1',250)
m2 = Monster('陈晨2',500)
m3 = Monster('陈晨3',800)
ms = [m1,m2,m3]
def die(m1,m2,m3):
return False if m1.hp == 0 and m2.hp == 0 and m3.hp == 0 else True
attack_round = 1
while u.hp > 0 and die(m1,m2,m3):
print('====第%d回合====' % attack_round)
index = randint(0,2)
u.attack(ms[index])
u.magic_attack(ms)
if ms[index].hp > 0:
ms[index].attack(u)
print(u)
print(m1)
print(m2)
print(m3)
# for n in range(3):
# print('小怪兽%s的生命值为%s' %(str(ms[n]._name),str(ms[n]._hp)))
attack_round += 1
if u.hp > 0:
print('%s奥特曼胜利!' % u.name)
else:
print('小怪兽胜利!')
if __name__ == '__main__':
main()
from random import randint, randrange
from abc import ABCMeta,abstractmethod
class Fighter(object,metaclass=ABCMeta):
"""战斗者"""
# 通过__slots__魔法限定对象可以绑定的成员变量
__slots__ = ('_name', '_hp')
def __init__(self, name, hp):
"""
初始化方法
:param name: 名字
:param hp: 生命值
"""
self._name = name
self._hp = hp
@property
def name(self):
return self._name
@property
def hp(self):
return self._hp
@hp.setter
def hp(self, hp):
self._hp = hp if hp >= 0 else 0
@abstractmethod
def attack(self,other):
pass
@property
def alive(self):
return self._hp > 0
class Ultraman(Fighter):
"""奥特曼"""
__slots__ = ('_name', '_hp', '_mp')
def __init__(self, name, hp, mp):
"""
初始化方法
:param name: 名字
:param hp: 生命值
:param mp: 魔法值
"""
super().__init__(name, hp)
self._mp = mp
def attack(self, monster):
"""
攻击
:param monster: 被攻击的小怪兽
"""
monster.hp -= randint(15, 25)
def huge_attack(self, monster):
"""
究极必杀技
:param monster: 被攻击的小怪兽
:return: 使用成功返回True否则返回False
"""
if self._mp >= 50:
self._mp -= 50
injury = monster.hp * 3 // 4
injury = injury if injury >= 50 else 50
monster.hp -= injury
return True
else:
self.attack(monster)
return False
def magic_attack(self, monsters):
"""
魔法攻击
:param monsters: 被攻击的一群小怪兽
:return: 使用魔法成功返回True否则返回False
"""
if self._mp >= 20:
self._mp -= 20
for monster in monsters:
if monster.alive>0:
monster.hp -= randint(10, 15)
return True
else:
return False
def resume(self):
"""恢复魔法值"""
incr_point = randint(1, 10)
self._mp += incr_point
return incr_point
def __str__(self):
return '~~~%s奥特曼~~~\n' % self._name + \
'生命值: %d\n' % self._hp + \
'魔法值: %d\n' % self._mp
class Monster(Fighter):
"""小怪兽"""
__slots__ = ('_name', '_hp')
def attack(self, ultraman):
"""
攻击
:param ultraman: 被攻击的奥特曼
"""
ultraman.hp -= randint(10, 20)
def __str__(self):
return '~~~%s小怪兽~~~\n' % self._name + \
'生命值: %d\n' % self._hp
def is_any_alive(monsters):
"""判断有没有小怪兽是活着的"""
for monster in monsters:
if monster.alive > 0:
return True
return False
def select_alive_one(monsters):
"""选中一只活着的小怪兽"""
monsters_len = len(monsters)
while True:
index = randrange(monsters_len)
monster = monsters[index]
if monster.alive > 0:
return monster
def display_info(ultraman, monsters):
"""显示奥特曼和小怪兽的信息"""
print(ultraman)
for monster in monsters:
print(monster, end='')
def main():
u = Ultraman('骆昊', 1000, 120)
m1 = Monster('舒小玲', 250)
m2 = Monster('白元芳', 500)
m3 = Monster('王大锤', 750)
ms = [m1, m2, m3]
fight_round = 1
while u.alive and is_any_alive(ms):
print('========第%02d回合========' % fight_round)
m = select_alive_one(ms) # 选中一只小怪兽
skill = randint(1, 10) # 通过随机数选择使用哪种技能
if skill <= 6: # 60%的概率使用普通攻击
print('%s使用普通攻击打了%s.' % (u.name, m.name))
u.attack(m)
print('%s的魔法值恢复了%d点.' % (u.name, u.resume()))
elif skill <= 9: # 30%的概率使用魔法攻击(可能因魔法值不足而失败)
if u.magic_attack(ms):
print('%s使用了魔法攻击.' % u.name)
else:
print('%s使用魔法失败.' % u.name)
else: # 10%的概率使用究极必杀技(如果魔法值不足则使用普通攻击)
if u.huge_attack(m):
print('%s使用究极必杀技虐了%s.' % (u.name, m.name))
else:
print('%s使用普通攻击打了%s.' % (u.name, m.name))
print('%s的魔法值恢复了%d点.' % (u.name, u.resume()))
if m.alive > 0: # 如果选中的小怪兽没有死就回击奥特曼
print('%s回击了%s.' % (m.name, u.name))
m.attack(u)
display_info(u, ms) # 每个回合结束后显示奥特曼和小怪兽的信息
fight_round += 1
print('\n========战斗结束!========\n')
if u.alive > 0:
print('%s奥特曼胜利!' % u.name)
else:
print('小怪兽胜利!')
if __name__ == '__main__':
main()
def main():
persons = [True]*30
counter = 0
index = 0
number = 0
while counter<15:
if persons[index]:
number += 1
if number == 9:
persons[index] = False
counter +=1
number = 0
index +=1
index %= 30
for person in persons:
print('基督徒' if person else '非基督徒',end = '')
if __name__ == '__main__':
main()
from math import sqrt
class Point(object):
def __init__(self,x=0,y=0):
self._x = x
self._y = y
@property
def x(self):
return self._x
@x.setter
def x(self,x):
self._x = x
@property
def y(self):
return self._y
@y.setter
def y(self,y):
self._y=y
def move_to(self,x,y):
self._x = x
self._y = y
def move_by(self,dx,dy):
self._x += dx
self._y += dy
def distance_to(self,other):
dx = self._x-other.x
dy = self._y-other.y
return sqrt(dx**2+dy**2)
def __str__(self):
return '(%s,%s)' %(str(self._x),str(self._y))
class Line(object):
def __init__(self,start,end):
self._start = start
self._end = end
@property
def length(self):
return self._start.distance_to(self._end)
def main():
p1 = Point(3,5)
print(p1)
p2 = Point()
print(p2)
line = Line(p1,p2)
print(line.length)
if __name__ == '__main__':
main()
继承-从已经有的类创建新类的过程
提供继承信息的称为父类(超类/基类)
得到继承信息的称为子类(派生类/衍生类)
通过继承我们可以将子类中的重复代码抽取到父类中
子类通过继承并复用这些代码来减少重复代码的编写
将来如果要维护子类的公共代码只需要在父类中进行操作即可
方法重写(override)–覆盖/置换/覆写
子类在继承父类方法之后 对方法进行了重新实现
当我们给子类对象发送watch_av消息时执行的是子类重写过的方法
静态方法是指发给对象的包装器:@staticmethod
发给类的包装器是抽象类:@classmethod:def (对象)(cls,对象属性)
class Teacher(object):
def __init__(self,name,age,title):
self._name=name
self._age=age
self._title=title
@property
def name(self):
return self._name
@property
def age(self):
return self._age
@name.setter
def name(self,name):
self._name = name
@age.setter
def age(self,age):
self._age=age
@property
def title(self):
return self._title
@title.setter
def title(self,title):
self._title=title
def teach(self,course):
print('%s%s正在讲%s.' %(self._name,self._title,course))
def main():
t=Teacher('陈晨',25,'老师')
t.teach('python程序设计')
if __name__ == '__main__':
main()
python没有从语言层面支持抽象类的概念
我们可以通过abc模块来制造抽象类的效果
在定义类的时候通过指定metaclass=ABCMeta可以将类声明为抽象类
抽象类是不能创建对象的 抽象类存在的意义是专门拿给其他类继承
abc模块中还有一个包装器abstractmethod
通过这个包装器可以将方法包装为抽象方法 必须要求子类进行重写
有抽象方法就是抽象类
#员工工资结算
from abc import ABCMeta,abstractclassmethod
class Employee(object,metaclass=ABCMeta):
"""员工"""
def __init__(self,name):
"""初始化方法"""
self._name = name
@property
def name(self):
return self._name
@abstractclassmethod
def get_salary(self):
pass
class Manager(Employee):
def get_salary(self):
return 15000
class Programmer(Employee):
def __init__(self,name):
super().__init__(name)
self._working_hour = 0
@property
def working_hour(self):
return self._working_hour
@working_hour.setter
def working_hour(self,working_hour):
self._working_hour = working_hour\
if working_hour>0 else 0
def get_salary(self):
return 150*self._working_hour
class Salesman(Employee):
def __init__(self,name,sales=0):
super().__init__(name)
self._sales = sales
@property
def sales(self):
return self._sales
@sales.setter
def sales(self,sales):
self._sales = sales if sales>0 else 0
def get_salary(self):
return 1200+self._sales*0.05
def main():
emps = [Manager('刘备'),Programmer('诸葛亮'),Manager('曹操'),
Salesman('荀彧'),Salesman('吕布'),Programmer('张辽'),Programmer('赵云')]
for emp in emps:
if isinstance(emp,Programmer):
emp.working_hour = int(input('请输入%s本月工作时间:'% emp.name))
elif isinstance(emp,Salesman):
emp.sales = float(input('请输入%s本月销售额:'% emp.name))
#同样是接收get_salary这个消息,但是不同的员工表现出了不同的行为
#因为三个子类都重写了get_salary方法 所以这个方法会表现出多态行为
print('%s本月工资为:¥%.2f元' %
(emp.name,emp.get_salary()))
if __name__ == '__main__':
main()
#创建银行账户类
class Account(object):
def __init__(self,*,card_number,owner,balance=0):
self._card_number=card_number
self._owner=owner
self._balance=balance
@property
def balance(self):
return self._balance
def deposit(self,money):
if money>0:
self._balance += money
return True
return False
def withdraw(self,money):
if 0return True
return False
def transfer(self,other,money):
if self.withdraw(money):
other.deposit(money)
return True
return False
def main():
account = Account(card_number='1234567',owner='熊彪')
print(account.balance)
account.deposit(2000)
account.withdraw(500) #Account.withdraw(account,500)
print(account.balance)
if account.withdraw(5000):
print(account.balance)
else:
print('余额不足')
account2 = Account(card_number='233443222',owner='陈晨',balance=120)
if account.transfer(account2,800):
print(account.balance)
print(account2.balance)
else:
print('转账失败')
if __name__ == '__main__':
main()
#创建分数类并且可以做加减乘除运算
from math import gcd
class Fraction(object):
def __init__(self,num,den):
if den == 0:
raise ValueError('分母不能为0')
self._den = den
self._num = num
self.normalize()
self.simplify()
@property
def num(self):
return self._num
@property
def den(self):
return self._den
def add(self,other):
return Fraction(self._num*other.den+self._den*other.num,self._den*other.den)\
.simplify().normalize()
def sub(self,other):
return Fraction(self._num*other.den-self._den*other.num,self._den*other.den)\
.simplify().normalize()
def mul(self,other):
return Fraction(self._num*other.num,self._den*other.den).simplify().normalize()
def div(self,other):
return Fraction(self._num*other.den,self._den*other.num).simplify().normalize()
#运算符重写:
def __add__(self, other):
return self.add(other)
def __sub__(self, other):
return self.sub(other)
def __mul__(self, other):
return self.mul(other)
def __truediv__(self, other):
return self.div(other)
def simplify(self):
"""化简"""
if self._num != 0 and self._den != 1:
factor = gcd(abs(self._num),abs(self._den))
if factor > 1:
self._num //= factor
self._den //= factor
return self
def normalize(self):
"""正规化分数"""
if self._den < 0:
self._num = -self._num
self._den = -self._den
return self
def __str__(self):
if self._num == 0:
return '0'
elif self._den == 1:
return str(self._num)
else:
return '%d/%d' %(self._num,self._den)
def main():
f1 = Fraction(3,2)
f2 = Fraction(5,4)
print(f1+f2)
print(f1-f2)
print(f1*f2)
print(f1/f2)
if __name__ == '__main__':
main()
#创建扑克牌类
from random import randrange
class Card(object):
"""一张牌"""
def __init__(self,suite,face):
self._suite = suite
self._face = face
@property
def face(self):
return self._face
@property
def suite(self):
return self._suite
def __str__(self):
if self._face == 1:
face_str = 'A'
elif self._face == 11:
face_str = 'J'
elif self._face == 12:
face_str = 'Q'
elif self._face == 13:
face_str = 'K'
else:
face_str = str(self._face)
return '%s%s' %(self._suite,face_str)
class Poker(object):
"""一副牌"""
def __init__(self):
self._cards = []
self._current = 0
for suite in '♠♥♣♦':
for face in range(1,14):
card = Card(suite,face)
self._cards.append(card)
@property
def cards(self):
return self._cards
def shuffle(self):
"""洗牌"""
self._current = 0
cards_len = len(self._cards)
for index,card in enumerate(self._cards):
pos = randrange(cards_len)
self._cards[index],self._cards[pos] = \
self._cards[pos],self._cards[index]
@property
def next(self):
"""发牌"""
card = self._cards[self._current]
self._current += 1
return card
@property
def has_next(self):
"""还有没有牌"""
return self._currentclass Player(object):
def __init__(self,name):
self._name = name
self._cards_on_hand = []
@property
def name(self):
return self._name
@property
def cards_on_hand(self):
return self._cards_on_hand
def get(self,card):
self._cards_on_hand.append(card)
def arrange(self):
self._cards_on_hand.sort(key=get_key)
def get_key(card):
return card.face
def main():
p = Poker()
p.shuffle()
players = [Player('东邪'),Player('西毒'),Player('南帝'),Player('北丐')]
for _ in range(13):
for player in players:
player.get(p.next)
for player in players:
print(player.name + ':',end=' ')
player.arrange()
for card in player.cards_on_hand:
print(card,end='')
print()
if __name__ == '__main__':
main()
import pygame
EMPTY = 0
BLACK = 1
WHITE = 2
black_color = [0,0,0]
white_color = [255,255,255]
class RenjuBoard(object):
def __init__(self):
self._board = [[]]*15
self.reset()
def reset(self):
for row in range(len(self._board)):
self._board[row] = [EMPTY]*15
def move(self,row,col,is_black):
if self._board[row][col] == EMPTY:
self._board[row][col] = BLACK if is_black else WHITE
return True
return False
def draw(self,screen):
for index in range(15):
pygame.draw.line(screen, black_color, [20, 20 + 40 * index], [580, 20 + 40 * index], 1)
pygame.draw.line(screen, black_color, [20 + 40 * index, 20], [20 + 40 * index, 580], 1)
pygame.draw.rect(screen, black_color, [16, 16, 568, 568], 4)
pygame.draw.circle(screen, black_color, [300, 300], 5, 0)
pygame.draw.circle(screen, black_color, [140, 140], 5, 0)
pygame.draw.circle(screen, black_color, [460, 460], 5, 0)
pygame.draw.circle(screen, black_color, [460, 140], 5, 0)
pygame.draw.circle(screen, black_color, [140, 460], 5, 0)
for row in range(len(self._board)):
for col in range(len(self._board[row])):
if self._board[row][col] != EMPTY:
ccolor = black_color \
if self._board[row][col] == BLACK else white_color
pos = [40 * col + 20, 40 * row + 20]
pygame.draw.circle(screen, ccolor, pos, 20, 0)
def main():
board = RenjuBoard()
pygame.init()
pygame.display.set_caption('五子棋')
screen = pygame.display.set_mode([600,600])
screen.fill([255,255,0])
board.draw(screen)
pygame.display.flip() #刷新窗口
running = True
is_black = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# elif event.type == pygame.KEYUP:
# pass
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
x,y = event.pos
row = round((y-20) / 40)
col = round((x-20) / 40)
if board.move(row,col,is_black):
is_black = not is_black
screen.fill([255,255,0])
board.draw(screen)
pygame.display.flip()
pygame.quit()
if __name__ == '__main__':
main()
import pygame
import time
from random import randint
class Ball(object):
def __init__(self,center,color,radius,sx,sy):
self._center = center
self._color = color
self._radius = radius
self._sx = sx
self._sy = sy
@property
def center(self):
return self._center
@property
def radius(self):
return self._radius
def move(self):
x,y = self._center[0],self._center[1]
x += self._sx
y += self._sy
self._center = (x,y)
if x + self._radius >= 800 or x-self._radius <= 0:
self._sx = -self._sx
if y + self._radius >= 600 or y-self._radius <= 0:
self._sy = -self._sy
def eat(self,other):
pass
def draw(self,screen):
pygame.draw.circle(screen, self._color,self._center,self._radius, 0)
#0代表线条的宽度为0就是实心填充
def main():
balls = []
pygame.init()
screen = pygame.display.set_mode([800, 600])
pygame.display.set_caption('大球吃小球')
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN and\
event.button == 1:
x,y = event.pos
color = random_color()
radius = randint(10,100)
sx,sy = randint(-10,10),randint(-10,10)
ball = Ball(event.pos,color,radius,sx,sy)
balls.append(ball)
refresh(screen,balls)
clock.tick(24)
for ball in balls:
ball.move()
pygame.quit()
def refresh(screen,balls):
bg_color = (242, 242, 242)
screen.fill(bg_color)
for ball in balls:
ball.draw(screen)
pygame.display.flip()
def random_color():
red = randint(0,255)
green = randint(0,255)
blue = randint(0,255)
return red,green,blue
if __name__ == '__main__':
main()
from random import randint
from math import sqrt
import pygame
class Ball(object):
"""球的类"""
def __init__(self, center, color, radius, speed):
"""
球的初始化方法
:param center: 求的位置在哪
:param color: 球的颜色
:param radius: 球的半径
:param speed: 球的速度
"""
self._center = center
self._color = color
self._radius = radius
self._speed = speed
def move(self):
"""
球的移动
:return : None
"""
x, y = self._center[0], self._center[1] # 获取球当前的x, y坐标
sx, sy = self._speed[0], self._speed[1] # 获取当前球的速度
if x + self._radius > 800: # 如果球在右边框了
x -= int(self._radius/4)+abs(sx) # 大幅增加一个反向速度
sx = -sx
elif x - self._radius < 0: # 如果球在左边框了
x += int(self._radius/4)+abs(sx)
sx = -sx
elif y + self._radius > 600: # 如果球在下边框了
y -= int(self._radius/4)+abs(sy)
sy = -sy
elif y - self._radius < 0: # 如果球在上边框了
y += int(self._radius/4)+abs(sy)
sy = -sy
else:
x, y = sx + x, sy + y # 如果球在中间,正常的增减速度
self._center = (x, y) # 重置移动后的位置
self._speed = sx, sy # 速度重新赋值
@property
def center(self):
"""
装饰器修饰后的get方法
:return: x,y的坐标元组
"""
return self._center
@property
def radius(self):
return self._radius
def eat(self, other):
"""
球吃的动作,主动,而非被动
:param other: 被吃的球
:return: 布尔值,是否被吃掉了
"""
# 计算两球之间的距离
distance = sqrt((self._center[0] - other.center[0]) ** 2 +
(self._center[1] - other.center[1]) ** 2)
if distance < self._radius + other.radius and self._radius > other.radius:
self._radius = int(sqrt(other.radius ** 2 + self._radius ** 2)) # 赋予吃了球后的新半径
return True # 吃球成功
return False # 吃球失败
def draw(self, screen):
center_pos = (self._center[0], self._center[1])
pygame.draw.circle(screen, self._color, center_pos, self._radius)
def draw_ball():
"""
画一个球
:return:
"""
balls = []
pygame.init()
display = pygame.display
display.set_caption('大球吃小球')
clock = pygame.time.Clock()
screen = display.set_mode([800, 600])
is_running = True
while is_running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
is_running = False
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
color = random_color()
radius = randint(10, 50)
speed = [randint(-10, 10), randint(-10, 10)]
ball = Ball(event.pos, color, radius, speed)
balls.append(ball)
clock.tick(30)
for ball in balls:
ball.move()
# 通过双重for循环来判断,每个球是否能够被吃
for index, ball in enumerate(balls):
for j, other in enumerate(balls):
if index != j: # 不能自己吃自己
is_eat = ball.eat(other) # 是否吃成功
if is_eat:
balls.pop(j) # 成功后就将被吃的球拿出列表,达到消失的效果
refresh(screen, balls)
pygame.quit()
def refresh(screen, balls):
"""
刷新游戏页面
:param screen: 需要刷新的布局容器
:param balls: 装球的列表
:return:
"""
bg_color = (255, 255, 255)
screen.fill(bg_color)
for ball in balls:
ball.draw(screen)
pygame.display.flip()
def random_color():
"""
随机生成颜色
:return: 返回随机后的元组
"""
red = randint(0, 255)
green = randint(0, 255)
blue = randint(0, 255)
return red, green, blue
def main():
draw_ball()
pass
if __name__ == '__main__':
main()
import pygame
from random import randint
from abc import ABCMeta, abstractmethod
BLACK_COLOR = (0, 0, 0) # 全局常量,黑色
RED_COLOR = (255, 0, 0) # 全局常量,红色
FOOD_COLOR = (230, 185, 185) # 全局常量,食物的颜色
GREEN_COLOR = (0, 255, 0) # 绿色
UP = 0 # 向上
RIGHT = 1 # 向右
DOWN = 2 # 向下
LEFT = 3 # 向左
class GameObject(object, metaclass=ABCMeta):
"""游戏物品抽象父类"""
def __init__(self, pos=(0, 0), color=BLACK_COLOR):
"""初始化方法"""
self._pos = pos # 在界面中的位置
self._color = color # 在界面中的颜色
@abstractmethod
def draw(self, screen):
"""
抽象方法,绘制对象
:param screen: 在哪个图像表面层绘画
:return: None
"""
pass
@property
def pos(self):
"""
装饰器修饰,直接获取对象在界面中的位置
:return: 元组,(x,y)
"""
return self._pos
class Wall(GameObject):
"""四周墙的类"""
def __init__(self, pos, width, height, tick, color=BLACK_COLOR):
"""
初始化、构造方法
:param pos: 墙开始画的坐标点
:param width: 墙的宽度
:param height: 墙的高度
:param tick: 墙的厚度
:param color: 墙的颜色
"""
super().__init__(pos, color)
self._width = width
self._height = height
self._tick = tick
@property
def width(self):
return self._width
@property
def height(self):
return self._height
def draw(self, screen):
pygame.draw.rect(screen, self._color,
(self._pos[0], self._pos[1], self._width, self._height), self._tick)
class Food(GameObject):
"""食物类"""
def __init__(self, pos, size=10, color=RED_COLOR):
"""
初始化方法
:param pos: 外切圆坐标
:param color:
:param size:
"""
super().__init__(pos, color)
self._is_hide = 0 # 是否隐藏的计数器,为了食物点不频繁的闪烁
self._size = size # 食物点的大小,直径
def draw(self, screen):
"""
绘制食物的方法
:param screen: 在哪个表面绘制
:return: None
"""
# 如果不是5的倍数,就消失一次,减少Boolean值的频繁闪烁,数值越大闪烁越快
if self._is_hide % 5 != 0:
# 开始在界面进行绘制食物
pygame.draw.circle(screen, self._color,
(self._pos[0] + self._size // 2, self._pos[1] + self._size // 2),
self._size // 2, 0)
self._is_hide += 1 # 计数点自加
class SnakeNode(GameObject):
"""蛇的结点类"""
def __init__(self, pos, size, color=GREEN_COLOR):
"""
初始化构造方法
:param pos: 结点的坐标
:param size: 结点的大小
:param color: 结点的颜色
"""
super().__init__(pos, color)
self._size = size
def draw(self, screen):
"""
绘制结点
:param screen: 在哪个表面进行绘制
:return: None
"""
# 绘制内部绿色的结点
pygame.draw.rect(screen, self._color,
(self._pos[0], self._pos[1], self._size, self._size), 0)
# 绘制结点的外部边框
pygame.draw.rect(screen, BLACK_COLOR,
(self._pos[0], self._pos[1], self._size, self._size), 1)
@property
def size(self):
"""
装饰器,修饰get_size方法
:return: 结点的大小
"""
return self._size
class Snake(GameObject):
"""蛇的类"""
def __init__(self):
"""
初始化构造方法
"""
super().__init__()
self._snake_dir = LEFT # 默认的蛇爬行的方向为左
self._nodes = [] # 蛇的结点容器
self._aline = True # 蛇是否存活
self._eat_food = False # 是否吃到食物
for index in range(5): # 初始化5个结点在列表容器中
node = SnakeNode((290 + index * 20, 250), 20)
self._nodes.append(node)
def is_in_nodes(self, x, y):
"""
判断刷新出来的苹果是否在蛇的结点上
:param x: 食物的x坐标
:param y: 食物的y坐标
:return: boolean 值,在为True,不在为False
"""
for node in self._nodes:
if node.pos[0] == x and node.pos[1] == y:
return True
return False
@property
def aline(self):
"""
装饰器,获取对象属性
:return: aline属性
"""
return self._aline
@property
def snake_dir(self):
"""
装饰器,获取蛇移动的方向
:return: snake_dir 属性
"""
return self._snake_dir
@property
def head(self):
"""
装饰器,获取容器中的第一个结点
:return: nodes[0] 第一个元素
"""
return self._nodes[0]
def change_dir(self, new_dir):
"""
改变蛇前进的方向
:param new_dir: 前进的新方向
:return: None
"""
# 如果方向和原来方向不同,而且相反,就可以改变,蛇的前进方向
if new_dir != self._snake_dir and (self._snake_dir + new_dir) % 2 != 0:
self._snake_dir = new_dir
def draw(self, screen):
"""
画出蛇
:param screen: 在哪个表面画蛇
:return: None
"""
# 遍历结点,同时画出结点
for node in self._nodes:
node.draw(screen)
def move(self):
"""
蛇移动的方法
:return: None
"""
# if self._aline:
head = self.head # 获取蛇头
snake_dir = self._snake_dir # 获取蛇前进的方向
# 获取蛇头想x,y坐标和头的大小
x, y, size = head.pos[0], head.pos[1], head.size
if snake_dir == UP: # 向上移动
y -= size # y坐标减少
elif snake_dir == RIGHT: # 向右移动
x += size # x坐标增加
elif snake_dir == DOWN: # 向下移动
y += size # y坐标增加
else: # 向左移动
x -= size # x坐标减少
new_head = SnakeNode((x, y), size) # 新建一个结点对象
self._nodes.insert(0, new_head) # 添加到蛇头
if self._eat_food: # 如果吃到了食物
self._eat_food = False # 重设参数为没吃到,同时不移除最后的一个结点
else: # 没吃到食物
self._nodes.pop() # 移除最后的一个结点元素
def collide(self, wall):
"""
判断是否撞墙
:param wall: 墙的对象
:return: None
"""
x, y = wall.pos # 获取墙的坐标
width = wall.width # 获取墙的宽
height = wall.height # 获取墙的高
node_one = self._nodes[0] # 获取蛇头对象
# 如果蛇头的x坐标小于了墙的最左边,或加上自身宽度大于了墙的初始位置加宽度,
# 或蛇头的y坐标小于了墙最上面,或加上自身宽度大于了墙初始xy位置加高度
if x > node_one.pos[0] or node_one.pos[0] + node_one.size > x + width \
or y > node_one.pos[1] or node_one.pos[1] + node_one.size > y + height:
self._aline = False # 蛇撞到墙,死了
else:
self._aline = True # 蛇没撞到墙,还或者
def eat_food(self, food):
"""
蛇吃食物的行为
:param food: food对象
:return: Boolean 是否吃到
"""
head = self.head # 获取蛇头结点
# 如果蛇头的x,y坐标与食物的x,y坐标重合,那么就吃到了食物
if head.pos[0] == food.pos[0] and head.pos[1] == food.pos[1]:
self._eat_food = True # 吃到食物的状态为True
return True # 返回True
return False # 没吃到食物返回False
def eat_me(self):
"""
吃自己判断
:return: None
"""
head = self.head # 获取蛇头结点对象
# 从蛇的第4个结点开始遍历,因为,蛇只能吃到自己的第四个结点
for index in range(3, len(self._nodes)):
# 如果蛇头坐标和蛇身坐标重合,就吃到了自己
if head.pos[0] == self._nodes[index].pos[0] and \
head.pos[1] == self._nodes[index].pos[1]:
self._aline = False # 修改当前蛇的存活状态
@property
def snake_len(self):
"""
获取蛇的结点长度
:return: 蛇的长度
"""
return len(self._nodes)
def main():
"""游戏主函数"""
def refresh():
"""刷新游戏窗口"""
screen.fill((242, 242, 242))
snake.draw(screen)
food.draw(screen)
wall.draw(screen)
pygame.display.flip()
def handle_key_event(key_event):
"""游戏按键事件监听"""
key = key_event.key # 拿取到所按的按键的值
if key == pygame.K_F2: # 如果为F2则重新开始游戏
reset_game()
# 如果key为w,a,s,d则为方向控制
elif key in (pygame.K_w, pygame.K_d, pygame.K_s, pygame.K_a):
if snake.aline: # 如果蛇还活着则进行操作
if key == pygame.K_w: # 按下了W
new_dir = UP # 设置新的方向向上
elif key == pygame.K_d: # 按下了D
new_dir = RIGHT # 设置新的方向向右
elif key == pygame.K_s: # 按下了S
new_dir = DOWN # 设置新的方向向下
else: # 按下了A
new_dir = LEFT # 设置新的方向向左
snake.change_dir(new_dir) # 调用蛇的方法,发送消息改变方向
pygame.event.clear() # 清除按键事件
def reset_game():
"""重设游戏的食物和蛇的对象,游戏重开"""
nonlocal food, snake, game_over # 设置为嵌套值域,而非当前函数
food = create_apple(snake) # 创建新的食物对象
snake = Snake() # 创建新的蛇对象
game_over = False # 游戏继续
scores = [] # 分数容器
pygame.init() # 初始化pygame
wall = Wall((10, 10), 600, 600, 3) # 创建墙的对象
screen = pygame.display.set_mode([620, 620]) # 设置窗口大小
screen.fill((242, 242, 242)) # 设置填充的背景
pygame.display.set_caption('贪吃蛇') # 设置窗口标题
pygame.display.flip() # 刷新界面
clock = pygame.time.Clock() # 设置时钟
snake = Snake() # 初始化一个蛇对象
food = create_apple(snake) # 初始化一个食物对象
reset_game() # 重开游戏,刷新界面
is_running = True # 游戏运行状态
game_over = False # 游戏当前回合状态
while is_running:
for event in pygame.event.get(): # 获取事件
if event.type == pygame.QUIT: # 判断事件类型是否为退出
is_running = False
elif event.type == pygame.KEYDOWN:
handle_key_event(event) # 传递按钮点击事件
if not game_over: # 本回合是否继续
if snake.aline: # 当前蛇是否还存活
refresh() # 刷新游戏窗口
snake.move() # 蛇开始移动
snake.collide(wall) # 判断蛇是否撞墙
snake.eat_me() # 判断蛇是否吃到自己
if snake.eat_food(food): # 判断蛇是否吃到食物
food = create_apple(snake) # 吃到食物,创建一个新的食物对象
else: # 本回合结束
game_over = True # 设置本回合结束
scores.append(snake.snake_len - 5) # 将分数添加到容器中
show_info(screen, scores) # 显示分数
clock.tick(5) # 帧数
pygame.quit() # 销毁pygame
pass
def show_info(screen, scores):
"""
在界面中绘制分数的函数
:param screen: 绘制的表面
:param scores: 绘制的分数列表
:return: None
"""
scores.sort(reverse=True) # 对分数进行排序
my_font = pygame.font.SysFont('宋体', 60) # 设置字体格式
game_over = my_font.render('GAME OVER', False, [0, 0, 0]) # 字体的文本和颜色
screen.blit(game_over, (180, 260)) # 开始绘制的坐标
list_len = len(scores) if len(scores) < 5 else 5 # 获取分数容器的大小,最多展示前五
for index in range(list_len): # 遍历欠前五的分数
my_font = pygame.font.SysFont('宋体', 40) # 设置字体
# 绘制的文字内容和分数
score = my_font.render('Number ' + str(index + 1) + ':' + str(scores[index]), False, [255, 0, 0])
screen.blit(score, (200, 300 + index * 40)) # 绘制的位置
pygame.display.flip() # 刷新界面
def create_apple(snake):
"""
创建苹果在蛇的身体之外
:param snake: 蛇的对象
:return: 在蛇身之外的Food坐标
"""
row = randint(0, 29) # 随机行号
col = randint(0, 29) # 随机列号
x, y = 10 + 20 * col, 10 + 20 * row # 换算为对应的坐标点
if not snake.is_in_nodes(x, y): # 如果不在蛇身上
return Food((10 + 20 * col, 10 + 20 * row), 20) # 返回一个食物对象
else:
create_apple(snake) # 递归调用函数直到有返回值
if __name__ == '__main__':
main()
import time
def main():
try:#保护下面的代码防止程序崩溃
with open('./abc/zhou5.2.py','r',encoding='utf-8') as fs:
# content = fs.read()
# for line in fs:
# print(line,end='')
# time.sleep(1)
# print(content)
mylist = fs.readlines()
print(mylist)
#fs.close()
except (FileNotFoundError ,IOError):
print('指定的文件无法打开')
print('程序执行结束')
if __name__ == '__main__':
main()
import json
def main():
studet = {'name':'熊彪','age':25,'grade':65}
try:
with open('data.json','r',encoding='utf-8') as fs:
yourdict = json.load(fs)
print(type(yourdict))
print((yourdict))
with open('data.json','w',encoding='utf-8') as fs:
json.dump(studet,fs)
except IOError as e:
print((e))
if __name__ == '__main__':
main()
def main():
try:
with open('./tu/mv/1.jpg','rb') as fs1:
data = fs1.read()
print(data)
with open('./abc/cd.jpg', 'wb') as fs2:
fs2.write(data)
except (FileNotFoundError, IOError):
print('指定的文件无法打开')
print('程序执行结束')
if __name__ == '__main__':
main()
from math import sqrt
def is_prime(n):
assert n>0
for factor in range(2,int(sqrt(n))+1):
if n%factor == 0:
return False
return True if n!=1 else False
def main():
filenames = ['a.txt','b.txt','c.txt']
fs_list = []
try:
#把可能出状况(在执行时有风险)的代码放到try代码块保护执行
for filename in filenames:
fs_list.append(open(filename,'w',encoding='utf-8')) #把文件流装进新的容器
for number in range(1,10000):
if is_prime(number):
if number<100:
fs_list[0].write(str(number) + '\n')
elif number<1000:
fs_list[1].write(str(number) + '\n')
else:
fs_list[2].write(str(number)+'\n')
#except可以写多个分别用于处理不同的异常状况
except IOError:
#如果try中出现了状况就通过except来捕获错误(异常)进行对应的处理
print('读写文件错误!')
else:
pass
#如果没有出状况那么可以把无风险的代码放到else中执行
finally:
#此处是最好的释放外部资源的位置因为这里的代码总是会执行
#所以此处最适合做释放外部资源的操作
for fs in fs_list:
fs.close()
print('操作完成!')
if __name__ == '__main__':
main()
# URL - Uniform Resource Locator
#天行数据找美女图片
import requests
import json
def main():
# request / response
resp = requests.get('http://api.tianapi.com/meinv/?key=81a5d68102a2826cbc8220c325d1a440&num=10')
mydict = json.loads(resp.text)
for tempdict in mydict['newslist']:
pic_url = tempdict['picUrl']
resp = requests.get(pic_url)
filename = pic_url[pic_url.rfind('/') + 1:]
try:
with open(filename, 'wb') as fs:
fs.write(resp.content)
except IOError as e:
print(e)
if __name__ == '__main__':
main()