Python100天
-
chapter01 初始Python
python --version import sys print(sys.version_info) print(sys.version)
# 单行注释 ''' 多行注释 ''' """ 多行注释 """
import this # Python之禅
""" Python 简单绘画 """ import turtle turtle.pensize(4) turtle.pencolor('red') turtle.forward(100) turtle.right(90) turtle.forward(100) turtle.right(90) turtle.forward(100) turtle.right(90) turtle.forward(100) turtle.mainloop()
-
chpater02 语言元素
-
指令和程序
-
变量和类型
- 整型:
- 0b100 二进制
- 0o100 八进制
- 100 十进制
- 0x100 十六进制
- 浮点型:
- 数字写法:123.456
- 科学技术法写法:1.23456e2
- 字符串型:
- 原始字符串表示法:
- 字节字符串表示法:
- Unicode字符串表示法
- 布尔型:
- True和False
- 复数型:
- 3+5j
- 整型:
-
变量命名
-
变量的使用
''' 使用type()检查变量的类型 ''' a = 100 b = 12.345 c = 1 + 5j d = 'hello, world' e = True print(type(a)) # <class 'int'> print(type(b)) # <class 'float'> print(type(c)) # <class 'complex'> print(type(d)) # <class 'str'> print(type(e)) # <class 'bool'>
int() # 将一个数值或字符串转换成整数,可以指定进制 float() # 将一个字符串转换成浮点数。 str() # 将指定的对象转换成字符串形式,可以指定编码 chr() # 将整数转换成该编码对应的字符串(一个字符) ord() # 将字符串(一个字符)转换成对应的编码(整数) a = int(input('a = ')) b = int(input('b = ')) print('%d / %d = %f' % (a, b, a / b)) # %d:整数点位符,%f:小数占位符 print('%d %% %d = %d' % (a, b , a % b)) # %%:表示百分号
-
运算符
-
算术运算符
- ’+‘、’-’、’*’、’/’
-
赋值运算符
- ‘=’,’+=‘
-
比较运算符
- ‘==’,’!=’
-
逻辑运算符
‘and’、‘or’、‘not’
-
-
实例
''' 将华氏温度转换为摄氏温度 ''' f = float(input('请输入华氏温度:')) c = (f - 32) / 1.8 print("%.1f华氏度 = %.1f摄氏度" % (f, c)) print(f'{f:.1f}华氏度 = {c:.1f}摄氏度') # `{f:.1f}`和`{c:.1f}`表示`f`和`c`替换占位符,`.1f`表示这是一个浮点数,小数点后保留1位有效数字。
-
-
chapter03 分支结构
- if语句的使用
- 关键字:if, elif, else
- 使用缩进方式来表示代码的层次结构,通常使用4个空格
- if语句的使用
-
chapter04 循环结构
-
for-in循环
sum = 0 for x in range(101): sum += x print(sum) # rang(101):产生0到100范围内的整数,需要注意取不到101 # rang(1, 101):产生1到100范围内的整数 # rang(1, 101, 2):产生1到100之间的奇数,2是步长 # range(100, 0, -2):产生100到1的偶数,其中-2是步长
-
while循环
# break 提前终止循环 # continue 放弃本次循环后续的代码
-
-
chapter05 构造程序逻辑
-
chapter06 函数和模块的使用
- 函数的作用
- 定义函数
- def
- return
- 函数的参数
- 函数的参数有默认值,也支持使用可变参数。
- 用模块管理函数
- 每个文件对应一个模块。
- from * import * as *
- 变量的作用域
- 局部作用域:函数体中定义的变量
- 嵌套作用域:函数体中定义的函数体中的变量
- 全局作用域:运行体级别
- 在函数体中可以使用global关键字,指示某一个变量来自于全局作用域。
- 使用nonlocal关键字,指示变量来自于嵌套作用域。
- 内置作用域:系统内置函数
-
chapter07 字符串和常用数据结构
-
使用字符串
print(s1, s2, s3, end='') # 指示以''结尾,默认使用'\n' print('\n\t\'\\') # \n:换行,\t:制表符,\'表示',\\表示\,\141(八进制),\x61(十六进制)表示a,\u9a86(Unicode字符编码)表示骆 s1 = r'\'hello, world!\'' # 字符串前加r,可以防止字符串在使用的时候不被转义。 # 字符串前加上u,解决中文乱码问题,后面字符以Unicode格式进行编码,一般用在中文字符串前面。 # b''前缀,表示后面字符串是bytes类型。 s1 = 'hello ' + 'world!' # 字符串拼接 s1 = 'hello' * 3 # 字符串重复3次 print('ll' in s1) # in和not in判断一个字符串是否包含另一个字符串 # [] [:]运算符从字符串取出某个字符或某些字符(切片) # len(str):获取str字符串的长度。 # str.capitalize():获取字符串首字母大写的拷贝。 # str.title() 获取字符串中每个单词首字母大写的拷贝。 # str.upper() 获取字符串变大写后的拷贝 # str.find('abc') 从字符串中查找子串所在位置,查找不到时会返回-1 # str.index('abc') 从字符串中查找子串所在位置,查找不到时会引发异常。 # str.startswith('He') 检查字符串是否以指定的字符串开始 # str.endwith('!') 检查字符串是否以指定的字符串结尾 print(str.center(50, '*')) # 将字符串以指定的宽度居中并在两侧填充指定的字符 print(str.rjust(50, '-')) # 将字符串以指定的宽度靠右放置,左侧填充指定的字符 print(str.isdigit()) # 判断字符串是否由数字构成 print(str.isalpha()) # 检查字符串是否以字母构成 print(str.isalnum()) # 判断字符串是否由字母和数字构成 print(str.strip()) # 获得字符串修剪左右两侧空格之后的拷贝
a, b = 5, 10 print('%d * %d = %d' % (a, b, a * b)) print('{0} * {1} = {2}'.format(a, b, a * b)) print(f'{a} * {b} = {a * b})
-
使用列表
list1 = [1, 2, 3, 4, 5] print(list1) list2 = ['hello'] * 3 # 乘号表示列表元素的重复, list2 = ['hello', 'hello', 'hello'] print(len(list2)) # 获取列表长度(元素个数) print(list1[0]) print(list1[-1]) for index in range(len(list1)): print(list1[index]) for elem in list1: print(elem) for index, elem in enumerate(list1): print(index, elem)
list1 = [1, 2, 3, 4, 5] list1.append(6) # 添加元素 list1.insert(1, 7) # 向指定位置添加元素 list1 += [1000, 2000] # 合并两个列表 if 3 in list1: list1.remove(3) # 删除指定值元素 a = list1.pop(0) # 从指定位置删除元素 list1.clear() # 清空列表元素
s1 = [1, 2, 3, 4, 5, 6] s2 = s1[1:4] # 列表切片 s3 = s1[:] # 通过完整切片来复制列表 s4 = s1[::-1] # 通过反向切片来获得倒转后的列表的拷贝
list1 = [1, 2, 3, 4, 5] list2 = sorted(list1) # 返回列表排序后的拷贝 list3 = sorted(list1, reverse = True) # 降序排序 list4 = sorted(list1, key = len) # 指定根据字符串长度进行排序, 而不是默认的字母表顺序 list1.sort(reverse = True) # 直接在列表对象上进行排序
-
生成式和生成器
f = [x for x in range(1, 10)] f = [x + y for x in 'ABCDE' for y in '1234567'] # 生成表达式 f = [x**2 for x in range(1, 1000)] print(sys.getsizeof(f)) f = (x ** 2 for x in range(1, 1000)) # 生成器,不占用内存空间 print(sys.getsizeof(f)) # 通过yield关键字,将一个普通函数改造成生成器函数。 # yield可以按return来理解,下次调用该函数时会继续从yield处继续执行。注意next及send函数。 def fib(n): a, b = 0, 1 for _ in range(n): a, b = b , a + b yield a def main(): for val in fib(20): print(val) if __name__ == '__main__': main()
-
使用元组
- 元组中的元素是无法修改的,自动就是线程安全的。
- 元组在创建时间和占用的空间上面都优于列表。
-
使用集合
-
集合中不允许有重复元素,而且可以进行交集、并集、差集等运算。
set1 = {1, 2, 3, 3, 3, 2} print(set1) set2 = set(range(1, 10)) set3 = set((1, 2, 3, 3, 2, 1)) print(set2, set3) set4 = {num for num in range(1, 100) if num % 3 == 0 or num % 5 == 0} print(set4) set1.add(5) # 向集合中添加元素,只能添加元素 set2.update([11, 12]) # 向集合中添加元素或集合,可以是元素,也可以是集合。 set2.discard(5) # 删除集合中指定元素,元素不存在时,不会产生异常。 if 4 in set2: set2.remove(4) # 删除集合中指定元素,元素不存在时,会产生异常。 print(set)
print(set1 & set2) # 集合的交集 print(set1 | set2) # 集合的并集 print(set1 - set2) # 集合的差集 print(set1 ^ set2) # 集合的对称差集 print(set1 <= set2) # 判断子集和超集
-
-
使用字典
# 创建字典的字面量语法 scores = {'骆昊': 95, '白元芳': 78, '狄仁杰': 82} print(scores) # 创建字典的构造器语法 items1 = dict(one=1, two=2, three=3, four=4) # 通过zip函数将两个序列压成字典 items2 = dict(zip(['a', 'b', 'c'], '123')) # 生成{'a':'1', 'b':'2','c':'3'} # 创建字典的推导式语法 items3 = {num: num ** 2 for num in range(1, 10)} print(items1, items2, items3)
# 通过键可以获取字典中对应的值 print(scores['骆昊']) print(scores['狄仁杰']) # 对字典中所有键值对进行遍历 for key in scores: print(f'{key}: {scores[key]}') # f标识 # 更新字典中的元素 scores['白元芳'] = 65 scores['诸葛王朗'] = 71 scores.update(冷面=67, 方启鹤=85) print(scores) if '武则天' in scores: print(scores['武则天']) print(scores.get('武则天')) # get方法也是通过键获取对应的值但是可以设置默认值 print(scores.get('武则天', 60)) # 武则天不存在时,可返回默认值60
# 删除字典中的元素 print(scores.popitem()) print(scores.popitem()) print(scores.pop('骆昊', 100)) # 清空字典 scores.clear() print(scores)
-
-
chapter08 面向对象编程基础
-
定义类
class Student(object): # __init__是一个特殊方法用于在创建对象时进行初始化操作 # 通过这个方法我们可以为学生对象绑定name和age两个属性 def __init__(self, name, age): self.name = name self.age = age def study(self, course_name): print('%s正在学习%s.' % (self.name, course_name)) # PEP 8要求标识符的名字用全小写多个单词用下划线连接 # 但是部分程序员和公司更倾向于使用驼峰命名法(驼峰标识) def watch_movie(self): if self.age < 18: print('%s只能观看《熊出没》.' % self.name) else: print('%s正在观看岛国爱情大电影.' % self.name)
-
创建和使用对象
def main(): # 创建学生对象并指定姓名和年龄 stu1 = Student('骆昊', 38) # 给对象发study消息 stu1.study('Python程序设计') # 给对象发watch_av消息 stu1.watch_movie() stu2 = Student('王大锤', 15) stu2.study('思想品德') stu2.watch_movie() if __name__ == '__main__': main()
-
访问可见性问题
- 单下划线开头表示属性是受保护的。双下划线开头表示属性是私有的。
-
面向对象的支柱
- 封装、继承和多态。
-
-
chapter09 面向对象进阶
-
@property装饰器
-
用@property包装器来包装getter和setter方法,使得对属性的访问既安全又方便。
class Person(object): def __init__(self, name, age): self._name = name self._age = age # 访问器 - getter方法 @property def name(self): return self._name # 访问器 - getter方法 @property def age(self): return self._age # 修改器 - setter方法 @age.setter def age(self, age): self._age = age def play(self): if self._age <= 16: print('%s正在玩飞行棋.' % self._name) else: print('%s正在玩斗地主.' % self._name) def main(): person = Person('王大锤', 12) person.play() person.age = 22 person.play() # person.name = '白元芳' # AttributeError: can't set attribute if __name__ == '__main__': main()
-
-
__slots__魔法
-
限定自定义类型的对象只能绑定某些属性,可以通过在类中定义__slots__变量来进行限定
-
__slots__的限定只对当前类的对象生效,对子类并不起任何作用
class Person(object): # 限定Person对象只能绑定_name, _age和_gender属性 __slots__ = ('_name', '_age', '_gender') def __init__(self, name, age): self._name = name self._age = age @property def name(self): return self._name @property def age(self): return self._age @age.setter def age(self, age): self._age = age def play(self): if self._age <= 16: print('%s正在玩飞行棋.' % self._name) else: print('%s正在玩斗地主.' % self._name) def main(): person = Person('王大锤', 22) person.play() person._gender = '男' # AttributeError: 'Person' object has no attribute '_is_gay' # person._is_gay = True
-
-
静态方法和类方法
# 静态方法 from math import sqrt class Triangle(object): def __init__(self, a, b, c): self._a = a self._b = b self._c = c @staticmethod def is_valid(a, b, c): return a + b > c and b + c > a and a + c > b def perimeter(self): return self._a + self._b + self._c def area(self): half = self.perimeter() / 2 return sqrt(half * (half - self._a) * (half - self._b) * (half - self._c)) def main(): a, b, c = 3, 4, 5 # 静态方法和类方法都是通过给类发消息来调用的 if Triangle.is_valid(a, b, c): t = Triangle(a, b, c) print(t.perimeter()) # 也可以通过给类发消息来调用对象方法但是要传入接收消息的对象作为参数 # print(Triangle.perimeter(t)) print(t.area()) # print(Triangle.area(t)) else: print('无法构成三角形.') if __name__ == '__main__': main()
# 类方法 from time import time, localtime, sleep class Clock(object): """数字时钟""" def __init__(self, hour=0, minute=0, second=0): self._hour = hour self._minute = minute self._second = second @classmethod def now(cls): ctime = localtime(time()) return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec) def run(self): """走字""" self._second += 1 if self._second == 60: self._second = 0 self._minute += 1 if self._minute == 60: self._minute = 0 self._hour += 1 if self._hour == 24: self._hour = 0 def show(self): """显示时间""" return '%02d:%02d:%02d' % \ (self._hour, self._minute, self._second) def main(): # 通过类方法创建对象并获取系统时间 clock = Clock.now() while True: print(clock.show()) sleep(1) clock.run() if __name__ == '__main__': main()
-
类之间的关系
- is-a:继承或泛化,例如学生和人,手机和电子产品的关系。
- has-a:关联,例如部门和员工,汽车和引擎的关系。关联关系如果是整体和部分的关联,那么我们称之为聚合关系;如果整体进一步负责了部分的生命周期(整体和部分是不可分割的,同时同在也同时消亡),那么这种就是最强的关联关系,我们称之为合成关系。
- use-a:依赖。例如司机有一个驾驶的行为(方法),其中(的参数)使用到了汽车,那么司机和汽车的关系就是依赖关系。
-
继承和多态
# 继承实例 class Person(object): """人""" def __init__(self, name, age): self._name = name self._age = age @property def name(self): return self._name @property def age(self): return self._age @age.setter def age(self, age): self._age = age def play(self): print('%s正在愉快的玩耍.' % self._name) def watch_av(self): if self._age >= 18: print('%s正在观看爱情动作片.' % self._name) else: print('%s只能观看《熊出没》.' % self._name) class Student(Person): """学生""" def __init__(self, name, age, grade): super().__init__(name, age) self._grade = grade @property def grade(self): return self._grade @grade.setter def grade(self, grade): self._grade = grade def study(self, course): print('%s的%s正在学习%s.' % (self._grade, self._name, course)) class Teacher(Person): """老师""" def __init__(self, name, age, title): super().__init__(name, age) self._title = title @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(): stu = Student('王大锤', 15, '初三') stu.study('数学') stu.watch_av() t = Teacher('骆昊', 38, '砖家') t.teach('Python程序设计') t.watch_av() if __name__ == '__main__': main()
-
子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态(poly-morphism)
from abc import ABCMeta, abstractmethod # 抽象类 class Pet(object, metaclass=ABCMeta): """宠物""" def __init__(self, nickname): self._nickname = nickname @abstractmethod # 抽象方法 def make_voice(self): """发出声音""" pass class Dog(Pet): """狗""" def make_voice(self): print('%s: 汪汪汪...' % self._nickname) class Cat(Pet): """猫""" def make_voice(self): print('%s: 喵...喵...' % self._nickname) def main(): pets = [Dog('旺财'), Cat('凯蒂'), Dog('大黄')] for pet in pets: pet.make_voice() if __name__ == '__main__': main()
-
-
-
chapter10 图形用户界面和游戏开发
-
基于tkinter模块的GUI
- 开发步骤
-
导入tkinter模块中我们需要的东西。
-
创建一个顶层窗口对象并用它来承载整个GUI应用。
-
在顶层窗口对象上添加GUI组件。
-
通过代码将这些GUI组件的功能组织起来。
-
进入主事件循环(main loop)。
import tkinter import tkinter.messagebox def main(): flag = True # 修改标签上的文字 def change_label_text(): nonlocal flag flag = not flag color, msg = ('red', 'Hello, world!')\ if flag else ('blue', 'Goodbye, world!') label.config(text=msg, fg=color) # 确认退出 def confirm_to_quit(): if tkinter.messagebox.askokcancel('温馨提示', '确定要退出吗?'): top.quit() # 创建顶层窗口 top = tkinter.Tk() # 设置窗口大小 top.geometry('240x160') # 设置窗口标题 top.title('小游戏') # 创建标签对象并添加到顶层窗口 label = tkinter.Label(top, text='Hello, world!', font='Arial -32', fg='red') label.pack(expand=1) # 创建一个装按钮的容器 panel = tkinter.Frame(top) # 创建按钮对象 指定添加到哪个容器中 通过command参数绑定事件回调函数 button1 = tkinter.Button(panel, text='修改', command=change_label_text) button1.pack(side='left') button2 = tkinter.Button(panel, text='退出', command=confirm_to_quit) button2.pack(side='right') panel.pack(side='bottom') # 开启主事件循环 tkinter.mainloop() if __name__ == '__main__': main()
-
使用Pygame进行游戏开发
-
制作游戏窗口
import pygame def main(): # 初始化导入的pygame中的模块 pygame.init() # 初始化用于显示的窗口并设置窗口尺寸 screen = pygame.display.set_mode((800, 600)) # 设置当前窗口的标题 pygame.display.set_caption('大球吃小球') running = True # 开启一个事件循环处理发生的事件 while running: # 从消息队列中获取事件并对事件进行处理 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if __name__ == '__main__': main()
-
在窗口中绘图
import pygame def main(): # 初始化导入的pygame中的模块 pygame.init() # 初始化用于显示的窗口并设置窗口尺寸 screen = pygame.display.set_mode((800, 600)) # 设置当前窗口的标题 pygame.display.set_caption('大球吃小球') # 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组) screen.fill((242, 242, 242)) # 绘制一个圆(参数分别是: 屏幕, 颜色, 圆心位置, 半径, 0表示填充圆) pygame.draw.circle(screen, (255, 0, 0,), (100, 100), 30, 0) # 刷新当前窗口(渲染窗口将绘制的图像呈现出来) pygame.display.flip() running = True # 开启一个事件循环处理发生的事件 while running: # 从消息队列中获取事件并对事件进行处理 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if __name__ == '__main__': main()
-
加载图像
import pygame def main(): # 初始化导入的pygame中的模块 pygame.init() # 初始化用于显示的窗口并设置窗口尺寸 screen = pygame.display.set_mode((800, 600)) # 设置当前窗口的标题 pygame.display.set_caption('大球吃小球') # 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组) screen.fill((255, 255, 255)) # 通过指定的文件名加载图像 ball_image = pygame.image.load('./res/ball.png') # 在窗口上渲染图像 screen.blit(ball_image, (50, 50)) # 刷新当前窗口(渲染窗口将绘制的图像呈现出来) pygame.display.flip() running = True # 开启一个事件循环处理发生的事件 while running: # 从消息队列中获取事件并对事件进行处理 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if __name__ == '__main__': main()
-
实现动画效果
import pygame def main(): # 初始化导入的pygame中的模块 pygame.init() # 初始化用于显示的窗口并设置窗口尺寸 screen = pygame.display.set_mode((800, 600)) # 设置当前窗口的标题 pygame.display.set_caption('大球吃小球') # 定义变量来表示小球在屏幕上的位置 x, y = 50, 50 running = True # 开启一个事件循环处理发生的事件 while running: # 从消息队列中获取事件并对事件进行处理 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False screen.fill((255, 255, 255)) pygame.draw.circle(screen, (255, 0, 0,), (x, y), 30, 0) pygame.display.flip() # 每隔50毫秒就改变小球的位置再刷新窗口 pygame.time.delay(50) x, y = x + 5, y + 5 if __name__ == '__main__': main()
-
碰撞检测
from enum import Enum, unique from math import sqrt from random import randint import pygame @unique class Color(Enum): """颜色""" RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) BLACK = (0, 0, 0) WHITE = (255, 255, 255) GRAY = (242, 242, 242) @staticmethod def random_color(): """获得随机颜色""" r = randint(0, 255) g = randint(0, 255) b = randint(0, 255) return (r, g, b) class Ball(object): """球""" def __init__(self, x, y, radius, sx, sy, color=Color.RED): """初始化方法""" self.x = x self.y = y self.radius = radius self.sx = sx self.sy = sy self.color = color self.alive = True def move(self, screen): """移动""" self.x += self.sx self.y += self.sy if self.x - self.radius <= 0 or \ self.x + self.radius >= screen.get_width(): self.sx = -self.sx if self.y - self.radius <= 0 or \ self.y + self.radius >= screen.get_height(): self.sy = -self.sy def eat(self, other): """吃其他球""" if self.alive and other.alive and self != other: dx, dy = self.x - other.x, self.y - other.y distance = sqrt(dx ** 2 + dy ** 2) if distance < self.radius + other.radius \ and self.radius > other.radius: other.alive = False self.radius = self.radius + int(other.radius * 0.146) def draw(self, screen): """在窗口上绘制球""" pygame.draw.circle(screen, self.color, (self.x, self.y), self.radius, 0)
-
事件处理
def main(): # 定义用来装所有球的容器 balls = [] # 初始化导入的pygame中的模块 pygame.init() # 初始化用于显示的窗口并设置窗口尺寸 screen = pygame.display.set_mode((800, 600)) # 设置当前窗口的标题 pygame.display.set_caption('大球吃小球') running = True # 开启一个事件循环处理发生的事件 while running: # 从消息队列中获取事件并对事件进行处理 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # 处理鼠标事件的代码 if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: # 获得点击鼠标的位置 x, y = event.pos radius = randint(10, 100) sx, sy = randint(-10, 10), randint(-10, 10) color = Color.random_color() # 在点击鼠标的位置创建一个球(大小、速度和颜色随机) ball = Ball(x, y, radius, sx, sy, color) # 将球添加到列表容器中 balls.append(ball) screen.fill((255, 255, 255)) # 取出容器中的球 如果没被吃掉就绘制 被吃掉了就移除 for ball in balls: if ball.alive: ball.draw(screen) else: balls.remove(ball) pygame.display.flip() # 每隔50毫秒就改变球的位置再刷新窗口 pygame.time.delay(50) for ball in balls: ball.move(screen) # 检查球有没有吃到其他的球 for other in balls: ball.eat(other) if __name__ == '__main__': main()
-
-
-
chapter11