赞
踩
课程方向:
知识点主要面向小学5年级+的少儿编程Python课程,适用于各类竞赛;
课程比较适合理工科父母的亲子互动,教培机构老师备课参考;
课程规划:
特别说明:竞赛中理论部分会有大量本课程无法涉及的部分:比如进制问题(二进制、八进制等)、数据结构和算法部分(二叉树、排序、链表等)以及初等数学、离散、图论等均没有。
# 向控制台输出一行字:Hello, Python
# 注意1:括号和引号(单双均可)必须是英文状态下的
# 注意2:#号开头表示注释,它的作用是解释,并不会执行
print("Hello, Python!")
那么,如何通过编程来实现变量的声明呢?
# 声明一个变量
# 注意1:= 不是等于的意思,是赋值的意思
# 注意2:阅读代码从右边向左边阅读,意为:将数字123赋值给变量a
a = 123
# 输出a
print(a)
# a变量被替换
a = 456
print(a)
从 a=123 的例子中,a是变量名,但变量的名字有什么要求?需要注意哪些规则?能乱起吗?
变量名可以包含字母、数字、下划线,但数字不能在变量名首位;
Python中的关键字无法作为变量名,编辑器会提示,比如:def、class,使用会直接报错;
Python中的英文是区分大小写的,大写的A和小写的a不是一种东西;
为了让变量名更加的有可读性,比如:你的名字,当然,中文变量名也是支持的,但基本不用;
# 关键字错误命名
def = 123
class = 123
print(class)
# 中文命名
你的名字 = 123
print(你的名字)
# 驼峰式
yourName = 123
print(yourName)
# 蛇形式
your_name = 123
print(your_name)
有时我们要对一些结果进行快速获取,可以直接使用命令行窗口直接输出:Shell模式;
>>> a = 123
>>> a
123
>>> b = 456
>>> print(b)
456
# 如果在主程序本身就已经运行赋值了,直接在命令行输出也是可以的
>>> c
798
虽说叫做四则运算,但其实运算符往往不止加减乘除这四种:
运算 | 符号 | 格式 |
---|---|---|
加 | + | 1 + 1 |
减 | - | 2 - 1 |
乘 | * | 3 * 4 |
除 | / | 6 / 2 |
整除 | // | 9 // 7 |
求余 | % | 10 % 8 |
幂 | ** | 2**3 |
# 加减乘除,在末尾Ctrl+D复制
print(1 + 1)
print(3 - 2)
print(4 * 5)
print(9 / 7)
print(9 // 7)
print(10 % 7)
print(2 ** 3)
# 使用变量进行四则运算
a = 1 + 1
print(a)
# 累加
a+=1
print(a)
# 温度转换
c = 40
f = 9 / 5 * c + 32
print(f)
给命令行输出一段内容,可以使用 print() 函数;
说明 | 语法 |
---|---|
函数名 | print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout) |
参数 | objects --表示输出的对象。输出多个对象时,需要用 , (逗号)分隔。 |
sep – 用来间隔多个对象。 | |
end – 用来设定以什么结尾。默认值是换行符 \n,我们可以换成其他字符。 | |
file – 要写入的文件对象。 | |
返回值 | 无 |
# 简单的数值输出
print(123)
# 可以输出多个数据,默认英文逗号隔开
# 输出时,默认会以空格来隔开显示
print(123, 456, 789)
# 通过sep参数改变显示时间隔符号
# 注意,参数的值需要通过双引号包含,因为它不是数值而是字符串
print(123, 456, 789, sep="-")
# 默认情况下一个print输出后会自动换行
# 可以通过end参数改变这一特性
print(123, end="|||")
print(456)
字符 | 说明 |
---|---|
\\ | 反斜杠 |
\’ | 单引号 |
\" | 双引号 |
\n | 换行符 |
# 转义字符输出
print("\'\"\n123")
# 只使用一个print输出以下图形
***
***
***
print("***\n ***\n ***")
如下快捷键表示啥意思?
ctrl + c
ctrl + v
alt + Tab
python学的一个输出函数是啥?
变量:
1、
a = 1
a = 2
print(a)输出是什么?
2、判断以下变量哪些合法哪些不合法?
abc a123 _xyz 123a $ab *ab -cc
3、四则运算
加减乘除在计算机中怎么表示?
8 / 2 = 多少?自己用代码打印出来试一下
如下 各是输出多少?
a = 2
a = a + 2
print(a)
a += 2
print(a)
a -= 3
print(a)
4、转义 动手试一下把如下字符打印出来,
\
\\
*
'
"
5、输出:
两种方式输出:
a-bb-cc-dd
类型名 | 转换函数 | 说明及示例 |
---|---|---|
整型 | int() | 将合法的字符数值或浮点数转换成整数 |
字符串型 | str() | 将任意内容转换成字符串型 |
浮点型 | float() | 将合法的字符数值或整数转换成浮点数 |
布尔型 | bool() | 将任意内容转换成布尔型 |
为了判断一个变量或内容,可以采用**type()**函数;
说明 | 语法 |
---|---|
函数名 | type(object) |
参数 | object --表现需要获取类型的内容 |
返回值 | 返回一个<class ‘类型符号’> |
# 使用type()获取四种类型
print(type(10))
print(type(10.15))
print(type("王二狗"))
print(type(True))
print(type(False))
布尔类型只有两个值:True和False,注意首字母是大写的;
布尔类型一般用于条件表达式的判断,这在后续课程会使用;
类型转换,有一些条件:
# 类型转换
print(int("123"))
print(int(123.34))
print(float("123"))
print(bool(0))
print(bool(1))
print(type(str(123)))
字符串的连接可以使用 +号 或者 逗号 ,具体如下:
# 字符串拼接,+号紧凑,逗号松散
print("我"+"和"+"你")
print("我" + "和" + "你")
print("我","和","你")
# 变量同理
a = "我"
b = "你"
print(a + b)
格式符 | 说明 |
---|---|
%d | 格式化整数,会直接取整 |
%f | 格式化浮点数,可以设置保留的小数点 |
%s | 字符串 |
# %符的格式化处理
name = "小明"
age = 3.33
weight = 1.23456
print("我的名字叫%s,今年%d岁了,身高%.2f"%(name, age, weight))
1、在屏幕上输出如下:
#
###
#####
#######
2、只使用一行代码打印第1题
3、声明2个整型变量a, b, 让a和b 相加等于100,在屏幕上输出。
4、声明1个整型变量a, 一个字符串变量b, 让a和b相加等于100,在屏幕上输出。
5、声明2个字符串变量a, b,让a和bb加等于100,在屏幕上输出。
6、声明两个浮点型变量a,b,让a和b相加等于90,并输出。
7、声明一个浮点型变量a,一个bool型变量,让a和b相加等于90,并输出
8、动手试一下
我们知道type()函数来打印变量的类型,
想一下如下代码打印出来的是什么?
aa = 123
print(type(123))
print(type(aa))
为什么会这样?
做如下修改之后会打印什么?说明了什么?
aa = "456"
print(type(aa))
aa = 123
bb = "123"
print(type(aa))
print(type(bb))
会输出什么?为什么不相同?
如果想让用户在键盘输入内容,可以使用 input() 函数;
说明 | 语法 |
---|---|
函数名 | input([prompt]) |
参数 | prompt --表示提示输入,[]表示它是可选状态。 |
返回值 | 返回提示内容 |
# 在这里写上你的代码 :-)
# 无任何提示的输入,运行时控制台的光标闪烁
input()
# 可以将输入的内容,赋值给一个变量
# input()输入的内容,不管字面上是什么都是字符串类型
a = input()
print(a)
print(type(a))
# 有提示的输入
b = input("请输入一个数,1-9之间:")
print(b)
通过输入的两个数值进行运算,必须进行转换;
# 通过输入进行数值计算
c = int(input("请输入第一个数,1-9之间:"))
d = int(input("请输入第二个数,1-9之间:"))
print("%d+%d=%d"%(c, d, c+d))
*
***
*****
# 输出三角图形,这里的*号是字符乘法,复制显示数量
e = input("请输入任意字符:")
print(" ",e)
print("",e*3)
print(e*5)
布尔类型的值,是专门用于各种表达式的判断,表达式的运算符如下:
名称 | 关系运算符 | 表达式返回值 |
---|---|---|
大于 | > | 成立范围True(6 > 5),否则为False(6 > 7) |
小于 | < | 成立返回True(6 < 8),否则为False(6 < 5) |
等于 | == | 成立返回True(6 == 6),否则为False(6 == 7) |
大于等于 | >= | 成立返回True(7 >= 6),否则为False(7 >= 8) |
小于等于 | <= | 成立返回True(6 <= 6),否则为False(6 <= 5) |
不等于 | != | 成立返回True(6 != 5),否则为False(6 != 6) |
# 表达式返回值
print(6 > 5)
print(6 > 7)
print(6 < 7)
print(6 < 5)
print(6 == 6)
print(6 == 7)
print(6 >= 7)
print(6 <= 7)
print(6 != 7)
除了关系运算符之外,还有一种叫做逻辑运算符,具体如下:
名称 | 逻辑运算符 | 表达式返回值 |
---|---|---|
and | x and y | x和y同时为True时,返回True,否则返回False |
or | x or y | x和y只要其中之一为True,返回True,否则返回False |
not | not x | x为True时,结果为False,否则为True |
# 逻辑运算符
print(5 > 6 and 5 > 4)
print(7 > 6 and 5 > 4)
print(5 > 6 or 5 > 4)
print(5 > 6 or 5 < 4)
print(not 5 > 6)
print(not True)
假设你一周七天中只有周一才能穿新衣服,那么就需要 if语句 中 单一条件判断:
if 条件判断:
条件满足时,执行
# 注意1:判断的数值需要转换为整数再判断
# 注意2:a == 1由于习惯或方式,可以加上括号(a == 1)
# 注意3:if条件判断内的语句,需要用Tab键缩进才能识别
a = int(input("请输入今天星期几,1-7之间:"))
if a == 1:
print("今天穿新衣")
单一if语句比较高冷,如果未满足条件,ta就不理你了;而else分支则可爱许多;
if 条件判断:
条件满足时,执行
else:
条件不满足时,执行
# 注意1:else后面有冒号,表示结束
# 注意2:else需要和if在同一垂直位对齐,否则报错
if a == 1:
print("今天穿新衣")
else:
print("今天无法穿新衣")
夏天到了,汗渍很多,每日换洗:1,3,5穿A款,2,4,6穿B款,星期日放假不出门;
a = int(input("请输入今天星期几,1-6之间:"))
if a == 1 or a == 3 or a == 5:
print("穿A款")
else:
print("穿B款")
年龄决定一个人当前的状态,8岁到80岁,你都在干什么?此时需要elif多重分支:
if 条件判断:
条件满足时,执行
elif 条件判断:
条件满足时,执行
...
# 8-25之间:求学阶段
# 26-60之间:工作阶段
# 大于60:退休阶段
a= int(input("请输入你的年龄:8-80之间:"))
if a >= 8 and a <=25:
print("我在上学!")
elif a >=26 and a<=60:
print("我在工作!")
elif a > 60:
print("我在退休!")
else:
print("这个年龄,尚未被统计!")
难道大于60岁就真的可以退休了吗?真实情况显然不是这样的,我们还需要具体判断:
...
elif a > 60:
# 如果爷爷有大伯,二伯和我爸
# 且,我还有姐姐和弟弟
# 再且,大伯、二伯每家还有三个
# 为了存压岁钱,也无法退休呢!
b = int(input("请输入子孙的数量,1-9之间:"))
if b >= 7 and b <=9:
print("退休后打两份工")
elif b >= 4 and b <=6:
print("退休后打一份工")
elif b <= 3:
print("退休中!")
...
王二狗考试得了双百,就得意的要求买台switch,还保证一周只玩三小时,但妈妈让他自己存;
for 变量 in 集合:
执行语句
想要实现一个月1-30号的自增循环,那需要使用**rang()**函数;
说明 | 语法 |
---|---|
函数名 | range(start[,end,step]) |
参数 | start:计数从start开始,默认是从0开始 |
end:计数到end结束,但是不包括end | |
step:每次自增的数值,默认1 | |
返回值 | 无 |
# 注意1:for...in...语法核心
# 注意2:i是变量,随便定义,每次获取自增后的值
# 注意3:range(1,30)实际上循环到1-29
# 注意4:range第三个参数,设置2体会下
for i in range(1,30+1):
print(i, end="|")
# 如果range只传入一个参数,默认从0开始到29
for i in range(30):
print(i, end="|")
使用以上学到的循环语句,我们存一个月的钱,对自己狠一点,每天存的钱比前一天多一元;
# 存一个月的钱
t = 0
for i in range(1, 30+1):
t += i;
print("一个月存了%d元!"%(t))
过不下去啦,每天要存的金额越来越多,还是放弃吧,王二狗说道;此时,我们需要使用break终止循环;
for i in range(1, 30+1):
# 坚持到第3天,就要放弃
# 注意:如果将if放在print后面,将执行第3天
if i == 3:
break
print(i, end="|")
逃避的加锁禁锢着王二狗的内心,悟道自律才能获得自由;决定:偶数天存钱,奇数天放纵;理由:循序渐进,慢慢来;此时,我们就需要使用continue终止当前循环;
for i in range(1, 30+1):
# 先来简单的,假设第三天不存
# 注意:continue必须在执行语句前面执行,否则白搭
if i == 3:
continue
print(i, end="|")
for i in range(1, 30+1):
#判断为奇数就退出当前循环
#去自增执行下一次循环
if i % 2 == 1:
continue
print(i, end="|")
常规的 while循环 和 for循环 基本一致,只不过while更加灵活一点;
# 初始化变量1
i = 1
# 如果变量小于等于30,则执行循环体
while i <= 30:
print(i, end="|")
# 当执行完毕,自增1
i += 1
王二狗家有一头拉磨的驴,ta的主人告诉ta,只要每天一直往前走,就会有精彩的未来;此时,我们就需要使用while中的无限循环,让其无穷无尽的执行下去;
# 只要判断表达式永远为True,则不停的执行
while True:
while True:
print("驴:请问,到达路的尽头了吗?^.^")
a = input("请告诉驴,到达与否,回车或输入yes:")
if a != "yes":
print("旁白:还没到,请继续向前!")
print("驴:加油!加油!努力!奋斗!")
else:
print("旁白:已经到了!")
print("驴:真好,我累了,要睡了!❤")
break
print("-----------------------")
列表其实就是一种可以同时存放多个数据的变量,就好比如下图存放了9条数据,但只有一个变量;
101 | 102 | 103 |
201 | 202 | 203 |
301 | 302 | 303 |
# 注意1,array是列表变量名,是随便定义的
# 注意2:列表的值外围是一个中括号,里面的每个数据可以称为元素
# 注意3:每个元素,用逗号隔开,元素太多,可以换行
# 注意4:元素遵循数据类型,如果是字符串元素,要加引号
# 注意5:其它语言一般称为数组,如果我不小心说数组啥啥啥的,等同
array = [101, 102, 103,
201, 202, 203,
301, 302, 303]
# 输出列表,带上中括号原封不动的输出
print(array)
# 看看什么类型,<class 'list'>列表类型
print(type(array))
什么是下标?即:列表中元素对应的位置编号,或称为:索引,默认从0开始计算;
0 | 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 |
# 获取王二狗的家
print(array[7])
除了直接通过下标获取指定位置的元素值,还有一些其它语法:
为了避免混淆,我不把下标0说成第1个位置(我会说下标为0的元素);
array[0]:获取下标为0的位置的元素,这里获取的是101;
array[2:4]:获取下标为2到3的元素,这里获取的是[103, 201],返回一个新list;
array[2:]:获取下标为2到end的元素,这里获取的是[103…303],返回一个新list;
array[:2]:获取下标为start到1的元素,这里获取的是[101,102],返回一个新list;
array[-2]:获取倒数第2个元素,这里获取的是[302];
array[-5:-2]:获取倒数第5到倒数第3的元素,这里获取的是:[202, 203, 301],返回一个新list;
print(array[0])
print(array[2:4])
print(array[2:])
print(array[:2])
print(array[-2])
print(array[-5:-2])
列表是一种容器类的结构,势必会给予它较为丰富的操作,比如点语法的操作方法:
列表变量.操作方法()
方法名 | 说明 |
---|---|
.append(o) | 在列表末尾添加o元素 |
.insert(i, o) | 在指定位置插入o元素 |
.remove(o) | 移除匹配到o元素的第一个 |
.pop(i) | 取出列表中最后一个元素,或指定元素;然后返回该元素的值 |
.extend(s) | 在列表尾部合并另一个列表 |
通过自身语法以及点语法,我们可以对列表进行一系列的 增删改查 操作:
# 创建一个空的列表
array = []
print(type(array))
# 使用.append()方法添加元素
array.append(101)
array.append(102)
array.append(103)
print(array)
# 使用.insert()在指定下标位置插入元素
array.insert(0, 109)
print(array)
# 使用.remove()方法删除元素
# 注意:参数需填写元素的值
array.remove(102)
print(array)
# 使用.pop()方法删除元素
# 注意1:这个删除严格意义上是取出返回的意思
# 注意2:参数需填写元素的下标
print(array.pop(1))
print(array)
# 使用[]方式修改元素,传递下标位置即可
array[0] = 1001
print(array)
# 使用.extend()方法合并列表
list = [1002, 1003]
array.extend(list)
print(array)
包括获取列表元素的数量、获取匹配的下标位置、排序、复制、清空等;
方法名 | 说明 |
---|---|
.count(o) | 统计元素o在列表中出现的次数 |
.index(o) | 获取元素o在列表中第一次出现的位置 |
.reverse() | 反转列表 |
.sort(reverse=True) | 排序,默认从小到大排序,设置reverse参数为True则反之 |
.copy() | 复制列表 |
.clear() | 清空列表 |
# 根据不同演示的方法会做出修改
array = [101, 102, 103,
201, 202, 203,
301, 302, 303, 102, 102]
# .count()方法
print(array.count(102))
# .index()方法
print(array.index(102))
# .reverse()方法,反转原列表
# 注意:这个方法本身不返回反转,而是让原列表反转
array.reverse()
print(array)
# .sort()方法,默认从小到大排序原列表
# 参数reverse=True|False,从大到小和反之
array.sort()
print(array)
array.sort(reverse=True)
print(array)
# .copy()方法,将列表复制出来交给新变量
# 注意:赋值和拷贝的区别,本课不深究
list = array.copy()
#list = array
array.pop()
print(array)
print(list)
# .clear()方法,清空
list.clear()
这里推荐三个极其常用的函数,来快速获取想要的对应数据:min()、max()、len();
# len()函数,获取长度
print(len(array))
# min()函数,获取最小值
print(min(array))
# max()函数,获取最大值
print(max(array))
还有一个删除列表的快捷语句 del 和 循环列表 数据的遍历方法;
# 删除某一个元素或多个元素
del array[0]
del array[2:4]
# 删除整个列表
# 注意:这里不是清空,是直接把array变量给抹除了
del array
# 遍历列表,两种方法,1.没必要 2.不错
for i in range(len(array)):
print(array[i], end="|")
print()
for i in array:
print(i, end="|")
元祖相对于列表,有两个最主要的特性:1. 数据集用圆括号包含;2. 数据只读,无法修改删除;
# 注意1:创建时()包含,但输出还用[]
# 注意2:无法修改删除,array[0] = 1001 将报错
# 注意3:type()后得知元祖是tuple[tʌpl]类型
# 注意4:如果创建的元祖只有一条元素,需要补上逗号
array = (101, 102, 203)
print(array)
print(array[0])
print(type(array))
遍历和列表一致;
# 元祖遍历
for i in array:
print(i, end="|")
字典的核心就是:配对!即:键值对(key:value)!就是将列表中的下标索引进行自定义设计;
# 字典创建的语法,通过 花括号 以及 key:value 的方式构成:
字典变量 = {键:值, 键:值, ...}
# 创建空字典,有两种方式1. {} 2. dict()
#array = {}
array = dict()
print(type(array))
# 创建字典,键值配对
# 注意1:冒号左边称为:键(key),右边称为:值(value)
# 注意2:依然遵循数据类型规则,key或value,数字不加引号,字符加
# 注意3:通过key找value,依然用中括号,但字符串不能省略引号
array = {
"A1":"张三",
"A2":"李四",
"A3":"王二狗",
"A4":"马六"
}
print(array)
print(array["A3"])
和列表一样,字典也需要进行增删查改的操作;
# 字典新增
array["A5"] = "王五"
# 字典删除,和列表一样
#del array["A4"]
array.pop("A4")
# 字典修改
array["A1"] = "张四"
和列表一样,字典也具有**.copy()和.clear()方法以及min()**、**max()和len()**等函数,这里不再赘述;
字典也有自己独有的方法,方便更好的操作:
方法名 | 说明 |
---|---|
.get(key, default) | 返回指定key的值,如果不存在则返回default默认值 |
.keys() | 返回字典中所有的key组成的列表,可再通过遍历输出 |
.values() | 同上 |
.items() | 返回字典中所有的(key,value)组成的元祖,再通过遍历输出 |
# 获取指定key的value,如果不在,返回指定值
print(array.get("A3"))
print(array.get("A9", "不存在"))
# 通过.keys()返回所有key
for i in array.keys():
print(i, end="|")
print()
# 通过.values()返回所有values
for i in array.values():
print(i, end="|")
print()
# 通过.items()返回所有(key,value)
for i in array.items():
print(i, end="|")
什么是一维?就是普通列表,一行数据;什么是二维?就是多行数据,表格式数据;
# 初始化区
s = {}
编号 | 姓名 | 性别 | 年龄 |
---|---|---|---|
A1 | 张三 | 男 | 12 |
A2 | 李四 | 女 | 11 |
A3 | 王二狗 | 男 | 12 |
# s是字典
# 注意1:整个学籍卡用字典来表示,这样直接可以通过key快速查找
# 注意2:但是value不是普通的数据,它是一个列表,是一串数据
# 注意3:对于字典里的value,本身可以通过s["A3"]访问,但得到是list类型
# 注意4:对于list列表类型,再通过[]号获取:s["A3"][0]得到"王二狗"
# 注意5:两个中括号,可以理解为嵌套list,或list里的list,这就是二维
s = {
"A1":["张三", "男", 12],
"A2":["李四", "女", 11],
"A3":["王二狗", "男", 12],
}
对于一款小软件,只有在用户主动关闭才能退出,我们通过死循环来实现;
# 死循环
while True:
# 选项开启
n = int(input("请输入要操作的选项:\n1.查看学籍 2.添加学籍 3.修改学籍 4.删除学籍\n请选择,1-4之间:"))
# 判断选项
if n == 1:
print("show")
elif n == 2:
print("add")
elif n == 3:
print("update")
elif n == 4:
print("delete")
else:
print("error")
# 标头
print()
print("%-3s %-7s %-5s %-5s"%("编号", "姓名", "性别", "年龄"))
print("------------------------")
# 遍历学籍卡
for i in s.items():
print("%-4s %-8s %-5s %-5s"%(i[0], i[1][0], i[1][1], i[1][2]))
print("------------------------")
print()
通过input()录入来写入数据到字典中,key是编号,而value是列表;
# 信息录入
a = input("请输入编号:")
b = input("请输入姓名:")
c = input("请输入性别:")
d = input("请输入年龄:")
# 写入s
s[a] = [b,c,d]
#空一行
print()
查询数据,通过input()获取编号后,录入修改的内容,再更新;
# 查询并修改
f = input("请输入编号:")
if s.get(f, "no") != "no":
b = input("请输入姓名:")
c = input("请输入性别:")
d = input("请输入年龄:")
s[f] = [b, c, d]
else:
print("编号有误!")
#空一行
print()
查询数据,通过input()获取编号后,直接del即可;
# 查询并删除
f = input("请输入编号:")
if s.get(f, "no") != "no":
del s[f]
else:
print("编号有误!")
#空一行
print()
字符串本身有一些功能,有些之前运用过,这里总结如下:
# 功能一:判断字符串类型
print(type("Hello"))
print(str(123)) # 转换
# 功能二:连接字符段片段
a = "hello"
b = "python!"
print(a + b) # 没有空格
print(a, b) # 包含一个空格
# 功能三:重复字符
c = "^.^ "
print(c * 5)
如果把字符串每个字符当成列表的元素,将会有很多处理方案:
# 将字符串理解为列表
# 注意:但是列表中方法和工具不一定都能用
d = "abcdefghijklmn"
# 输入b,那么下标位置为1
print(d)
print(d[1])
print(d[2:8])
# 第三个冒号是step步长
print(d[2:8:2])
# 可以用工具函数
print(len(d))
# 字符串也可以像列表一样遍历
for i in d:
print(i, end="|")
之前已经学习过%d、%f、%s等格式化输出的方式,再看一些变种:
# 格式化输出
#t = "hello"
#s = t + "python"
t = "hello%s"
s = t%"python"
print(s)
x = "我叫%s,今年%d岁,身高%.2f米"
y = x%("王二狗",10,1.45)
print(y)
字符串有一些用于判断数据的工具函数:成立返回True,失败返回False
方法名 | 返回值说明 |
---|---|
.isnumeric()、.isdigit() | 判断字符串是否只包含了数字 |
.isalpha() | 判断字符串是否只包含了字母 |
# 判断是否只包含数字
a = "123"
b = "123abc"
print(a.isdigit())
print(b.isdigit())
# 判断是否只包含字母
c = "abc"
d = "abc123"
print(c.isalpha())
print(d.isalpha())
字符串有一些用于转换数据的工具函数:直接返回转换后的数据
方法名 | 返回值说明 |
---|---|
.lower() | 将英文的字符串全部转换为小写 |
.upper() | 同上,大写 |
.format() | 格式化 |
# 大小写转换,格式化
print("abCdeFghiJklmn".upper())
print("abCdeFghiJklmn".lower())
print("123{}45{}6".format("x","y"))
print("123{1}45{0}6".format("x","y"))
字符串有一些用于查询处理数据的工具函数:返回新的字符串
方法名 | 返回值说明 |
---|---|
.find(s[, start, end]) | 判断是否包含子字符串,返回下标索引,否则返回-1 |
start:开始下标索引位置,默认0,end:结束下标索引位置,默认为字符串长度 | |
.replace(s1, s2[,max]) | 将字符串中的s1替换成s2后生成新的字符串 |
s1:将要被替换的字符串 s2:新字符串 max:替换次数 | |
.split(s, n) | 将字符串切割后形成一个字符串列表 |
s:分隔符 n:切割次数 默认值:-1,即切割所有 |
# 查询、替换、切割
print("abCdeFghiJklmn".find("d"))
print("abCdeFghiJklmn".find("d", 6,10))
print("1abCd1eFgh1iJk1lmn".replace("1", "2"))
print("1abCd1eFgh1iJk1lmn".replace("1", "2", 2))
print("1abCd1eFgh1iJk1lmn".split("1"))
print("1abCd1eFgh1iJk1lmn".split("1", 2))
Python有大量的功能需要借助丰富的库来实现,随机库 random 是其中一种:
# 引入随机库
import random
# 随机1-100之间
print(random.randint(1,100))
# 设置库的别名
import random as r
print(r.randint(1, 100))
除了上面的 .randint() 整数随机,还有其它的一系列随机数:
方法名 | 返回值说明 |
---|---|
.randint(s, e) | 返回s~e之间的一个随机整数 |
.uniform(s, e) | 返回s~e之间的一个随机小数 |
.randrange(s, e, p) | 同第一条,p是步长 |
.choice(s) | 从元祖中随机获取一个元素 |
.shuffle(s) | 打乱原列表 |
.sample(s, n) | 随机从s列表中取出n个元素组成新列表 |
# 随机小数
print(r.uniform(1, 10))
# 随机规律整数
# 随机奇数,偶数
print(r.randrange(1, 10, 2))
print(r.randrange(2, 11, 2))
# 从元祖数据中随机产生一个
print(r.choice(("ScratchJR", "Scratch", "Python", "C++")))
# 打乱原列表
array = ["a", "b", "c", "d", "e"]
r.shuffle(array)
print(array)
# 随机取出元素组成新列表
list = [1, 2, 3, 4, 5]
print(r.sample(list, 3))
turtle,即:海龟;和随机库一样,是Python中一种 绘图工具 库,也叫 海龟库:
# 引入海龟库
import turtle as t
# 画一笔,向前(默认右)画100步(单位:像素)
t.forward(100)
方法名 | 返回值说明 |
---|---|
.forward(d) | 面朝当前方向前进d个距离,d单位是像素 |
.back(d) | 同上,后退 |
# 暂停画笔绘制,不会关闭窗口,等待用户交互(比如关闭窗口)
# 注意1:在某些其它Python开发工具,没有.done()会自动关闭窗口
# 注意2:而.done()方法放在绘图代码结尾,保证窗口悬停
# 注意3:既然.done()是暂停的意思,后面再绘图便无效
# 注意4:本开发工具Mu Editor不会自动关闭,学习时不必每次调用
t.done()
在绘制图形时,有时需要转向,那么就需要调整前进箭头的指向(角度)即可
方法名 | 方法说明 |
---|---|
.left(a) | 设置当前角度左转a度,a的取值0-360 |
.right(d) | 同上,右转 |
# 拐个弯,向左拐90度
t.left(90)
# 再向前100步
t.forward(100)
# 拐个弯,向右拐90度
t.right(90)
# 再向前100步,或后退
#t.forward(100)
t.back(100)
为什么叫小海龟呢?因为箭头是可以设置为小海龟的,当然,默认是箭头
方法名 | 方法说明 |
---|---|
.shape() | 设置箭头的造型:arrow、turtle、circle、square、triangle、classic |
.hideturtle() | 设置绘图结束后,隐藏箭头 |
.showturtle() | 同上,相反 |
# 设置箭头造型
t.shape("turtle")
# 隐藏海龟
t.hideturtle()
通过计算总度数(360)除以要绘制的边数,就可以得到正方形和三角形的绘制角度
# 绘制正方形
# 注意1:forward可以简写fd,back=>bk
# 注意2:right可以简写rt,left=>lt
# 注意3:推荐初学者用完全单词,不然都不知道啥意思
for i in range(4):
t.forward(200)
t.right(90)
# 绘制三角形
for i in range(3):
t.forward(200)
t.left(120)
我们需要通过计算多边形的角度来获取要拐弯的角度,具体如下:
方法名 | 方法说明 |
---|---|
.numinput(t, p) | 弹窗输入框,t为标题文本,p为描述信息 |
# 获取多边形的边
n = t.numinput("OK", "请输入多边形的边数:")
# 绘制多边形
for i in range(int(n)):
t.forward(200)
t.right(360 / n)
圆的绘制,有自己单独的方法:.circle()
方法名 | 方法说明 |
---|---|
.circle(r[, extent=None, steps=None]) | 绘制一个圆,r是半径,可负数 |
e可选,弧形的角度 | |
s可选,多边形边数 |
# 绘制圆
t.circle(150)
t.circle(-150)
# 半圆
t.circle(150, 180)
# 多边形
t.circle(150, 180, 7)
t.circle(150, 360, 7)
t.circle(150, steps=7)
海龟库绘制时的线条是可以设置的:包括颜色、粗细以及绘制速度等
方法名 | 方法说明 |
---|---|
.speed(s) | 设置绘图的速度:0或大于10表示瞬间绘制,1~10之间,1最慢,10最快 |
.color(p[,f]) | 设置所有颜色,包括笔头和绘制的线条,以及填充 |
.pencolor© | 设置画笔颜色,绘制的线条以及笔头的轮廓部分 |
.pensize(s) | 设置画笔粗细,填入数字,最小值1 |
# 设置为海龟
t.shape("turtle")
# 设置颜色,只有一个参数,则设置所有,如有第二参数,为填充
t.color("blue", "green")
# 设置画笔颜色,箭头只会轮廓被覆盖
t.pencolor("red")
# 设置画笔粗细
t.pensize(5)
# 设置绘制速度
t.speed(0)
红 | 黑 | 白 | 黄 |
---|---|---|---|
red | black | white | yellow |
绿 | 粉 | 橙 | 紫 |
green | pink | orange | purple |
如何在绘制好的封闭区域进行填充呢?比如一个圆
方法名 | 方法说明 |
---|---|
.fillcolor© | 设置填充的颜色 |
.begin_fill() | 在需要填充的封闭区域前设置 |
.end_fill() | 在需要填充的封闭区域后设置 |
# 绘制一个圆
# 默认会填充会依附于t.color()
# 单独设置使用t.fillcolor()
t.fillcolor("orange")
t.begin_fill() # 开始填充
t.circle(100)
t.end_fill() # 结束填充
绘图部分都设置完毕了,那么运行的窗体、背景啥的能修改吗?
方法名 | 方法说明 |
---|---|
.setup(w, h) | 设置窗体的大小 |
.title(s) | 设置窗体的标题 |
.Screen().bgcolor© | 设置屏幕的背景颜色 |
.bgcolor© | 同上 |
# 设置窗体大小
t.setup(800, 600)
# 设置窗体标题
t.title("品味穿搭")
# 获取屏幕设置变量
s = t.Screen()
# 背景颜色
s.bgcolor("pink")
默认情况下,海龟绘图在屏幕中间开始。我们可以设置对应坐标让其在指定位置绘制
方法名 | 说明 |
---|---|
.goto(x, y) | 设置海龟箭头的位置,默认0, 0 |
.setx(n) | 设置海龟箭头的x位置 |
.sety(n) | 设置海龟箭头的y位置 |
.home() | 回到初始位置,并设置初始方向 |
# 将坐标定位至x:0,y:0
t.goto(0,0)
t.circle(200)
# 将坐标y轴上移100位置
t.goto(0, 100) # 或t.sety(100)
t.circle(100)
# 按照中心点绘制圆
n = t.numinput("同心圆", "请输入外围圆的半径:")
t.goto(0, 0 - n)
t.circle(n)
t.goto(0, 0 - n / 2)
t.circle(n / 2)
每次当笔头要位移绘制时,我们需要将笔头抬起,然后再绘制处再落笔即可
方法名 | 说明 |
---|---|
.penup() | 设置画笔抬起,此时无法绘制内容,简写为:.up() |
.pendown() | 设置画笔落下,此时可以绘制内容,简写为:.down() |
# 起始先抬笔
t.penup()
# 绘制时落笔
t.pendown()
想设计一个x轴和y轴的坐标图形,先利用已有的知识绘制出来
# x轴
t.penup()
t.goto(-50,0)
t.pendown()
t.forward(250)
# y轴
t.penup()
t.goto(0, -50)
t.left(90)
t.pendown()
t.forward(250)
方法名 | 说明 |
---|---|
.seth(a) | 设置海龟箭头方向, |
右(0)、上(90)、左(180)、下(-90, 270) | |
.stamp() | 将箭头标记驻留在绘制结尾 |
# y轴
t.penup()
t.goto(0, -50)
t.seth(90)
t.pendown()
t.forward(250)
t.stamp()
在坐标(0, 0)位置设置一个中心点,并在点写上文字
方法名 | 说明 |
---|---|
.dot(s[, c]) | 绘制一个点,s为大小,c可选颜色 |
.write(s[, move, align, font]) | 写入文字,s是文字,move是true或false,设置画笔初始位置 |
align是方向:left(左)、right(右)、center(中) | |
font是字体:“宋体”, 20, “bold”,字体是本机的字体,20是字体大小 | |
bold是加粗,另外选项:noraml(正常)、italic(倾斜) |
# x轴
t.penup()
t.goto(-50,0)
t.pendown()
t.forward(250)
t.stamp()
t.write("x", align="left", font=("宋体", 12, "bold"))
# y轴
t.penup()
t.goto(0, -50)
t.seth(90)
t.pendown()
t.forward(250)
t.stamp()
t.write("y", align="right", font=("宋体", 12, "bold"))
# 中心点
t.goto(0, 0)
t.dot(10)
t.write("(0,0)", align="left", font=("宋体", 12, "bold"))
# 隐藏箭头
t.hideturtle()
我们这里所说的函数有两个意思:系统内置函数和自定义函数
# 引入海龟库
import turtle as t
# 加速
t.speed(10)
# 抬笔
t.penup()
# 去左上角
t.goto(-150, 150)
# 落笔
t.pendown()
# 画圆
t.circle(100)
# 抬笔
t.penup()
# 去右上角
t.goto(150, 150)
# 落笔
t.pendown()
# 画圆
t.circle(100)
# 抬笔
t.penup()
# 去左下角
t.goto(-150, -150)
# 落笔
t.pendown()
# 画圆
t.circle(100)
# 抬笔
t.penup()
# 去右下角
t.goto(150, -150)
# 落笔
t.pendown()
# 画圆
t.circle(100)
函数的括号部分是用于传递参数的,如果留空那就是无参数的函数
# 创建一个函数,关键字def开头
# 注意1:和if语句一样,创建函数结尾加上冒号
# 注意2:和if语句一样,在函数体内必须有Tab键间隔
def hello():
print("我是函数!")
# 调用多次函数
hello()
hello()
hello()
函数的括号部分是用于传递参数的,如果留空那就是无参数的函数
# 函数的参数,本质上就是变量
def info(name, age):
print("我的名字叫:%s, 年龄:%d"%(name, age))
# 调用传递不同参数
info("张三", 12)
info("李四", 11)
info("王二狗", 12)
# 函数,解决了后期升级和可读性问题
def dc(x, y):
# 抬笔
t.penup()
# 去左上角
t.goto(x, y)
# 落笔
t.pendown()
# 画圆
t.circle(100)
# 左上
dc(-150, 150)
# 右上
dc(150, 150)
# 左下
dc(-150, -150)
# 右下
dc(150, -150)
除了无参和固定参数外,还有带默认值的参数以及不确定个数的参数
# 带默认值的参数
# 注意1:不带默认值的参数是必须传递的,否则报错
# 注意2:带默认值的,如果传递了则覆盖默认值,反之则启用默认值
def info(id, name, gender="未知"):
print(id, name, gender)
# 调用
#info(1) # 报错
# 启用默认值
info(1, "王二狗")
# 覆盖默认值
info(1, "王二狗", "男")
什么叫做不确定参数?传递参数的个数不确定,有多有少,从而设计的传参方式
# 不固定的传参
# 需求说明:给同时进入大厅的客户发表问候
# 例如:1.张三,欢迎光临!2. 张三,李四,王二狗,欢迎光临!
# 注意1:传递的参数名和普通参数一样,自定义,args单词为多组参数的意思
# 注意2:参数左边有一个 * 号,表示我是不固定个数的传参
# 注意3:不管传递了多少个参数,都将形成一个 turple(元祖)类型,可遍历
def hello(*args):
for i in args:
print(i, end=",")
print("欢迎光临!")
hello()
hello("张三")
hello("张三", "李四", "王二狗")
def hello(info, *args):
for i in args:
print(i, end=",")
print(info)
hello("恭喜发财", "张三", "李四", "王二狗")
# **args模式,特别适合key:value形式的数据传递
# 注意1:这个参数会返回一个 dict 字典数据
# 注意2:调用的时候,通过赋值传递即可
def student(**args):
#print(type(args))
for i in args.items():
print(i)
student(id="A1", name="张三", age=11)
student(id="A2", name="李四", age=10)
student(id="A3", name="王二狗", age=12)
之前我们自定义的函数都是无返回值的函数,即:调用函数后,直接执行所有代码
# 无返回值函数
# 注意1:无返回值函数权限太高,自行执行需求,包括格式方法等
# 注意2:调用方只能调用和传参,没有任何其它权限
def hello(a, b):
print("%dx%d=%d"%(a,b,a*b))
hello(10,20)
hello(30,50)
通过函数计算得到的结果后,不用去处理它的流程和显示格式,返回给调用方处理
# 有返回值函数
# 注意1:通过return关键字将结果返回出来
# 注意2:由于函数是返回结果,直接调用是无任何输出的
# 注意3:可以把有返回值的函数当前变量处理,输出或判断等
def info(a, b):
return a * b
print(info(10, 20))
print("%dx%d=%d"%(10,20,info(10,20)))
# 对函数返回值进行判断
if info(10,20) > 150:
print("结果正确!")
有没有考虑过一个问题:函数体内声明的变量会不会被外部干涉?
# 这里的num 叫全局变量
num = 100
# 在函数体内声明变量
def hello(x,y):
# 这里的num 叫局部变量
num = 10
return x + y + num
# 在这里的返回值中,参与运算的是局部变量num
print(hello(10, 20))
# 注意:这里的num一定是全局 num,局部num出了函数体就看不见了
print(num)
全局变量除了在函数体外直接定义,也可以在函数体内声明
# 全局变量解析
def info():
# 在函数体内创建一个全局变量
global x
x = 10
y = 20
# 在未调用时,x无法访问
#print(x)
# 在调用时,x可以访问,y是局部变量无法访问
info()
print(x)
#print(y)
归纳以下几点:
利用全局变量的特性,实现一个调用关系的小例子:
# 调用关系
def your():
print(name, age)
def my():
global name
name = "王二狗"
age = 12
# 外部初始化全局变量name和age
name = "张三"
age = 11
# 首先,调用your(),直接被全局变量接管
your()
# 其次,调用my(),会激活全局变量name和局部变量age
# 此时,name被新的全局变量覆盖,而age只是局部,无法接管另一个函数的同名变量
my()
your()
函数太多怎么办?将函数独立里成文件用库的方式import导入,实现模块化
# 加法函数,addition.py
def sum(x, y):
return x + y
# 模块其实就是引入库,比如import turtle
# 本节课主要是学会如何自己创建可以import的库
# 将函数存放到单独文件中,通过import调用
# import 导入同文件夹下的.py文件名
import addition as add
print(add.sum(10, 20))
引入模块库时,可以使用from…import可将指定方法导入模块中
# from...import只是将库中某一个或几个方法引入近来
# 多个方法,用逗号个开 circle,fd,bk
from turtle import circle
# 如果想将所有的turtle引入近来,直接import *
from turtle import *
print(add.sum(10, 20))
# 无法执行
#turtle.forward(100)
# 直接使用方法,当成函数语法使用
circle(100)
fd(100)
什么是递归,即:重复的执行自身函数,从而解决某些问题
需求分析:阶乘问题
思路分析:从后向前乘
# 阶乘递归函数
def F(n):
# 当n为1时,就需要退出递归不再调用
if n <= 1:
# return 除了返回还有类似break退出的作用
return 1
#print(123)
else:
# 5 * F(5-1)
# 5 * 4 * F(4-1)
# 5 * 4 * 3 * F(2-1)
# 5 * 4 * 3 * 2 * 1
return n * F(n - 1)
print(fn(5))
提升一点难度,尝试用递归来算出第20位的经典数列:斐波那契数列
# 斐波那契数列
def F(n):
# 前两项固定为1
if n == 1 or n == 2:
return 1
# 套用递归
# 如果n=3,F(2) + F(1) = 2
# 如果n=5, F(4) + F(3) = 3 + 2 = 5
# 如果n=8,F(7) + F(6) = 5 + 3 + 5 + 5 + 2 + 1 = 21
return F(n-1) + F(n-2)
print(F(20))
头疼的数学计算,提供了不少快捷的函数方便我们直接使用
函数名 | 返回值说明 |
---|---|
abs(x) | 返回x的绝对值 |
round(x[, n]) | 返回x四舍五入的值,n可选,保留小数的位数 |
# 绝对值,不管正负,都取正
print(abs(-5))
print(abs(5))
# 四舍五入,遇5进位
print(round(3.55))
print(round(3.55, 1))
print(round(3.44))
print(round(3.44, 1))
除了上述直接作用的函数外,math库也提供了更多的数学方法和属性
方法名 | 返回值说明 |
---|---|
.ceil(x) | 返回x向上取整的值 |
.floor(x[, n]) | 返回x向下取整的值 |
.fsum(list) | 返回list中所有元素的和 |
属性名 | 返回值说明 |
---|---|
.pi | 返回圆周率 |
.e | 返回自然常数 |
# 对小数向上取整,进位取整
print(m.ceil(2.55))
print(m.ceil(2.44))
# 对小数向下取整,截断取整
print(m.floor(2.55))
print(m.floor(2.44))
# 获取列表中所有元素的和
print(m.fsum([1, 2, 3, 4, 5]))
# 获取pi,圆周率的值
print(m.pi)
# 获取e,自然常数,无限不循环小数
print(m.e)
利用随机、海龟图、函数等知识点,绘制一张包含很多个五角星的星空
# 引入库
import turtle as t
import random as r
# 绘制速度
t.speed(0)
# 设置窗体大小
t.setup(800, 600)
# 晚间天空SlateBlue4
t.bgcolor("SlateBlue4")
# 五角星函数
def drawStar(x, y, color, size, angle):
t.penup()
t.goto(x,y)
t.pendown()
# 设置颜色
t.color(color)
# 设置角度
t.left(angle)
# 五角星绘制
t.begin_fill()
for i in range(5):
t.forward(size)
t.right(144)
t.end_fill()
# 循环100次
for i in range(100):
# 随机坐标
x = r.randint(-400, 400)
y = r.randint(-300, 300)
# 随机颜色
color = r.choice(["red", "blue", "pink", "white", "green", "orange", "maroon"])
# 随机大小
size = r.randint(10, 30)
# 随机角度
angle = r.randint(0, 360)
# 调用五角星函数
drawStar(x, y, color, size, angle)
# 绘制完毕
t.done()
t.hideturtle()
36课语法基础已经结束了!下面就谈一谈教培老师和亲子家长如何规划学习
路线规划一(一般小学生):
路线规划二(优质小学生):
路线规划三(优质中学生):
Tkinter是一款Python内置的GUI软件界面开发库,用这个库可以做软件
学习这款库,有以下注意点:
tkinter库旗下的方法:
方法名 | 说明 |
---|---|
.Tk() | 生成窗体的方法,返回值是一个对象(点出万物的变量),设置当前窗体 |
.Label() | 生成一个文字标签,返回值同上,设置当前文本 |
.mainloop() | 循环窗体,不断刷新窗体内容 |
.Tk()方法下的方法:
方法名 | 说明 |
---|---|
.geometry() | 窗体的大小,长高坐标,具体传参看后续代码 |
.title() | 窗体的标题,参数即标题名称 |
.Label()方法下的方法:
方法名 | 说明 |
---|---|
.pack() | 将文本内容定位到指定的窗体上,细节看后续代码 |
通过以上的知识点,完成一个包含文本的窗体
# 引入GUI库 tkinter
import tkinter as tk
# 库下的.Tk()方法,称为窗体组件,可以生成一个窗口
# 注意1:Tk中的T是大写,区分大小写
# 注意2:方法返回一个可以点出万物的变量(是对象,还没学这概念)
# 注意3:可以通过print(type(t))来查看类型
t = tk.Tk()
# 设置窗体大小,800x600是长和高,[400是x轴,200是y轴]
t.geometry("800x600")
#t.geometry("800x600+400+200")
# 设置窗体标题
t.title("tkinter 初步")
# 引入一个Label()文字组件
# 注意1:Label(t[,option])方法组件区分大小写
# 注意2:参数t是必须,text是文字内容
lab1 = tk.Label(t, text="我的第一个tk程序!")
# 入驻窗体
lab1.pack()
# 循环,让窗体内交互内容不断刷新
# 但是,由于我们的编辑器自带了轮询,所以不加也在刷新
# 可是,如果脱离编辑器环境,就变成静态的死窗口了
# 结论,还是加上去
tk.mainloop()
按钮**.Button()组件方法和单行文本框.Entry()**组件方法的使用
方法名 | 说明 |
---|---|
.Button() | 生成一个按钮,参数看后续代码 |
.Entry() | 生成一个单行文本框,参数看后续代码 |
.Entry()旗下的方法:
方法名 | 说明 |
---|---|
.get() | 可以获取单行文本框的值 |
.delete() | 可以删除单行文本框的值,清空直接范围:0-“end” |
.Label()旗下的方法:
方法名 | 说明 |
---|---|
.config() | 可以修改文本内的值 |
通过以上的知识点,构建一个按钮和输入框,并实现交互
# 创建一个文本框
# 注意1:.Entry()组件方法,区分大小写
ent1 = tk.Entry(t, font=("宋体", 20))
ent1.pack()
# 自定义函数
def fn():
#print("感谢点击!")
# 获取文本框的值
res = ent1.get()
# 改变文本标签的值
lab1.config(text=res)
# 清空文本框
# 0表示第一个字符,"end"表示到最后一个字符
ent1.delete(0, "end")
# 创建一个按钮
# 注意1:.Button()组件方法,区分大小写
# 注意2:command是交互属性,可以调用自定义函数
but1 = tk.Button(t, text="确认", command=fn)
but1.pack()
可以通过以往的只是了判断输入框的数据是否符合要求
# 判断res是否为空,当然可以判断各种其它验证
if res == "":
print("数据不可以为空!")
else:
lab1.config(text=res)
ent1.delete(0, "end")
弹窗组件是一个需要引入的独立库,通过这个组件可以实现弹窗效果
方法名 | 说明 |
---|---|
.showinfo() | 提示框的类型设定为:普通提示 |
.showwarning() | 提示框的类型设定为:警告提示 |
.showinfo()和showwarning()方法旗下的属性:
方法名 | 说明 |
---|---|
title | 提示的标题 |
message | 提示内容的详情文本 |
# 引入信息提示框
import tkinter.messagebox as tmb
# 判断res是否为空,当然可以判断各种其它验证
if res == "":
#print("数据不可以为空!")
# 提示组件有集中类别:showinfo(普通消息)、showwarning(警告消息)等...
tmb.showwarning(title="警告信息", message="输入框不可以为空!")
# 让输入框获得焦点
ent1.focus()
else:
lab1.config(text=res)
ent1.delete(0, "end")
绘图组件:Canvas()提供了一些简单的绘图功能
方法名 | 说明 |
---|---|
.Canvas() | 在窗体上绘制图形,可以设置bg、width和height |
.Canvas()方法旗下的方法:
方法名 | 说明 |
---|---|
.create_oval(x1,y1,x2,y2[,options]) | 创建一个圆的图形,前四个参数为左上角和右下角坐标位置 |
.move(oval, moveX, moveY) | 将绘图区的一个图形,移动相应坐标的数值 |
# 载入绘图区域
cv = tk.Canvas(t, bg="lightblue", width="800", height="300")
# 绘制一个橙红太阳
oval = cv.create_oval(450, 150, 350, 50, fill="orange")
cv.pack()
.Tk()方法旗下的方法:
方法名 | 说明 |
---|---|
.resizeable(x,y) | 设置窗体的x和y是否允许拖动,都设置False,即无法最大化 |
# 移动太阳
cv.move(oval, 0, 100)
# 无法调整大小,x和y轴
t.resizable(False, False)
软件有一个重要的功能,就是菜单系统:Menu()组件可以实现
tkinter库旗下的方法:
方法名 | 说明 |
---|---|
.Menu() | 创建一个菜单组 |
# 创建第一个菜单容器,用于存放具体的菜单组
one = tk.Menu(t)
# 再创建一个菜单组,内嵌到one菜单容器里
# 注意1:第一参数,内嵌到哪个菜单容器
# 注意2:tearoff只有两个值1和0,1表示可独立分离,0不可以
file = tk.Menu(one, tearoff=0)
.Menu()旗下的方法:
方法名 | 说明 |
---|---|
.add_cascade() | 在指定的菜单组中添加一个菜单项 |
.add_separator() | 创建一条水平线 |
# 在one这个菜单容器中添加一个"文件"菜单项,设置它隶属于file菜单组
one.add_cascade(label="文件", menu=file)
file.add_command(label="新建")
file.add_command(label="打开")
# 水平分割线
file.add_separator()
file.add_command(label="保存")
# cmmand执行执行函数
file.add_command(label="关闭", command=close)
.Tk()旗下的方法:
方法名 | 说明 |
---|---|
.destroy() | 关闭窗口 |
.config() | 将组件展现 |
# 将菜单容器one展现出来
t.config(menu=one)
# 关闭
def close():
t.destroy()
对Tkinter库的一些说明
Pygame库是一款专门用于游戏开发的库,用这个库可以做游戏
pygame库旗下的方法:
方法名 | 说明 |
---|---|
.init() | 初始化pygame模块及检查系统 |
.display | 属性,控制窗口和屏幕的模块 |
.display属性旗下的方法:
方法名 | 说明 |
---|---|
.set_mode() | 设置窗体的大小,传递元祖参数,返回Surface模块 |
.set_caption() | 属性,控制窗口和屏幕的模块 |
.flip() | 刷新屏幕 |
.update() | 刷新屏幕部分内容,在不传参时:同上 |
Surface模块旗下的方法:
方法名 | 说明 |
---|---|
.fill() | 设置背景颜色 |
窗口显示、背景色、标题等设置
# 引入库pygame,并设置别名pg
import pygame as pg
# 初始化
# 注意1:pgame库旗下的方法init()
# 注意2:它的作用是导入pygame各个模块以及检查系统等
pg.init()
# .display属性:控制窗口和屏幕的模块
# .display旗下set_mode()方法,
# 注意1:传递的参数是一个元祖数据,(长, 高)
# 注意2:赋值给screen,这个变量就可以控制窗体和屏幕
# .display旗下set_caption()方法,设置标题
screen = pg.display.set_mode((800, 600))
pg.display.set_caption("Pygame游戏")
# 背景色
bgcolor = "pink"
# 轮询
while True:
# screen旗下的fill()方法,设置背景色
screen.fill(bgcolor)
# pg.display旗下的flip()方法,刷新屏幕
pg.display.flip()
初始化init()加载所需的各种模块,相对应的卸载就是quit()方法
# 卸载模块
pg.quit()
事件:即需要通过触发才能执行的程序,比如鼠标点击、键盘按键等触发操作
pygame库旗下的属性(模块):
模块名 | 说明 |
---|---|
.event | 处理事件和事件列队的模块 |
.event事件模块下的方法:
方法名 | 说明 |
---|---|
.get() | 从事件列队里获取事件 |
.event.get()方法遍历返回值下的属性:
方法名 | 说明 |
---|---|
.type | 获取事件对应的值 |
# 遍历事件
for e in pg.event.get():
# 获取事件对应的值
print(e.type)
# 遍历事件
for e in pg.event.get():
# 如果检测到事件值为256(即点击了关闭按钮)
if e.type == 256:
# 卸载pygame
pg.quit()
# pg.QUIT系统常量,直接返回256
if e.type == pg.QUIT:
isOpen = True
# 轮询
while isOpen:
screen.fill(bgcolor)
pg.display.flip()
# 遍历事件
for e in pg.event.get():
# 如果检测到事件值为256(即点击了关闭按钮)
# pg.QUIT系统常量,直接返回256
if e.type == pg.QUIT:
isOpen = False
# 卸载pygame
pg.quit()
pygame也自带了各种绘图的方法,我们这里学习一下绘制一个圆以及矩形
pygame库旗下的属性(模块):
模块名 | 说明 |
---|---|
.draw | 绘图模块 |
.time | 用于管理实践的模块 |
.draw模块下的方法:
方法名 | 说明 |
---|---|
.rect() | 绘制一个矩形,参数参考代码 |
.circle() | 绘制一个圆,参数参考代码 |
.time模块下的方法:
方法名 | 说明 |
---|---|
.Clock() | 可以返回一个追踪时间的变量(对象) |
.Clock()方法下的方法:
方法名 | 说明 |
---|---|
.tick() | 设置刷新频率 |
绘制一个静态的矩形,绘制一个可以移动的圆,并设置刷新频率
# 时间追踪
clock = pg.time.Clock()
# 小球默认位置
x, y = 390, 290
# 轮询
while isOpen:
# 频率
clock.tick(10)
# 矩形
pg.draw.rect(screen, ("blue"), (100, 100, 35, 35))
# 绘制圆
pg.draw.circle(screen, ("red"), (x, y), 20)
# 默认情况下向右移动
x += 20
本节课想要通过用户键盘的操作,来改变小球的移动方向
# 判断是否键盘按下
elif e.type == pg.KEYDOWN:
而对于上下左右的按键常量为:
但是,判断具体按键并不是e.type,通过手册查询到是e.key
# 小球方向
dir = "right"
isOpen = True
# 轮询
while isOpen:
# 判断方向
if dir == "right":
x += 20
elif dir == "left":
x -= 20
elif dir == "up":
y -= 20
elif dir == "down":
y += 20
for e in pg.event.get():
if e.type == pg.QUIT:
isOpen = False
# 判断是否键盘按下
elif e.type == pg.KEYDOWN:
# 判断按下了左键盘
if e.key == pg.K_LEFT:
#print("左")
dir = "left"
elif e.key == pg.K_RIGHT:
#print("右")
dir = "right"
elif e.key == pg.K_UP:
#print("上")
dir = "up"
elif e.key == pg.K_DOWN:
#print("下")
dir = "down"
我们想让移动的球对方块进行碰撞,采用坐标重叠的方法设计
# 方块默认位置
rx, ry = 100, 100
while isOpen:
# 方块占用的区域为:x(100~135),y(100~135)
pg.draw.rect(screen, ("blue"), (rx, ry, 35, 35))
# 判断小球是否碰撞方块
if rx != -9999 and ry != -9999:
if x > rx and x < rx + 35 and y > ry and y < ry + 35:
# 让方块飞到天际去
rx = -9999
ry = -9999
# 判断小球碰撞边界,边缘坐标+本身大小
if x < 0 + 20 or x > 800 - 20 or y < 0 + 20 or y > 600 - 20:
x, y = 390, 290
pygame库提供了文字输入的模块方法font
pygame库旗下的属性(模块):
模块名 | 说明 |
---|---|
.font | 文字模块 |
.font模块下的方法:
方法名 | 说明 |
---|---|
.Sysfont() | 返回一个可以创建字体的变量(对象Font) |
# 设置文本
# 注意1:参数1为字体名称,可以在C盘windows下Fonts查阅
# 注意2:参数2为大小20
font = pg.font.SysFont("simhei", 20)
.Sysfont()方法下方法:
方法名 | 说明 |
---|---|
.render() | 绘制文本 |
Surface模块下的方法:
方法名 | 说明 |
---|---|
.blit() | 将图像或文字图形绘制到窗体上 |
# 得分文本
# 注意1:参数1为文本,参数2为是否平滑抗锯齿
# 注意2:参数3为元祖模式颜色,参数4
# 注意3:blit方法将文本绘制到窗体上
screen.blit(font.render("得分:", True, ("black")), (720,10))
# 分数文本
screen.blit(font.render(str(score), True, ("black")), (780, 10))
# 得分
score = 0
# 判断小球是否碰撞方块
if rx != -9999 and ry != -9999:
score += 1
# 判断小球碰撞边界
if x < 0 + 20 or x > 800 - 20 or y < 0 + 20 or y > 600 - 20:
score = 0
之前学习的编程方式就是面向过程,即员工思维。
提醒:面向对象难度较大,对于教培老师,当然要掌握;对于小学生,可选;
面向对象就好比总裁思维,那总裁的思维是哪些?
我们之前已经零星的接触过属性和方法的区别
属性和方法概念:
实例演练,小汽车对象:
有玩过泰拉瑞亚的世界生成形式的游戏吗?大概这个意思
类是一切的基石,而对象是类生成出来的一个副本
# 编写一个世界类
# 注意1:约定俗成,类名首字母大写
# 注意2:class和pass是关键字
# 注意3:两种写法 class World: 或 class World():
class World:
# 空类会报错,需要pass填充
pass
# 创建一个对象,即副本,直接函数形式调用即可
# 注意1:为方便后续使用,一般会将调用类()返回给一个变量
# 注意2:这个w就是这个对象
# 注意3:World()看上去是函数调用,但有自己的名称:实例化
w = World()
print(w)
print(type(w))
初始化函数:__ init __() 一般在定义类时定义,也可以称为初始化方法
# 世界类
class World():
# 定义初始化函数
# 注意1:参数1固定为self,必传,关键字
def __init__(self):
# 函数没内容,pass占位
pass
w = World()
类的属性,一般用于保证创建的对象具有相应的特性
# 世界类
class World():
# 定义初始化函数
# 注意1:参数1固定为self,必传,关键字
# 注意2:self代表World本身
def __init__(self):
# 创建属性
self.name = "火山"
self.gender = "熔岩"
w1 = World()
print(w1.name+w1.gender,"的世界被创建!")
# 世界类
class World():
# 定义初始化函数
# 注意1:参数1固定为self,必传,关键字
# 注意2:self代表World本身的实例化对象
def __init__(self, name, gender):
# 创建属性
self.name = name
self.gender = gender
# 给初始化函数传参
# 相当于给生成的世界做自定义选项
# 或者添加了世界种子之类的东西
w1 = World("火山", "熔岩")
print(w1.name+w1.gender,"的世界被创建!")
w2 = World("寒冰", "洞窟")
print(w2.name+w2.gender,"的世界被创建!")
所谓静态,无法实例化改变,数据定义后可以共享给所有对象使用
# 世界类
class World:
# 静态属性
# 注意1:不在初始化函数里,不需要self
# 注意2:不通过函数赋值,可直接赋值
age = 1000
def __init__(self, name, gender):
self.name = name
self.gender = gender
w1 = World("火山", "熔岩")
print(w1.age)
w2 = World("寒冰", "洞窟")
print(w2.age)
# 类.静态属性
print(World.age)
动态属性,就很好理解了。直接在实例化对象创建的属性
w1 = World("火山", "熔岩")
print(w1.age)
# 实例化对象直接创建的属性
# 类似普通变量,在类中不存在,本身也是实例属性
w1.info = "我是动态属性"
print(w1.info)
实例方法(函数),也是普通类里的方法,用于执行实例化对象后的某种行为
# 方法(函数),self是函数必填的
def run(self):
return "遇到火山熔岩副本,我要使用降温灭火装备!"
w1 = World("火山", "熔岩")
# 实例方法
print(w1.run())
w2 = World("寒冰", "洞窟")
print(w2.run())
如果要实现针对不同对象(副本),采取对应的行为:
# 世界类
class World:
age = 1000
def __init__(self, name, gender, a, b):
self.name = name
self.gender = gender
self.a = a
self.b = b
# 类方法(函数),self是函数必填的
# 注意:字符串太长,可以在+号后面加一个\表示换行
def run(self):
return "遇到" + self.name + self.gender +\
"副本,我要使用" + self.a + self.b + "装备!"
w1 = World("火山", "熔岩", "降温", "灭火")
print(w1.run())
w2 = World("寒冰", "洞窟", "保暖", "碎冰")
print(w2.run())
和静态属性一样,静态方法是每一个对象(副本)都可以共享使用的方法
# 静态方法
# 在普通方法上方设置@staticmethod就变成静态方法
# 这种@的语法叫做装饰器语法
@staticmethod
def over():
return "Game Over!"
w1 = World("火山", "熔岩", "降温", "灭火")
print(w1.run())
print(w1.over())
w2 = World("寒冰", "洞窟", "保暖", "碎冰")
print(w2.run())
print(w2.over())
# 静态方法可以直接通过类名.方法()
print(World.over())
和动态属性一样,在类外声明的普通函数,并用实例化对象调用的方法
# 普通函数
def eat():
return "吃饭"
# 将函数名赋值给动态属性
w2.eat = eat
print(w2.eat())
使用装饰器@classmethod声明的方法
# 类方法
@classmethod
def info(cls):
return cls.age
# 类方法
print(World.info())
面向对象有三大特性:封装、继承和多态,那什么是封装?
# 世界类
class World:
def __init__(self, name, gender):
self.name = name
self.gender = gender
w1 = World("火山", "熔岩")
# 共有属性特性
# 注意1:可以直接赋值
# 注意2:可以直接输出
w1.name = "沙漠"
print(w1.name)
def __init__(self, name, gender):
# 私有属性,只要在前面加上两个下划线即可
self.__name = name
self.__gender = gender
w1 = World("火山", "熔岩")
# 私有属性直接获取,报错
print(w1.__name)
# 世界类
class World:
def __init__(self, name, gender):
# 私有属性,只要在前面加上两个下划线即可
self.__name = name
self.__gender = gender
def getName(self):
return self.__name
w1 = World("火山", "熔岩")
# 私有变量被封装了,但可以设置一个方法作为调用入口
# 这个调用入口就好比机箱提供的插口区
print(w1.getName())
# 世界类
class World():
def __init__(self, name = "", gender = ""):
# 私有属性,只要在前面加上两个下划线即可
self.__name = name
self.__gender = gender
def setName(self, name):
self.__name = name
def getName(self):
return self.__name
w1 = World()
# 私有化后的属性赋值
w1.setName("沙漠")
# 私有变量被封装了,但可以设置一个方法作为调用入口
# 这个调用入口就好比机箱提供的插口区
print(w1.getName())
私有方法和私有属性概念一样
# 我是私有方法,外部无法调用
def __run(self):
return "运行。。。"
# 无法执行私有方法
print(w1.__run())
# 我是私有方法,外部无法调用
def __run(self):
return "运行。。。"
# 对外公开的方法
def go(self):
return self.__run()
# 启动
print(w1.go())
getName() 和 setName() 是一种比较通用的封装属性的手段,但还是有点麻烦
# 世界类
class World:
def __init__(self, name = "火山", gender = "熔岩"):
self.__name = name
self.__gender = gender
# 对外获取私有属性__name
def getName(self):
return self.__name
w1 = World()
# 私有属性无法直接赋值取值,但操作语法并不报错
# 这里的__name已经是动态属性,和类里面的私有属性无关
w1.__name = "寒冰"
# 这里输出的是动态属性 寒冰
print(w1.__name)
# 之类获取到私有属性 火山
print(w1.getName())
# 世界类
class World:
def __init__(self, name = "火山", gender = "熔岩"):
self.__name = name
self.__gender = gender
# 装饰器
@property
def name(self):
return self.__name
# 装饰器
@name.setter
def name(self, name):
self.__name = name
def getName(self):
return self.__name
w1 = World()
w1.name = "寒冰"
# 下面两种获取均为 寒冰
print(w1.name)
print(w1.getName())
父亲有100w,儿子继承了父亲的100w,那么儿子就有了100w,这就是继承
# 火山类
class Fire:
name = "火山"
gender = "熔岩"
def fight(self):
print("在"+ self.name + self.gender +"里战斗!")
# 寒冰类
class Cold:
name = "寒冰"
gender = "洞窟"
def fight(self):
print("在"+ self.name + self.gender +"里战斗!")
# 火山对象
f = Fire()
f.fight()
# 寒冰对象
c = Cold()
c.fight()
要解决火山、寒冰等工厂冗余问题,我们还得请回世界工厂来整合共性
# 世界类(父类)
class World:
# 将相同的逻辑放在父类继承
age = 1000
def fight(self):
print("在"+ self.name + self.gender +"里战斗!")
# 火山类(子类)
# 注意1:子类继承父类,只需要在括号里传入父类名
class Fire(World):
name = "火山"
gender = "熔岩"
# 寒冰类(子类)
class Cold(World):
name = "寒冰"
gender = "洞窟"
# 火山对象
f = Fire()
print(f.age)
f.fight()
# 寒冰对象
c = Cold()
c.fight()
有时,我们需要修改父类继承下来的属性和方法,以及初始化函数
# 世界类(父类)
class World:
# 将相同的逻辑放在父类继承
age = 1000
# 初始化函数
def __init__(self, name, gender):
self.name = name
self.gender = gender
def fight(self):
print("在"+ self.name + self.gender +"里战斗!")
# 火山类(子类)
# 注意1:子类继承父类,只需要在括号里传入父类名
class Fire(World):
pass
# 寒冰类(子类)
class Cold(World):
pass
# 火山对象
f = Fire("火山", "熔岩")
print(f.age)
f.fight()
# 寒冰对象
c = Cold("寒冰", "洞穴")
c.fight()
# 火山类(子类)
# 注意1:子类继承父类,只需要在括号里传入父类名
class Fire(World):
# 重写属性
def __init__(self):
# 子类调用父类的初始化函数,并传递参数
World.__init__(self, "火山", "熔岩")
# 寒冰类(子类)
class Cold(World):
# 重写属性
def __init__(self):
World.__init__(self, "寒冰", "洞穴")
# 火山对象
f = Fire()
print(f.age)
f.fight()
# 寒冰对象
c = Cold()
c.fight()
# 重写方法
def fight(self):
#调用父类
World.fight(self)
print(123)
对于父类,我们有几个问题有待解决,比如父类要不要封装等
对于继承的思考:
创建一个抽象的世界类,防止用户实例化:
# 引入abc模块,实现抽象化
import abc
# 世界类(抽象父类)
class World(metaclass=abc.ABCMeta):
# 抽象方法
@abc.abstractmethod
def fight(self):pass
# 无法实例化
w1 = World()
# 火山类(子类)
class Fire(World):
pass
# 实例化后,报错,提示必须实现父类的抽象方法
# 也就是,总裁的命令必须完成
f = Fire()
# 火山类(子类)
class Fire(World):
def fight(self):
return "战斗!"
f = Fire()
print(f.fight())
# 引入abc模块,实现抽象化
import abc
# 世界类(抽象父类)
class World(metaclass=abc.ABCMeta):
#抽象属性
@property
@abc.abstractmethod
def name(self):pass
# 抽象方法
@abc.abstractmethod
def fight(self):pass
# 火山类(子类)
class Fire(World):
@property
def name(self):
return self.__name
@name.setter
def name(self, name):
self.__name = name
def fight(self):
return "在" + self.__name + "区域战斗!"
# 抽象属性也必须强制定义
f = Fire()
f.name = "火山"
print(f.fight())
# 我们只用abc模块中的两个方法,这样可以去掉abc.的前缀
from abc import ABCMeta, abstractmethod
# 世界类(抽象父类)
class World(metaclass=ABCMeta):
#抽象属性
@property
@abstractmethod
def name(self):pass
# 抽象方法
@abstractmethod
def fight(self):pass
多态:即多种形态,执行同一种命令根据场景不同而执行不同的行为特征
多态理解:
第一种做法,通过固有函数作为执行者,传入不同环境实现不同行为的多态;
from abc import ABCMeta, abstractmethod
# 世界类(抽象父类)
class World(metaclass=ABCMeta):
# 抽象方法
@abstractmethod
def fight(self):pass
# 火山类(子类)
class Fire(World):
def fight(self):
print("与炎魔战斗!")
# 寒冰类(子类)
class Cold(World):
def fight(self):
print("与霜魔战斗!")
# 战斗
def fight(obj):
obj.fight()
# 函数调用,传入不同的子类对象实现执行不同行为
fight(Fire())
fight(Cold())
'''
f = Fire()
c = Cold()
fight(f)
fight(c)
'''
# 世界类(父类)
class World:
def fight(self, obj):
obj.fight()
# 火山类(子类)
class Fire(World):
def fight(self):
print("与炎魔战斗!")
# 寒冰类(子类)
class Cold(World):
def fight(self):
print("与霜魔战斗!")
w = World()
# 调用父类的方法执行子类的方法
w.fight(Fire())
w.fight(Cold())
面向对象中,有很多工具方法来更方便的查询或构建我们的代码
# 世界类
class World:
def __init__(self, x, y):
self.x = x
self.y = y
# __str__() 替代本来的对象描述
def __str__(self):
return "这是一个世界类" + str(self.x)
# 析构函数
def __del__(self):
print("删除对象时,我被触发" + str(self.y))
w = World(10, 20)
print(w)
del w
重写父类方法时,我们还需要得到父类方法最终的结果,使用super()函数
# 世界类(父类)
class World:
def run(self):
return "World!"
# 火类
class Fire(World):
def run(self):
# 通过 super()函数调用父类方法
return super().run() + "Fire!"
f = Fire()
print(f.run())
从本节课开始,我们用面向对象实战一款经典的开放世界文字版:塞尔达传说
直接面向对象,对于新手来说不太容易,先面向过程开始,从底层打工开始
# 游戏开始
print("Loading...")
print("Loading...")
print("Loading...")
print("游戏开始....")
print("林克,林克,林克,醒一醒....")
# 初始化名字
name = input("请输入你的名字:")
if name != "林克":
print("你忘了吗?你叫林克!")
name = "林克"
# 初始化血量
life = 1
print("\n走出洞穴,遇到一个老爷爷,他要送你两个烤苹果!")
flag = int(input("是否接受?接受输入->1,不接受输入->0:"))
if flag == 1:
life += 2
print("你的生命值+2")
# 初始化防御力
defence = 1
# 初始化攻击力
attack = 1
# 统计目前状态
print("\n目前生命值:%d,防御力:%d,攻击力:%d"%(life, defence, attack))
和怪物攻击,默认怪先手,通过数值加减来判断胜利或失败
# 走入寒冰区
print("\n走入寒冰区,老爷爷要送你防寒服!")
# 区域防御力
defence_cold = 0
flag = int(input("是否接受?接受输入->1,不接受输入->0:"))
if flag == 1:
defence_cold = defence + 1
print("你的寒冰区防御力+1")
# 遇到第一个怪
print("\n你遇到了寒冰怪,开始挑战!")
enemy1_atk = 2
enemy1_life = 1
# 互相攻击,直到一方倒下
while True:
# 怪物先手,开始攻击,攻击算法:怪物攻击力 - 玩家防御力
# 玩家的生命值 = 玩家生命总量 - (怪物攻击力 - 玩家区域防御力)
# 吃满buff第一轮:3 - (2 - 2) = 3
# 不吃buff第一轮:1 - (2 - 1) = 0 死了
life = life - (enemy1_atk - defence_cold)
# 判断玩家生命
if life <= 0:
print("挑战失败!")
print("Game over!")
break
# 玩家开始攻击
enemy1_life = enemy1_life - attack
# 判断怪物的生命
if enemy1_life <= 0:
print("你胜利了!目前生命值为:%d"%life)
break
# 胜利后继续走入火山区
print("\n胜利后继续走入火山区")
# 统计目前状态
print("\n目前生命值:%d,防御力:%d,攻击力:%d"%(life, defence, attack))
胜利后可继续往下执行,但失败后,要退出整个系统,需要函数处理
# 主要函数
def main():
# 游戏开始
...
# 入口
main()
直接继续复制寒冰区的代码即可
# 获取防火服
print("\n火山区矿工告诉你,里面很热,需要防火服")
# 区域防御力
defence_fire = 0
flag = int(input("是否接受?接受输入->1,不接受输入->0:"))
if flag == 1:
defence_fire = defence + 1
print("你的火山区防御力+1")
# 遇到第一个怪
print("\n你遇到了熔岩怪,进入战斗模式!")
enemy2_atk = 2
enemy2_life = 1
# 互相攻击,直到一方倒下
while True:
life = life - (enemy2_atk - defence_fire)
# 判断玩家生命
if life <= 0:
print("挑战失败!")
print("Game over!")
return
# 玩家开始攻击
enemy2_life = enemy2_life - attack
# 判断怪物的生命
if enemy2_life <= 0:
print("你胜利了!目前生命值为:%d"%life)
break
# 胜利后继续走入城堡
print("\n胜利后走入城堡迎接公主")
# 统计目前状态
print("\n目前生命值:%d,防御力:%d,攻击力:%d"%(life, defence, attack))
介绍Boss和初始化数据
# 公主介绍Boss
print("\n公主:我的骑士啊!恶魔的攻击力为10000,防御力4000,生命值5000,而且先手!")
print("我这里有一把攻击力为8999光之弓,还有一张先手祝福之卷轴!")
flag1 = int(input("是否接受光之弓?接受输入->1,不接受输入->0:"))
flag2 = int(input("是否接受先手祝福之卷轴?接受输入->1,不接受输入->0:"))
# 恶魔数据
enemy3_life = 5000
enemy3_defence = 4000
enemy3_atk = 10000
# 更新攻击力
if flag1 == 1:
attack += 8999
Boss对战和小怪基本一致,主要是否接受先手Buff这个条件
# 互相攻击,直到一方倒下
while True:
# 判断先手
if flag2 == 1:
# 玩家开始攻击
enemy3_life = enemy3_life + enemy3_defence - attack
# 取消先手buff
flag2 = 0
# 判断怪物的生命
if enemy3_life <= 0:
print("\n你战胜了恶魔,拯救了公主,游戏通关!")
return
life = life - (enemy3_atk - defence)
# 判断玩家生命
if life <= 0:
print("你被恶魔打败啦,公主也没救回来!")
print("Game over!")
return
# 玩家开始攻击
enemy3_life = enemy3_life + enemy3_defence - attack
# 判断怪物的生命
if enemy3_life <= 0:
print("\n你战胜了恶魔,拯救了公主,游戏通关!")
return
文字游戏,太多旁白,我们先从这里入手进行整理吧
# 旁白类
class Aside:
# 开场语音
@staticmethod
def start():
print("Loading...")
print("Loading...")
print("Loading...")
print("游戏开始....")
print("林克,林克,林克,醒一醒....")
# 介绍Boss
@staticmethod
def boss():
print("\n公主:我的骑士啊!恶魔的攻击力为10000,防御力4000,生命值5000,而且先手!")
print("我这里有一把攻击力为8999光之弓,还有一张先手祝福之卷轴!")
# 游戏胜利
@staticmethod
def win():
print("你战胜了恶魔,拯救了公主,游戏通关!")
# 败于谁下
@staticmethod
def who(name):
print("你被%s打败啦,公主也没救回来!"%name)
# 游戏失败
@staticmethod
def over():
print("Game over!")
# 战斗旁白
@staticmethod
def fight(name):
print("\n你遇到了%s,进入战斗模式!"%name)
# 单局胜利
@staticmethod
def single(name):
print("恭喜你战胜了%s!"%name)
# 人物状态
@staticmethod
def status(life, defence, attack):
print("目前生命值:%d,防御力:%d,攻击力:%d"%(life, defence, attack))
# 输入提示
@staticmethod
def input(info):
return input("是否接受%s?接受输入->1,不接受输入->0:"%info)
# 开场
Aside.start()
#...
Aside.who(name)
Aside.over()
#...
将玩家的数据信息,单独通过一个类来管理调用
# 人物类
class Person:
# 初始化
def __init__(self, name, life, defence, attack):
self.__name = name
self.__life = life
self.__defence = defence
self.__attack = attack
self.__defence_cold = 0
self.__defence_fire = 0
@property
def name(self):
return self.__name
@name.setter
def name(self, name):
self.__name = name
@property
def life(self):
return self.__life
@life.setter
def life(self, life):
self.__life = life
@property
def defence(self):
return self.__defence
@defence.setter
def defence(self, defence):
self.__defence = defence
@property
def attack(self):
return self.__attack
@attack.setter
def attack(self, attack):
self.__attack = attack
@property
def defence_cold(self):
return self.__defence_cold
@defence_cold.setter
def defence_cold(self, defence_cold):
self.__defence_cold = defence_cold
@property
def defence_fire(self):
return self.__defence_fire
@defence_cold.setter
def defence_fire(self, defence_fire):
self.__defence_fire = defence_fire
# 开场语音
@staticmethod
def start():
print("Loading...")
print("Loading...")
print("Loading...")
print("游戏开始....")
print("林克,林克,林克,醒一醒....")
# 初始化名字
name = input("请输入你的名字:")
if name != "林克":
print("你忘了吗?你叫林克!")
name = "林克"
# 实例化人物数据
p = Person(name, 1, 1, 1)
return p
# 攻击
p.life = p.life - (enemy1_atk - p.defence_cold)
# 统计目前状态
Aside.status(p.life, p.defence, p.attack)
将怪物的数据信息,单独通过一个类来管理调用
# 怪物类
class Enemy:
# 初始化
def __init__(self, life, attack, defence = 0):
self.__life = life
self.__attack = attack
self.__defence = defence
@property
def life(self):
return self.__life
@life.setter
def life(self, life):
self.__life = life
@property
def attack(self):
return self.__attack
@attack.setter
def attack(self, attack):
self.__attack = attack
@property
def defence(self):
return self.__defence
@defence.setter
def defence(self, defence):
self.__defence = defence
# 创建寒冰怪,实例化
en1 = Enemy(1, 2)
# 怪物属性调用
p.life = p.life - (en1.attack - p.defence_cold)
将小怪和boss战的逻辑,存储到一个单独的类进行管理
# 战斗类
class Fight:
# 和普通怪战斗
@staticmethod
def general(p, en, Aside, defence):
# 互相攻击,直到一方倒下
while True:
# 怪物先手:攻击:怪物攻击力 - 玩家防御力
# 玩家生命值 = 玩家生命总量 - (怪物攻击 - 玩家区域防御力)
# 吃满buff第一轮:3 - (2 - 2) = 3
# 不吃buff第一轮:1 - (2 - 1) = 0 死亡
p.life = p.life - (en.attack - defence)
# 判断玩家生命
if p.life <= 0:
Aside.who(en.name)
Aside.over()
return False
# 玩家开始攻击
en.life = en.life - p.attack
# 判断怪物的生命
if en.life <= 0:
Aside.single(en.name)
return True
# 和Boss战斗
@staticmethod
def boss(p, en, Aside, flag2):
# 互相攻击
while True:
# 判断先手
if flag2 == 1:
# 玩家攻击
en.life = en.life + en.defence - p.attack
# 取消先手
flag2 = 0
# 判断怪物生命
if en.life <= 0:
Aside.win()
return False
# 正常手(没有buff,我就是先手,有buff,我就是后手)
p.life = p.life - (en.attack - p.defence)
# 判断玩家生命
if p.life <= 0:
Aside.who(en.name)
Aside.over()
return False
# 玩家攻击
en.life = en.life + en.defence - p.attack
# 判断怪物生命
if en.life <= 0:
Aside.win()
return True
# 创建熔岩怪
en2 = Enemy("熔岩怪", 1, 2)
# 遇到第二个怪,熔岩怪
Aside.fight(en2.name)
# 战斗
if Fight.general(p, en2, Aside, p.defence) == False: return
# 创建Boss
en3 = Enemy("恶魔", 5000, 10000, 4000)
# 战斗
if Fight.boss(p, en3, Aside, flag2) == False: return
目前四个场景都在主程序中,分成独立类,方便以后扩展升级
# 引入类库
from Aside2 import *
from Original2 import *
from Cold2 import *
from Fire2 import *
from Castle2 import *
def main():
# 开场语音
p = Aside.start()
# 执行场景一
o = Original()
o.exec(p, Aside)
# 执行场景二
c = Cold()
c.exec(p, Aside)
# 执行场景三
f = Fire()
f.exec(p, Aside)
# 执行场景四
cc = Castle()
cc.exec(p, Aside)
from abc import ABCMeta, abstractmethod
from Enemy2 import *
from Fight2 import *
# 世界类(抽象父类)
class World(metaclass=ABCMeta):
# 抽象方法,执行场景
@abstractmethod
def exec():pass
from World2 import *
# 初始场景(子类)
class Original(World):
# 执行
def exec(self, p, Aside):
print("\n走出洞穴,遇到一个老爷爷,他要送你两个烤苹果!")
flag = int(Aside.input("烤苹果"))
if flag == 1:
p.life += 2
print("你的生命值+2")
# 统计目前状态
Aside.status(p.life, p.defence, p.attack)
观察目前结构,调整重复代码,并实现场景的多态调用,实现总裁式一行启动模式
# 统计数据
def stats(self, p):
# 统计目前状态
Aside.status(p.life, p.defence, p.attack)
# 统计目前状态
super().stats(p)
Aside类,直接通过World引入,避免前台传递Aside类
在World类中,创建一个静态方法,实现多态的调用效果
由于return 被封装到子类的方法里了,无法实现退出函数,需要再传递回来
# 静态方法
@staticmethod
def run(obj, p):
return obj.exec(p)
def main():
# 开场语音
p = Aside.start()
# 执行场景一(初始区)
World.run(Original(), p)
# 执行场景二(寒冰区)
if World.run(Cold(), p) == False: return
# 执行场景三(火山区)
if World.run(Fire(), p) == False: return
# 执行场景四(城堡区)
if World.run(Castle(), p) == False: return
# 战斗
if Fight.general(p, en1, Aside, p.defence_cold) == False: return False
# 引入game
import game2 as g
# 塞尔达,启动
g.main()
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。