测试题:
0.继承机制给程序猿带来的最明显的好处是?
写一个新类时可以从旧类继承,不用重复编写,减少重复劳动。
1.如果按以下方式重写魔法方法__init__,结果会怎么样?
class Myclass:
def __init__(self):
return "I love FishC.com!"
会报错,因为__init__不能返回除None的其他对象。
>>> a = Myclass()
Traceback (most recent call last):
File "" , line 1, in <module>
a = Myclass()
TypeError: __init__() should return None, not 'str'
2.当子类定义了与父类相同名字的属性或方法,Python是否会自动删除父类的相关属性和方法?
不会删除!Python的做法跟其他大部分面向对象编程语言一样,都是将父类属性或方法覆盖,子类对象调用的时候调用到覆盖后的新属性或方法,但父类的任然存在,只是子类“看不到”。
3.假设已经有鸟类的定义,现在我要定义企鹅类继承于鸟类,但我们知道企鹅是不会飞的,我们应该如何屏蔽父类(鸟类)中飞的方法?
覆盖父类方法,例如将函数体内容写pass,这样调用fly方法就没有任何反应了。
4.super函数有什么“超级”的地方?
super函数超级之处在于你不需要明确给出任何基类的名字,它会自动帮你找出所有基类以及对应的方法。由于你不用给出基类的名字,这就意味着你如果需要改变类继承关系,你只需要改变class语句里的父类即可,而不必在大量代码中去修改所有被继承的方法。
5.多重继承使用不当会导致重复调用(也叫钻石继承、菱形继承)的问题,请分析以下代码在实际编程中有可能导致什么问题?
class A():
def __init__(self):
print("进入A...")
print("离开A...")
class B(A):
def __init__(self):
print("进入B...")
A.__init__(self)
print("离开B...")
class C(A):
def __init__(self):
print("进入C...")
A.__init__(self)
print("离开C...")
class D(B,C):
def __init__(self):
print("进入D...")
B.__init__(self)
C.__init__(self)
print("离开D...")
多继承容易导致重复调用问题,上例中实例化D类后A被前后进入了两次。
>>> d = D()
进入D...
进入B...
进入A...
离开A...
离开B...
进入C...
进入A...
离开A...
离开C...
离开D...
6.如何解决上一题中出现的问题?
使用super()方法。
class A():
def __init__(self):
print("进入A...")
print("离开A...")
class B(A):
def __init__(self):
print("进入B...")
super().__init__()
print("离开B...")
class C(A):
def __init__(self):
print("进入C...")
super().__init__()
print("离开C...")
class D(B,C):
def __init__(self):
print("进入D...")
super().__init__()
print("离开D...")
结果就不会重复调用了
>>> e = D()
进入D...
进入B...
进入C...
进入A...
离开A...
离开C...
离开B...
离开D...
动动手
0.定义一个点(Point)类和直线(Line)类,使用getLen方法可以获得直线的长度。
提示:
1.设点A(X1,Y1)、点B(X2,Y2),则两点构成的直线长度|AB| = ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 ) \sqrt{(x1-x2)^2+(y1-y2)^2 )} (x1−x2)2+(y1−y2)2)
2.Python中计算开根号可使用math模块中的sqrt函数
3.直线需有两点构成,因此初始化时需有两个点(Point)对象作为参数
import math
class Point(object):
"""docstring for Point"""
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y
def getX(self):
return self.x
def getY(self):
return self.y
class Line(Point):
"""docstring for Line"""
def __init__(self, p0, p1):
self.x = p1.getX() - p0.getX()
self.y = p1.getY() - p0.getY()
self.len = math.sqrt(self.x * self.x + self.y * self.y)
def getlen(self):
return self.len
测试结果:
>>> p0 = Point(1,5)
>>> p1 = Point(2,6)
>>> line = Line(p0, p1)
>>> line.getlen()
1.4142135623730951
1.展示一个你的作品:你已经掌握了Python大部分知识,要开始自食其力了!请画一个星期做一个你能做出的最好的作品(可以是游戏、应用软件、脚本),使用上你学过的任何东西(类,函数,字典,列表……)来改进你的程序。
这次写了一个外星人飞船游戏,上下左右键控制移动,空格键发射炮弹,后续还会继续改进。
①主程序文件:alien_invasion.py
import pygame
from pygame.sprite import Group
from settings import Settings
from ship import Ship
import game_functions as gf
def run_game():
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
pygame.display.set_caption("Alien Invasion")
# 创建一艘飞船
ship = Ship(ai_settings, screen)
# 创建一个用于存储子弹的编组
bullets = Group()
# 开始游戏主循环
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
gf.update_bullets(bullets)
gf.update_screen(ai_settings, screen, ship, bullets)
run_game()
②炮弹:bullet.py
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
"""一个对飞船发射的子弹进行管理的类"""
def __init__(self, ai_settings, screen, ship):
"""在飞船所在的位置创建一颗子弹对象"""
super(Bullet, self).__init__()
self.screen = screen
# 在(0,0)处创建一个子弹矩形,在设置正确的位置
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width, ai_settings.bullet_height)
self.rect.centerx = ship.rect.centerx
self.rect.top = ship.rect.top
# 存储用小数表示的子弹位置
self.y = float(self.rect.y)
self.color = ai_settings.bullet_color
self.speed_factor = ai_settings.bullet_speed_factor
def update(self):
"""向上移动子弹"""
# 更新表示子弹位置的小数值
self.y -= self.speed_factor
# 更新表示子弹的rect的位置
self.rect.y = self.y
def draw_bullet(self):
"""绘制子弹"""
pygame.draw.rect(self.screen, self.color, self.rect)
③飞船:ship.py
import pygame
class Ship():
def __init__(self, ai_settings, screen):
"""初始化飞船并设置其初始位置"""
self.screen = screen
self.ai_settings = ai_settings
# 加载飞船图像并获取其外接矩形
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
# 将每艘新飞船放在屏幕底部中央
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
# 在飞船属性center中存储小数值
self.center = float(self.rect.centerx)
# 在飞船属性bottomx中存储小数值
self.bottomx = float(self.rect.bottom)
# 移动标志
self.moving_right = False
self.moving_left = False
self.moving_up = False
self.moving_down = False
def update(self):
"""根据移动标志调整飞船的位置"""
# 更新飞船的center值而不是rect
if self.moving_right and self.rect.right < self.screen_rect.right:
self.center += self.ai_settings.ship_speed_factor
if self.moving_left and self.rect.left > 0:
self.center -= self.ai_settings.ship_speed_factor
if self.moving_down and self.rect.bottom < self.screen_rect.bottom:
self.bottomx += self.ai_settings.ship_speed_factor
if self.moving_up and self.rect.top > 0:
self.bottomx -= self.ai_settings.ship_speed_factor
# 根据self.center更新rect对象
self.rect.centerx = self.center
self.rect.bottom = self.bottomx
def blitme(self):
"""在指定位置创建飞船"""
self.screen.blit(self.image, self.rect)
④设置文件:settings.py
class Settings():
"""存储外星人入侵的所有设置"""
def __init__(self):
"""初始化游戏的设置"""
# 屏幕设置
self.screen_width = 800
self.screen_height = 500
self.bg_color = (230, 230, 230)
self.ship_speed_factor = 1.5
# 子弹设置
self.bullet_speed_factor = 1
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = 60, 60, 60
self.bullets_allowed = 3
⑤功能函数:game_functions.py
import sys
import pygame
from bullet import Bullet
def check_keydown_events(event, ai_settings, screen, ship, bullets):
"""响应按键按下"""
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_UP:
ship.moving_up = True
elif event.key == pygame.K_DOWN:
ship.moving_down = True
elif event.key == pygame.K_SPACE:
fire_bullet(ai_settings, screen, ship, bullets)
def fire_bullet(ai_settings, screen, ship, bullets):
# 创建一颗子弹,并将其加入到编组bullets中
if len(bullets) < ai_settings.bullets_allowed:
new_bullet = Bullet(ai_settings, screen, ship)
bullets.add(new_bullet)
def check_keyup_events(event, ship):
"""响应按键松开"""
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
elif event.key == pygame.K_UP:
ship.moving_up = False
elif event.key == pygame.K_DOWN:
ship.moving_down = False
def check_events(ai_settings, screen, ship, bullets):
"""响应按键和鼠标事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
check_keydown_events(event, ai_settings, screen, ship, bullets)
elif event.type == pygame.KEYUP:
check_keyup_events(event, ship)
def update_screen(ai_settings, screen, ship, bullets):
"""更新屏幕上的图像,并切换到新屏幕"""
# 每次循环都重绘屏幕
screen.fill(ai_settings.bg_color)
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
# 让最近绘制的屏幕可见
pygame.display.flip()
def update_bullets(bullets):
"""更新子弹的位置,并删除已经消失的子弹"""
# 更新子弹位置
bullets.update()
# 删除已经消失的子弹
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
零基础入门Python系列文章也要画上一个句号了,接下我将学习Python爬虫和数据处理方面的内容,感谢大家!