2020-11-29 周记录(九)

Pygame

重构:模块 game_functions

game_functions.py--->函数 check_events()

import sys
import pygame

def check_events():
    """响应按键和鼠标事件"""
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

game_functions.py--->函数 update_screen()

import sys
import pygame

def check_events():
    """响应按键和鼠标事件"""
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

def update_screen(ai_settings,screen,ship):
    """更新屏幕上的图像,并切换到新屏幕"""
    #每次循环都重新绘制屏幕
    screen.fill(ai_settings.bg_color)
    ship.blitme()

    #让最近绘制的屏幕可见
    pygame.display.flip()

修改alien_invasion.py

import pygame
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(screen)

    #开始游戏的主循环
    while True:

        gf.check_events()
        gf.update_screen(ai_settings,screen,ship)
        
run_game()

左右移动飞船

game_functions.py

import sys
import pygame

def check_events(ship):
    """响应按键和鼠标事件"""
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                ship.moving_right = True
            elif event.key == pygame.K_LEFT:
                ship.moving_left = True

        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_RIGHT:
                ship.moving_right = False
            elif event.key == pygame.K_LEFT:
                ship.moving_left = False

def update_screen(ai_settings,screen,ship):
    """更新屏幕上的图像,并切换到新屏幕"""
    #每次循环都重新绘制屏幕
    screen.fill(ai_settings.bg_color)
    ship.blitme()

    #让最近绘制的屏幕可见
    pygame.display.flip()

ship.py

import pygame

class Ship():

    def __init__(self,screen):
        """初始化飞船并设置其初始位置"""
        self.screen = screen

        #加载飞船图像并获取其外接矩形
        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  #飞船中心的x坐标
        self.rect.bottom = self.screen_rect.bottom  #飞船下边缘的y坐标

        #移动标志
        self.moving_right = False
        self.moving_left = False

    def update(self):
        """根据移动标志调整飞船的位置"""
        if self.moving_right:
            self.rect.centerx += 1
        if self.moving_left:
            self.rect.centerx -= 1
  
    def blitme(self):
        """在指定位置绘制飞船"""
        self.screen.blit(self.image,self.rect)
        

alien_invasion.py

import pygame
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(screen)

    #开始游戏的主循环
    while True:

        gf.check_events(ship)
        ship.update()
        gf.update_screen(ai_settings,screen,ship)
        
run_game()

调整飞船的速度

settings.py

class Settings():
    """储存《外星人入侵》的所有设置的类"""

    def __init__(self):
        """初始化游戏的设置"""
        #屏幕设置
        self.screen_width = 1280
        self.screen_height = 800
        self.bg_color = (230,230,230)

        #飞船的设置
        self.ship_speed_factor = 1.5

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  #飞船中心的x坐标
        self.rect.bottom = self.screen_rect.bottom  #飞船下边缘的y坐标

        #在飞船的属性center中储存小数值
        self.center = float(self.rect.centerx)

        #移动标志
        self.moving_right = False
        self.moving_left = False

    def update(self):
        """根据移动标志调整飞船的位置"""
        #更新飞船的center值,而不是rect
        if self.moving_right:
            self.center += self.ai_settings.ship_speed_factor
        if self.moving_left:
            self.center -= self.ai_settings.ship_speed_factor

        #根据self.center更新rect对象
        self.rect.centerx = self.center
  
    def blitme(self):
        """在指定位置绘制飞船"""
        self.screen.blit(self.image,self.rect)
        

alien_invasion.py

import pygame
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)

    #开始游戏的主循环
    while True:

        gf.check_events(ship)
        ship.update()
        gf.update_screen(ai_settings,screen,ship)
        
run_game()

Python 常见双下划线关键字的用法

1.__init__
__init__ 方法通常用在初始化一个类实例的时候,例如:

class Person(object):

      def __init__(self, name, age):

      self.name = name

      self.age = age

2.__str__
__str__用来返回对象的字符串表达式。例如:

class Person(object):

     def __init__(self, name):

          super(Person, self).__init__()

          self.name = name

    def __str__(self):

         return'Hola,%s' % self.name

lina = Person('Lina')

print(lina)

在我们编写一个新的Python类的时候,总是在最开始位置写一个初始化方法__init__,以便初始化对象,然后会写一个__str__方法,方面我们调试程序。

3.__new__
__new__方法的调用是发生在__init__之前的

class Person(object):



     def __new__(cls,*args, **kwargs):

          print('new called')

          return object.__new__(cls)

     def __init__(self, name):

          print('init called')

          super(Person, self).__init__()

          self.name = name

     def __str__(self):

          return'Hola,%s' % self.name

lina = Person('Lina')

print(lina)

__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供

__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例

__init__ 和 __new__ 最主要的区别在于:

1.__init__ 通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。

2.__new__ 通常用于控制生成一个新实例的过程。它是类级别的方法。

__new__ 的作用

依照Python官方文档的说法,__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass。

4.__name__和__main__
为了区分 主执行代码和被调用文件,python引入了变量:__name__。__name__就是标识模块的名字的一个系统变量。这里分两种情况:假如当前模块是主模块(也就是调用其他模块的模块),那么此模块名字就是__main__,通过if判断这样就可以执行“__mian__:”后面的主函数内容;假如此模块是被import的,则此模块名字为文件名字(不加后面的.py),通过if判断这样就会跳过“__mian__:”后面的内容。

5.__slots__
为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的slots变量,来限制该class实例能添加的属性。比如,只允许对Student实例添加name和age属性:

class Student(object):

slots = ('name', 'age') # 用tuple定义允许绑定的属性名称

Python __str__() 方法

定义 __str__() 方法:

class Cat:
    """定义一个猫类"""
 
    def __init__(self, new_name, new_age):
        """在创建完对象之后 会自动调用, 它完成对象的初始化的功能"""
        # self.name = "汤姆"
        # self.age = 20
        self.name = new_name
        self.age = new_age  # 它是一个对象中的属性,在对象中存储,即只要这个对象还存在,那么这个变量就可以使用
        # num = 100  # 它是一个局部变量,当这个函数执行完之后,这个变量的空间就没有了,因此其他方法不能使用这个变量
 
    def __str__(self):
        """返回一个对象的描述信息"""
        # print(num)
        return "名字是:%s , 年龄是:%d" % (self.name, self.age)
 
    def eat(self):
        print("%s在吃鱼...." % self.name)
 
    def drink(self):
        print("%s在喝可乐..." % self.name)
 
    def introduce(self):
        # print("名字是:%s, 年龄是:%d" % (汤姆的名字, 汤姆的年龄))
        # print("名字是:%s, 年龄是:%d" % (tom.name, tom.age))
        print("名字是:%s, 年龄是:%d" % (self.name, self.age))
 
# 创建了一个对象
tom = Cat("汤姆", 30)
print(tom)

总结:
1.在python中方法名如果是__xxxx__()的,那么就有特殊的功能,因此叫做“魔法”方法
2.当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据
3.__str__方法需要返回一个字符串,当做这个对象的描写

Python学校人事管理系统

编写类

import datetime

class PersonTypeError(TypeError):
    pass

class PersonValueError(ValueError):
    pass

class Person():
    _num = 0

    def __init__(self,name,sex,birthday,ident):
        if not (isinstance(name,str) and sex in ("女","男")):
            raise PersonValueError(name,sex)
        try:
            birth = datetime.date(*birthday) #生成一个日期对象
        except:
            raise PensonValueError("Wrong date:",birthday)
        self._name = name
        self._sex = sex
        self._birthday = birth
        self._id = ident
        Person._num += 1  #实例计数、

    def id(self):
        return self._id
    def name(self):
        return self._name
    def sex(self):
        return self._sex
    def birthday(self):
        return self._birthday
    def age(self):
        return (datetime.date.today().year - self._birthday.year)

    def set_name(self,name):
        """修改名字"""
        if not isinstance(name,str):
            raise PersonValueError("set_name",name)
        self._name = name

    def __lt__(self,another):
        if not isinstance(another,Person):
            raise PersonTypeError(another)
        return self._id < another._id

    @classmethod
    def num(cls): return Person._num

    def __str__(self):
        return " ".join((self._id,self._name,self._sex,str(self._birthday)))

    def details(self):
        return ",".join(("编号: " + self._id,
                         "姓名: " + self._name,
                         "性别: " + self._sex,
                         "出生日期: " + str(self._birthday)))

class Student(Person):
    _id_num = 0

    @classmethod
    def _id_gen(cls):
        """实现学号生成规则"""
        cls._id_num += 1
        year = datetime.date.today().year
        return "1{:04}{:05}".format(year,cls._id_num)

    def __init__(self,name,sex,birthday,department):
        Person.__init__(self,name,sex,birthday,Student._id_gen())
        self._department = department
        self._enroll_date = datetime.date.today()
        self._courses = {} #一个空字典

    def set_course(self,course_name):
        """设置字典键对应值为空"""
        self._courses[course_name] = None

    def set_score(self,course_name,score):
        """给字典中的键赋值"""
        if course_name not in self._courses:
            raise PersonValueError("No this course selected:",course_name)
        self._courses[course_name] = score

    def scores(self):
        return [(cname,self._courses[cname]) for cname in self._courses]

    def details(self):
        return ",".join((Person.details(self),
                         "入学日期: " + str(self._enroll_date),
                         "院系: " + self._department,
                         "课程记录: " + str(self.scores())))
        
class Staff(Person):
    _id_num = 0

    @classmethod
    def _id_gen(cls,birthday):
        """实现职工号生成规则"""
        cls._id_num += 1
        birth_year = datetime.date(*birthday).year
        return "0{:04}{:05}".format(birth_year,cls._id_num)

    def __init__(self,name,sex,birthday,entry_date=None):
        super().__init__(name,sex,birthday,Staff._id_gen(birthday))

        if entry_date:
            try:
                self._entry_date = datetime.date(*entry_date)
            except:
                raise PersonValueError("Wrong date:",entry_date)

        else:
            self._entry_date = datetime.date.today()
        self._salary = 1720 #工资,可修改
        self._department = "未定" #需另行设定
        self._position = "未定"   #需另行设定

    def set_salary(self,amount):
        if not type(amount) is int:
            raise TypeError
        self._salary = amount

    def set_position(self,position):
        self._position = position

    def set_department(self,department):
        self._department = department

    def details(self):
        return ",".join((super().details(),
                         "入职日期: " + str(self._entry_date),
                         "院系: " + self._department,
                         "职位: " + self._position,
                         "工资: " + str(self._salary)))

调用

p1 = Staff("谢雨洁","女",(1995,7,30),(2002,5,5))
p2 = Staff("克拉克","男",(1990,6,21))

p3 = Student("王晓豪","男",(1999,11,12),"计算机科学与技术")
p4 = Student("布鲁斯","男",(1997,10,29),"软件工程")

print(p1)
print(p2)
print(p3)
print(p4)

p1.set_department("数学")
p1.set_position("副教授")
p1.set_salary(8400)

print(p1.details())
print(p2.details())

p3.set_course("数据结构")
p3.set_score("数据结构",100)
p3.set_course("算法")
p3.set_score("算法",99)

print(p3.details())
print(p4.details())

结果

0199500001 谢雨洁 女 1995-07-30
0199000002 克拉克 男 1990-06-21
1202000001 王晓豪 男 1999-11-12
1202000002 布鲁斯 男 1997-10-29
编号: 0199500001,姓名: 谢雨洁,性别: 女,出生日期: 1995-07-30,入职日期: 2002-05-05,院系: 数学,职位: 副教授,工资: 8400
编号: 0199000002,姓名: 克拉克,性别: 男,出生日期: 1990-06-21,入职日期: 2020-11-30,院系: 未定,职位: 未定,工资: 1720
编号: 1202000001,姓名: 王晓豪,性别: 男,出生日期: 1999-11-12,入学日期: 2020-11-30,院系: 计算机科学与技术,课程记录: [('数据结构', 100), ('算法', 99)]
编号: 1202000002,姓名: 布鲁斯,性别: 男,出生日期: 1997-10-29,入学日期: 2020-11-30,院系: 软件工程,课程记录: []
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容