【experimental】12岁儿童Python三个月编程入门

我将编程看作是人与特定系统交互构成的一系列创意活动(creative activity with specific system)
OIP-C.jpeg

81V2c3GHklL._AC_UF1000,1000_QL80_.jpg

宏观层面:
=====

 - 初学者对于语言的介绍不用太多关注,快速安装好开发环境即可
 - 学习就是要注意熟悉各种pattern,能够举一反三
 - 程序离不开存储、执行,目前主流的编程语言离不开:数据类型、变量、各种运算符操作以及执行控制
 - Python 丰富的生态,各种三方库,可以快速实现一个复杂问题的解决方案
 - 强大的语言是能够让用户很自然表达解决问题的方案,如同写作那么自然

微观层面:
=====

 - Python的基础语法,稍微练习几次就能熟练掌握;重点掌握基础数据类型的使用,list, dict等
 - 针对特定应用,掌握必要的第三方库,比如编写2D game,可以使用Pygame; 网络数据抓取选择request以及其他相关的库;GUI图形用户节目程序开发推荐PyQt库;Machine Learning生态也是很丰富
 - 同一类型问题,多编写几个程序实践一下,尽量少拷贝粘贴,自行输入代码
 - 有一定programming基础可以更多了解高阶的主题,有两个方向:特定问题域的深入;更一般性计算机科学的学习

课程小结:
=====

 - 第一课:语言介绍,基础数据类型和变量以及一些常规操作
 - 第二课:输入与输出,字符串格式化输出
 - 第三课:语句,执行控制,条件,循环
 - 第四课:python list, dict的等数据类型使用,文件读写操作
 - 第五课:python三方库使用,import等关键字,pygame简单演示,文字、图片、播放wav,mp3等
 - 第六课:snake game分解,pygame基础游戏编写结构分析,snakegame游戏逻辑分解(基于过程的编程范式)
 - 第七课:OOP面向对象初步,介绍class的基本概念,可以用class 建模现实的一些概念,比如animal,student,
   bank账户等; 将sanke game用OOP编程方式改写,大部分代码复用
 - 第八课:目标是异常处理入门,snake game加入一些额外的功能,计分; 有时间初级一些网络数据抓取,API使用
 - 第九课:GUI图形用户程序开发初步,重点推荐PyQt6,可以实现一个比较简单的例子? 还可以提及多线程概念
 - 第十课:课程小结,选个主题练习编写一个中等复杂程度的应用,课后自行再不断完善?

入门教材不是很重要,重要的是有合适的导师指引!!渡过了入门期,后续有很多种可能的学习路径,比如可以结合自己的兴趣,学习如何开发特定领域的应用程序;抑或继续系统深入学习计算机科学

第1个月:

• Python简介 - 解释Python是什么,它的用途以及一些可以用它完成的示例。
• 变量和数据类型 - 教他们有关不同类型的数据(字符串、整数、浮点数等)以及如何将它们存储在变量中。
• 输入和输出 - 教他们如何要求用户输入以及如何将输出打印到控制台上。
• 条件语句 - 教他们如何使用if/else语句在代码中做出决策。
• 循环 – 教他们关于for和while循环的知识,以及如何使用它们重复执行代码。
初期不用对这些概念死记硬背,在后续的不同练习中逐渐掌握,先有模糊的感性认识即可

第1个月的每周计划:

第1周:

• 介绍Python编程语言及其历史和用途。
• 安装Python和代码编辑器。
• 讲解变量和数据类型的基础知识,如整数、浮点数、字符串、布尔值等。
• 演示如何使用Python进行数学运算和字符串操作。
• 分配第1周的练习,包括让学生练习使用变量和数据类型,以及完成一些简单的数学和字符串操作。

介绍Python编程语言及其历史和用途。

你好!Python是一种广泛使用的高级编程语言,它是一种解释型语言,由Guido van Rossum于1991年创建。Python的设计目标是易读易写、清晰简洁,适合快速开发应用程序、脚本和自动化任务。

Python的历史可以追溯到上世纪80年代末和90年代初,在这个时期,Guido van Rossum和其他Python的创始人致力于创建一种易学易用的编程语言,以解决当时其他语言的一些缺陷。

Python的应用非常广泛,它被用于Web开发、科学计算、数据分析、人工智能、机器学习等领域。它还有一个庞大的社区,提供了大量的第三方库和工具,使得Python编程变得更加简单和快速。

总之,Python是一种非常有用的编程语言,可以用于各种各样的项目和应用程序,无论是初学者还是专业人士,都可以从中受益。

我也只是2010年之后才开始接触Python,在研究3D打印机的时候,接触了使用Python开发的3D打印软件
添加一些图片和视频,有所感性认识

python-applications.png
What_is_Python_used_for_91052e6b72.png

安装Python和代码编辑器。

安装Python和代码编辑器是Python编程的第一步。下面是安装Python和代码编辑器的基本步骤:

1. 下载Python安装程序:访问Python官方网站(https://www.python.org/downloads/),下载适合您操作系统的Python安装程序。
2. 安装Python:打开下载的安装程序,并按照提示进行安装。在安装过程中,可以选择将Python添加到系统路径中,以便能够从任何位置访问它。
3. 选择一个代码编辑器:代码编辑器是一种用于编写和编辑代码的工具。Python有许多流行的代码编辑器可供选择,例如Visual Studio Code、PyCharm和Sublime Text等。选择一个适合自己的代码编辑器,并安装它。
4. 配置代码编辑器:在代码编辑器中配置Python解释器和代码运行环境。通常需要将代码编辑器连接到Python解释器,并指定要使用的Python版本。一些代码编辑器也支持通过插件或扩展添加其他功能,例如调试器和代码补全。

完成上述步骤后,您就可以开始编写Python代码并运行它了。

我们工作中,重度使用visial studio code,编辑、浏览代码,执行和调试代码
visual-studio-code.png

讲解变量和数据类型的基础知识,如整数、浮点数、字符串、布尔值等

当我们编写计算机程序时,我们需要告诉计算机在执行指令时要处理什么类型的数据。Python提供了不同的数据类型来表示不同的数据,其中一些常见的数据类型包括:

1. 整数(int):表示整数值,例如 3、12、-5。
2. 浮点数(float):表示带有小数点的数值,例如 3.14、2.0、-0.5。
3. 字符串(string):表示文本数据,例如 "Hello"、"Python"、"123"。
4. 布尔值(bool):表示 True 或 False。

为了在程序中使用这些数据类型,我们需要使用变量来存储它们。变量可以看作是计算机内存中的一个标签,用于存储和引用数据。在Python中,我们可以通过赋值来创建变量,例如:

1.png

在这个例子中,我们分别创建了整数、浮点数、字符串和布尔变量,它们分别被赋值为10、3.99、"Alice"和True。请注意,在Python中,我们不需要事先声明变量的数据类型,因为Python是一种动态类型语言,它可以根据变量的值来自动推断其类型。
通过理解这些基本概念,我们可以开始编写简单的Python程序,例如:

2.png

在这个例子中,我们创建了两个整数变量num1和num2,并将它们相加得到结果result。然后,我们创建了一个字符串变量name,并将其与另一个字符串"Hello, "相加后输出。这些简单的程序可以帮助我们熟悉Python的基本语法和概念,并为我们更复杂的程序打下基础。

演示如何使用Python进行数学运算和字符串操作

好的,让我们来演示一下如何使用Python进行数学运算和字符串操作。
首先,让我们来看看数学运算。Python支持所有基本的数学运算,如加法、减法、乘法、除法和求幂。下面是一些示例:
3.png

希望这些示例可以帮助您了解如何在Python中进行数学运算和字符串操作。

演示如何使用条件语句来控制程序流程

当我们需要在程序中根据不同的条件采取不同的行动时,就需要使用条件语句。在Python中,条件语句通常使用if语句实现。
if语句的一般形式为:

4.png

在这个例子中,程序首先使用input()函数获取一个整数,然后使用if语句判断该整数是偶数还是奇数,并打印出相应的信息。
除了if语句,Python还支持其他的条件语句,例如elif语句和assert语句,这些语句都可以用来控制程序流程。

练习: 编写一个Python程序,提示用户输入姓名和年龄,然后打印出个性化消息。
测试: 给定以下代码:
5.png

这个程序的输出是什么?

第2周:

• 介绍Python中的输入和输出,包括print语句和input函数。
• 讲解Python中的条件语句和布尔运算符。
• 演示如何使用条件语句来控制程序流程。
• 分配第2周的练习,让学生练习使用条件语句和布尔运算符,并编写一个简单的程序,根据用户输入的值输出不同的结果。

介绍Python中的输入和输出,包括print语句和input函数

Python中的输入和输出是编写程序时的两个基本操作。输出通常使用print语句或函数来完成,而输入则使用input函数来完成。
print语句可以将文本、数字和变量输出到屏幕上。例如,下面的代码将输出一个简单的问候语:
6.png

除了文本,print语句也可以输出数字和变量的值:
7.png

需要注意的是,input函数返回的是一个字符串类型的值,所以如果你需要使用这个值进行数学运算,你需要将它转换为一个数值类型。例如:
8.png

广义的输入输出有很多形式,比如游戏手柄的输入、手机的触摸、人脸识别等;声音提示、

讲解Python中的条件语句和布尔运算符

条件语句和布尔运算符是Python编程中非常重要的概念,它们可以帮助程序根据不同情况采取不同的操作。
条件语句基本上是根据某个条件的真假来执行代码块。在Python中,条件语句使用if、elif和else关键字。
下面是一个简单的示例代码:
9.png

在上面的代码中,如果x大于5,程序将执行第一行print语句,如果x等于5,则执行第二行print语句,否则执行最后一行print语句。
布尔运算符用于比较两个条件,并根据这些条件之间的关系来计算结果。在Python中,有三个布尔运算符:and、or和not。
下面是一个简单的示例代码:
10.png

在上面的代码中,第一个if语句中的and运算符要求x大于2并且y小于20才会输出,第二个if语句中的or运算符只要求x大于7或者y小于5其中一个条件成立就会输出,第三个if语句中的not运算符要求x不大于y才会输出。
总之,条件语句和布尔运算符是Python编程中非常重要的概念,对于掌握Python编程非常重要。

练习: 编写一个Python程序,提示用户输入一个数字,然后打印出该数字是正数、负数还是零。
测试: 给定以下代码:
11.png

这个程序的输出是什么?

第3周:

• 介绍Python中的循环,包括for循环和while循环。
• 演示如何使用循环来遍历列表和字典。
• 分配第3周的练习,让学生练习使用循环,编写一个程序,遍历一个列表并输出其中的每个元素。

介绍Python中的循环,包括for循环和while循环=》
在Python中,循环语句可以用于多次执行代码块。主要有两种类型的循环:for循环和while循环。
for循环用于对一组对象进行迭代,可以通过for循环来遍历字符串、列表、元组、集合、字典等数据类型中的元素。for循环的基本语法如下:
12.png

while循环则用于在条件满足的情况下重复执行代码块。while循环的基本语法如下:
13.png

演示如何使用循环来遍历列表和字典=》
14.png

编写一个Python程序,提示用户输入一个单词,然后逐个打印出单词中的每个字母。
测试: 给定以下代码:

第4周:

• 介绍Python中的函数,包括如何定义和调用函数。
• 演示如何使用函数来组织代码和重复利用代码。
• 分配第4周的练习,让学生练习使用函数,编写一个简单的程序,包含几个函数,完成特定的任务。
• 在每周结束时,您可以安排一个练习或小测验,以检查学生对本周所学内容的理解和掌握程度。此外,您可以鼓励学生寻找一些有趣的编程项目,以进一步发展他们的技能和兴趣。

介绍Python中的函数,包括如何定义和调用函数=>
在Python中,函数是一段可重复使用的代码块,可以将它们定义在程序中,以便在需要时调用它们。函数在代码的组织和复用方面非常有用。
定义函数的语法如下:
15.png

这个函数将 2 和 3 作为参数传递,并返回它们的和。函数的返回值可以被保存在变量中,也可以直接被打印出来。
在函数中,可以使用return语句来返回值。如果函数没有return语句,则默认返回None。例如:

16.png

编写一个Python程序,实现以下功能:

定义一个函数 calculate_average,输入参数为一个整数列表,返回值为列表中所有整数的平均值。

定义一个函数 find_max,输入参数为一个整数列表,返回值为列表中的最大值。

定义一个函数 find_min,输入参数为一个整数列表,返回值为列表中的最小值。

定义一个函数 find_range,输入参数为一个整数列表,返回值为列表中最大值和最小值的差。

定义一个主函数 main,在该函数中实现以下功能:

    提示用户输入一组整数,以逗号分隔。例如:1,2,3,4,5

    将输入转换为整数列表,并调用上述四个函数计算列表的平均值、最大值、最小值和范围,并将结果打印到屏幕上。

    如果用户输入的内容不是有效的整数列表,则显示错误信息并退出程序。

测试程序,确保它可以正确处理各种输入情况,并产生正确的输出结果。

提示:可以使用内置函数 input() 来获取用户输入,使用内置函数 split() 来将字符串拆分成列表,使用内置函数 int() 来将字符串转换为整数。
参考代码:
17.png
18.png
19.png
20.png

这个程序的输出是什么?

第2个月:

• 列表 - 教他们关于列表的知识,如何创建、访问和修改它们。
• 字典 - 教他们关于字典的知识,以及如何使用它们存储键-值对。
• 文件输入和输出 - 教他们如何在Python中读写文件。
• 模块和库 – 介绍模块的概念以及如何在Python中使用库。

列表 - 教他们关于列表的知识,如何创建、访问和修改它们

my_list = [1, 2, 3, 4, 5]

这将创建一个名为 my_list 的列表,其中包含五个整数。

## 访问列表元素 ##

要访问列表中的元素,可以使用索引。Python中的索引从0开始,因此要访问第一个元素,可以使用索引0。例如:

my_list = [1, 2, 3, 4, 5]
print(my_list[0])  # 输出1

要访问列表中的最后一个元素,可以使用索引 -1。例如:

my_list = [1, 2, 3, 4, 5]
print(my_list[-1])  # 输出5

修改列表元素

要修改列表中的元素,可以使用索引和赋值运算符 =。例如,要将列表中的第一个元素修改为10:

my_list = [1, 2, 3, 4, 5]
my_list[0] = 10
print(my_list)  # 输出[10, 2, 3, 4, 5]
列表方法

Python还提供了许多有用的列表方法,例如 append()、insert()、pop()、remove()、sort() 等等。下面是一些示例:

  • append():将一个元素添加到列表的末尾。

    my_list = [1, 2, 3, 4, 5]
    my_list.append(6)
    print(my_list) # 输出[1, 2, 3, 4, 5, 6]

  • insert():将一个元素插入到列表的指定位置。

    my_list = [1, 2, 3, 4, 5]
    my_list.insert(2, 10) # 在索引为2的位置插入10
    print(my_list) # 输出[1, 2, 10, 3, 4, 5]

  • pop():删除并返回列表中指定位置的元素。

    my_list = [1, 2, 3, 4, 5]
    print(my_list.pop(2)) # 输出3
    print(my_list) # 输出[1, 2, 4, 5]

  • remove():删除列表中第一个匹配给定值的元素。

    my_list = [1, 2, 3, 4, 5]
    my_list.remove(3)
    print(my_list) # 输出[1, 2, 4, 5]

  • sort():按升序对列表进行排序。

    my_list = [3, 2, 1, 5, 4]
    print(my_list)

除了创建、访问和修改列表外,还有其他一些列表相关的操作和方法。以下是一些常用的列表操作和方法:
添加元素:可以使用 append() 方法将元素添加到列表的末尾,也可以使用 insert() 方法将元素插入到列表的任何位置。

my_list = [1, 2, 3]
my_list.append(4)        # 添加元素到末尾
print(my_list)           # 输出 [1, 2, 3, 4]

my_list.insert(2, 5)     # 在位置 2 插入元素 5
print(my_list)           # 输出 [1, 2, 5, 3, 4]
  • 删除元素:可以使用 remove() 方法删除列表中的指定元素,也可以使用 pop() 方法删除指定位置的元素。

    my_list = [1, 2, 3, 4, 5]
    my_list.remove(3) # 删除元素 3
    print(my_list) # 输出 [1, 2, 4, 5]

    my_list.pop(2) # 删除位置 2 上的元素
    print(my_list) # 输出 [1, 2, 5]

  • 切片:可以使用切片操作访问列表中的一部分元素。

    my_list = [1, 2, 3, 4, 5]
    print(my_list[1:3]) # 输出 [2, 3]

    print(my_list[:3]) # 输出 [1, 2, 3]

    print(my_list[3:]) # 输出 [4, 5]

    print(my_list[-2:]) # 输出 [4, 5]

  • 迭代:可以使用循环迭代列表中的元素

    my_list = [1, 2, 3, 4, 5]
    for i in my_list:

     print(i)
    
  • 排序:可以使用 sort() 方法对列表进行排序。

    my_list = [3, 5, 1, 4, 2]
    my_list.sort()
    print(my_list) # 输出 [1, 2, 3, 4, 5]

以下是几个关于list的练习作业:

编写一个函数get_evens,输入一个整数列表,返回所有偶数构成的新列表。

def get_evens(lst):
    evens = []
    for num in lst:
        if num % 2 == 0:
            evens.append(num)
    return evens

编写一个函数get_odds,输入一个整数列表,返回所有奇数构成的新列表。

def get_odds(lst):
    odds = []
    for num in lst:
        if num % 2 != 0:
            odds.append(num)
    return odds

编写一个函数get_squares,输入一个整数列表,返回所有数字的平方构成的新列表。

def get_squares(lst):
    squares = []
    for num in lst:
        squares.append(num ** 2)
    return squares

其他练习:

编写一个函数remove_duplicates,输入参数为一个包含重复元素的整数列表,返回值为一个新的列表,其中不包含重复元素。例如,输入列表[1, 2, 3, 3, 4, 4, 5],返回列表[1, 2, 3, 4, 5]。
可以使用循环和条件语句来实现remove_duplicates函数,如下所示:

def remove_duplicates(lst):
    new_lst = []
    for i in lst:
        if i not in new_lst:
            new_lst.append(i)
    return new_lst

这个函数首先创建一个空列表new_lst来存储不重复的元素,然后遍历输入列表lst中的每个元素。对于每个元素,如果它不在new_lst中,则将其添加到new_lst中。最后,返回new_lst,它包含输入列表lst中的所有不重复元素。

编写一个函数reverse_list,输入参数为一个整数列表,返回值为一个新的列表,其中元素顺序与输入列表相反。例如,输入列表[1, 2, 3, 4, 5],返回列表[5, 4, 3, 2, 1]。

def reverse_list(lst):
    """
    Reverses the elements of a list and returns a new list with the reversed elements.
    """
    return lst[::-1]

该函数接受一个列表作为参数,并使用切片操作[::-1]返回一个新列表,该新列表的元素顺序与输入列表相反。例如,reverse_list([1, 2, 3, 4, 5])的输出为[5, 4, 3, 2, 1]。

编写一个函数find_common_elements,输入参数为两个整数列表,返回值为一个新的列表,其中包含两个输入列表中的公共元素。例如,输入列表[1, 2, 3, 4, 5]和[3, 4, 5, 6, 7],返回列表[3, 4, 5]。

def find_common_elements(list1, list2):
    common_elements = []
    for elem in list1:
        if elem in list2 and elem not in common_elements:
            common_elements.append(elem)
    return common_elements

这个函数先创建一个空列表 common_elements,然后遍历第一个输入列表 list1 中的元素。对于每个元素,如果它同时出现在第二个输入列表 list2 中且还没有被加入到 common_elements 列表中,就将它加入到 common_elements 列表中。最后返回 common_elements 列表。

需要注意的是,这个函数的实现并不是最优的,因为它在判断一个元素是否在 common_elements 列表中时需要进行线性搜索,这会增加函数的时间复杂度。如果输入列表比较大,可以考虑使用集合(set)来代替列表,这样判断一个元素是否在集合中的时间复杂度是常数级别的。

编写一个函数sum_adjacent_pairs,输入参数为一个整数列表,返回值为一个新的列表,其中相邻两个元素相加的和作为新列表的元素。例如,输入列表[1, 2, 3, 4, 5],返回列表[3, 5, 7, 9]。

def sum_adjacent_pairs(nums):

if len(nums) < 2:
    return []
res = []
for i in range(len(nums)-1):
    res.append(nums[i] + nums[i+1])
return res

这个函数首先检查列表长度是否大于等于2,如果不是,直接返回一个空列表。然后,它遍历列表中每个元素,将相邻两个元素相加,并将结果添加到新列表中,最后返回新列表。

编写一个函数largest_subarray_sum,输入参数为一个整数列表,返回值为该列表中任意连续子列表的最大和。例如,输入列表[-2, 1, -3, 4, -1, 2, 1, -5, 4],返回值为6,因为最大子列表为[4, -1, 2, 1],其和为6。

def largest_subarray_sum(nums):
    max_sum = float('-inf')
    current_sum = 0
    for num in nums:
        current_sum += num
        max_sum = max(max_sum, current_sum)
        current_sum = max(current_sum, 0)
    return max_sum

该函数使用了一种称为Kadane算法的技巧,可以在线性时间内找到最大子数组和。具体来说,我们迭代整个数组,并对每个元素求出包含该元素的最大子数组和。我们同时跟踪最大的子数组和,并在迭代过程中更新它。如果当前子数组和变为负数,则我们可以将它重置为零,因为在加上负数之后它只会变得更小,而不会成为最大子数组的一部分。最后,我们返回最大的子数组和。

例如,对于输入列表[-2, 1, -3, 4, -1, 2, 1, -5, 4],我们首先将current_sum设置为0和max_sum设置为负无穷大。在迭代过程中,我们依次考虑元素-2、1、-3、4、-1、2、1、-5和4。首先,我们将current_sum设置为-2,并将max_sum更新为-2。接下来,我们将current_sum设置为1,并将max_sum更新为1。然后,我们将current_sum设置为-2,但因为它比0小,所以我们不更新max_sum。接下来,我们将current_sum设置为4,并将max_sum更新为4。然后,我们将current_sum设置为3,并将max_sum更新为4。接下来,我们将current_sum设置为5,并将max_sum更新为5。然后,我们将current_sum设置为6,并将max_sum更新为6。接下来,我们将current_sum设置为1,但因为它比0小,所以我们不更新max_sum。最后,我们将current_sum设置为5,并将max_sum更新为6。因此,函数返回6,即最大子数组和为6。

字典 - 教他们关于字典的知识,以及如何使用它们存储键-值对

字典是一种可变容器,可以存储键-值对。每个键对应一个值,通过键可以快速查找对应的值。字典可以通过大括号{}或者dict()函数进行创建。字典的键必须是唯一的且不可变的,例如字符串、数字或元组等不可变类型。

以下是一些常用的字典操作:

创建字典:
my_dict = {'name': 'John', 'age': 25, 'city': 'New York'}

访问字典中的值:

name = my_dict['name']
age = my_dict['age']

更新字典中的值:

my_dict['city'] = 'San Francisco'

添加新的键-值对:

my_dict['occupation'] = 'Software Engineer'

删除键-值对:

del my_dict['occupation']

判断某个键是否存在于字典中:

if 'name' in my_dict:
    print('Name exists in the dictionary')

获取所有的键和值:

keys = my_dict.keys()
values = my_dict.values()

获取所有的键值对:

items = my_dict.items()

items = my_dict.items()

清空字典:

my_dict.clear()

使用字典的get方法获取键对应的值,如果键不存在则返回默认值:

age = my_dict.get('age', 0)

使用字典的pop方法删除键-值对,并返回该键对应的值:

age = my_dict.pop('age')

字典也支持嵌套,可以将一个字典作为另一个字典的值,形成嵌套字典。

字典还支持一些其他的方法和操作,例如fromkeys()、copy()、update()等,可以根据需要进行学习和使用。

更深入地介绍字符串,包括字符串操作和格式化

文件输入和输出 - 教他们如何在Python中读写文件

文件输入和输出是Python中非常常见和重要的操作之一,可以用于读取和处理大量的数据,同时也可以将结果写入文件进行存储和分享。以下是一些常见的文件输入输出操作:
打开和关闭文件

在Python中,可以使用open()函数打开一个文件,该函数需要指定文件路径和打开方式(例如只读、只写、追加等),并返回一个文件对象,用于后续的读写操作。例如:

f = open("myfile.txt", "r")  # 打开myfile.txt文件,只读模式

完成文件操作后,需要使用close()方法关闭文件,以释放文件资源并确保所有数据已写入磁盘。例如:

f.close()  # 关闭文件

更好的做法是使用with语句来打开文件,这样可以确保文件在使用完毕后自动关闭,而不需要手动调用close()方法。例如:

with open("myfile.txt", "r") as f:

# 文件操作

读取文件内容

打开文件后,可以使用read()方法读取文件内容,返回一个包含文件内容的字符串。例如:

with open("myfile.txt", "r") as f:
    content = f.read()  # 读取整个文件内容

还可以使用readline()方法逐行读取文件内容,返回一个包含单行文本的字符串。例如:

with open("myfile.txt", "r") as f:
    line = f.readline()  # 读取第一行文本

使用readlines()方法一次性读取所有行,返回一个包含所有文本行的列表。例如:

with open("myfile.txt", "r") as f:
    lines = f.readlines()  # 读取所有文本行

写入文件内容

可以使用write()方法向文件中写入文本内容。例如:

with open("myfile.txt", "w") as f:
    f.write("Hello, world!\n")  # 写入一行文本

还可以使用writelines()方法写入多行文本内容。例如:

with open("myfile.txt", "w") as f:
    f.writelines(["Hello, world!\n", "How are you?\n"])  # 写入多行文本

示例

以下是一个简单的文件读取和写入的示例代码:

with open("input.txt", "r") as input_file, open("output.txt", "w") as output_file:
    for line in input_file:
        line = line.strip()  # 去掉行末的换行符
        words = line.split()  # 将行文本拆分为单词列表
        for word in words:
            if len(word) > 5:
            output_file.write(word + "\n")  # 写入长度大于5的单词

此代码打开一个名为input.txt的文件进行读取,将每一行拆分为单词,并将长度大于5的单词写入名为output_file

另一个重要的方面是学习如何处理不同类型的文件,例如文本文件和二进制文件。Python有许多用于处理不同类型文件的内置函数和库。例如,对于文本文件,可以使用Python的内置open()函数打开文件,并使用read()和write()方法读取和写入文件内容。

对于二进制文件,可以使用Python的open()函数以二进制模式打开文件,并使用read()和write()方法来读取和写入二进制数据。同时,Python也提供了一些专门用于处理二进制数据的库,例如struct和pickle等库。

以下是一个使用open()函数读取和写入文本文件的简单示例:

# 打开一个文本文件
file = open("example.txt", "r")

# 读取文件中的内容
content = file.read()

# 关闭文件
file.close()

# 打开一个新文件,并写入内容
new_file = open("new_file.txt", "w")
new_file.write("This is some new content.")
new_file.close()

这里,我们首先使用open()函数打开一个文本文件,指定文件名和文件打开模式。在这种情况下,我们使用“r”模式来打开文件以进行只读访问。然后,我们使用read()方法读取文件中的内容,并将其存储在一个变量中。最后,我们使用close()方法关闭文件句柄。

接下来,我们使用open()函数创建一个新的文本文件,指定文件名和文件打开模式。在这种情况下,我们使用“w”模式来打开文件以进行写入访问。然后,我们使用write()方法写入一些新的内容,并使用close()方法关闭文件句柄。

当然,这只是一个简单的示例。在实际应用中,可能需要使用其他文件打开模式、读取和写入大量数据、处理不同的文件类型等。在学习文件输入和输出的过程中,最好的方法是实践和实验,以便更好地理解这些概念和工具的用法。

模块和库 – 介绍模块的概念以及如何在Python中使用库。

模块和库是Python中非常重要的概念。模块是一个Python文件,其中包含一些可重用的代码。库是由多个模块组成的集合,可以用来提供各种功能,例如数学运算、文件处理、网络通信等。

在Python中,可以使用import语句来导入模块和库。例如,要导入Python的数学库,可以使用以下语句:

import math

导入库后,就可以使用其中的函数和变量。例如,要计算圆的面积,可以使用math库中的pi常量和pow函数:

import math

r = 2.0
area = math.pi * math.pow(r, 2)
print(area)

输出:12.566370614359172

除了简单的import语句外,还有其他一些导入模块和库的方法。例如,可以使用from语句导入模块中的特定函数或变量:

from math import pi, pow

r = 2.0
area = pi * pow(r, 2)
print(area)

输出:12.566370614359172

另外,也可以使用as关键字给导入的模块或库起一个别名,以方便使用。例如,将math库导入并命名为m:

import math as m

r = 2.0
area = m.pi * m.pow(r, 2)
print(area)

输出:12.566370614359172

总之,模块和库是Python编程中不可或缺的一部分,可以大大提高代码的可重用性和可维护性。

重要的一个库pygame - 编写游戏的图形库
pygame.jpeg

Pygame介绍

Pygame是一个用于开发2D游戏的Python库。它提供了一系列用于游戏开发的工具和函数,可以帮助开发者更快地构建游戏。Pygame具有跨平台性,可以在Windows、Mac OS X和Linux等多个平台上使用。

使用Pygame,开发者可以轻松地创建窗口、绘制图形、播放声音、响应用户输入等功能。它还提供了对位图、声音和视频等多媒体资源的处理功能。开发者可以使用Pygame创建各种类型的游戏,包括平台游戏、射击游戏、角色扮演游戏等等。

下面是一些Pygame的常用功能:

  • 创建和管理游戏窗口
  • 加载和显示图像
  • 绘制几何图形、文本和图像
  • 播放声音和音乐
  • 检测用户输入,如键盘和鼠标事件
  • 控制游戏速度和时间
  • 碰撞检测和物理引擎
  • 简单的人工智能

总之,Pygame是一个非常适合初学者学习游戏开发的Python库,使用Pygame可以让开发者轻松地入门游戏开发,从而更好地理解编程和计算机图形学的相关知识。
pygame介绍

pygame快速入门教程

小时级别入门教程

尝试使用Pygame编写一些完整的小游戏

  • snake game
分解snake game游戏,利用现有的知识构建完整的程序
变量
循环
贪吃蛇游戏的基本逻辑
简单贪吃蛇游戏

第3个月:

• 面向对象编程 - 教他们关于类、对象和方法的知识,以及如何在Python中定义和使用它们。
• 异常处理 - 教他们如何处理代码中的错误和异常。
• 网络爬虫 - 介绍网络爬虫的概念以及如何使用Python从网站上提取数据。
• GUI编程 - 教他们如何使用Python库(如Tkinter)创建简单的图形用户界面。
• 最终项目 - 让他们应用课程中所学的知识来创建一个最终项目,以展示他们对Python的理解。
• 在整个课程中,您可以布置作业和项目,以巩固每个课程中教授的概念。您还可以鼓励他们参加编程挑战或黑客马拉松,以进一步发展他们的编程技能。

面向对象编程

"介绍Python中的面向对象编程,包括类、对象和方法的概念" 给12岁儿童介绍这些概念
面向对象编程是一种编程范式,它将数据和操作数据的方法打包在一起,形成一个称为“类”的结构。类是一个模板,它描述了数据和方法应该如何组合在一起,以便可以创建对象。对象是类的一个实例,它包含了类定义的数据和方法。

在Python中,类是用关键字class定义的。
Python中的面向对象编程(Object-Oriented Programming, OOP)是一种编程范式,通过创建对象来表示现实世界中的实体或概念。在Python中,对象是类的实例,类定义了对象的属性和方法。
下面是一些常见的Python OOP概念:

1. 类(Class):是一种数据类型,用来定义对象的属性和方法。类是创建对象的蓝图。
2. 对象(Object):是类的实例,具有类定义的属性和方法。
3. 属性(Attribute):是类中定义的变量,用于存储对象的数据。
4. 方法(Method):是类中定义的函数,用于操作对象的数据。
5. 继承(Inheritance):是一种创建新类的方式,通过从现有类继承属性和方法来创建新类。
6. 多态(Polymorphism):是一种使用相同的方法名,但根据对象类型执行不同的操作的能力。
7. 封装(Encapsulation):是将对象的属性和方法封装在一起的能力,以隐藏对象的实现细节,并提供访问对象的公共接口。

Python的OOP编程支持所有这些概念,使得开发者可以利用面向对象的优势来组织和管理代码,提高代码的复用性和可维护性。

编程范式是一种编程方法和理念的总称,是一种特定的编程风格或编程思想,它规定了程序的组织方式、处理数据的方法和编写代码的风格等。常见的编程范式包括面向过程编程(Procedural Programming)、面向对象编程(Object-Oriented Programming)、函数式编程(Functional Programming)等。不同的编程范式在程序设计思想、编码规范、开发效率和程序性能等方面都有不同的特点和优劣,选择合适的编程范式可以提高程序的质量和效率。

当涉及到OOP时,一个好的方式是使用一个具有现实意义的例子。下面是一个描述动物和它们的属性和行为的例子,以便演示Python中的类和对象的使用方法:

动物类

class Animal:
    def __init__(self, name, species, age):
        self.name = name
        self.species = species
        self.age = age

    def describe(self):
        print(f"{self.name} is a {self.species} and is {self.age} years old.")

    def make_sound(self):
        pass

class Dog(Animal):
    def __init__(self, name, age, breed):
        super().__init__(name, 'dog', age)
        self.breed = breed

    def describe(self):
        print(f"{self.name} is a {self.breed} and is {self.age} years old.")

    def make_sound(self):
        print("Bark bark!")

class Cat(Animal):
    def __init__(self, name, age, color):
        super().__init__(name, 'cat', age)
        self.color = color

    def describe(self):
        print(f"{self.name} is a {self.color} {self.species} and is {self.age} years old.")

    def make_sound(self):
        print("Meow meow!")

my_dog = Dog("Buddy", 3, "Golden Retriever")
my_cat = Cat("Fluffy", 2, "Black")


my_dog.describe()
# Output: Buddy is a Golden Retriever and is 3 years old.

my_dog.make_sound()
# Output: Bark bark!

my_cat.describe()
# Output: Fluffy is a Black cat and is 2 years old.

my_cat.make_sound()
# Output: Meow meow!

通过这些代码,我们可以看到Python中的OOP概念如何应用于具体的示例,包括类、对象、属性、方法、继承、多态和封装。

学习编程最好的方式是透过练习

购物车例子

以下是一个例子,可以用来练习OOP概念。这个例子模拟一个简单的购物车程序。
要求学生按照以下步骤完成:

1. 定义一个Product类,具有名称、价格和数量属性。还要定义一个方法total_cost(),用于计算商品的总价值(即价格 * 数量)。
2. 定义一个ShoppingCart类,具有一个实例属性items,其中保存购物车中的商品。还要定义以下方法:
• add_item(product, quantity),将给定数量的商品添加到购物车中。
• remove_item(product),从购物车中删除指定的商品。
• total_cost(),计算购物车中所有商品的总价值。
• display_cart(),显示购物车中所有商品的名称、价格、数量和总价值。

class Product:
    def __init__(self, name, price, quantity):
        self.name = name
        self.price = price
        self.quantity = quantity

    def total_cost(self):
        return self.price * self.quantity

class ShoppingCart:
    def __init__(self):
        self.items = []

    def add_item(self, product, quantity):
        for item in self.items:
            if item['product'].name == product.name:
                item['quantity'] += quantity
                return
        self.items.append({'product': product, 'quantity': quantity})

    def remove_item(self, product):
        for item in self.items:
            if item['product'].name == product.name:
                self.items.remove(item)
                return

    def total_cost(self):
        total = 0
        for item in self.items:
            total += item['product'].total_cost()
        return total

    def display_cart(self):
        print("Shopping Cart:")
        for item in self.items:
            print(f"{item['product'].name} - {item['product'].price:.2f} x {item['quantity']} = {item['product'].total_cost():.2f}")
        print(f"Total cost: $ {self.total_cost():.2f}")

# testing code
# 创建一些产品
p1 = Product("Apple", 0.50, 5)
p2 = Product("Banana", 0.25, 10)
p3 = Product("Orange", 0.75, 2)

# 创建一个购物车
cart = ShoppingCart()

# 添加一些商品到购物车
cart.add_item(p1, 3)
cart.add_item(p2, 5)
cart.add_item(p3, 1)
cart.add_item(p1, 2)

# 显示购物车中的商品
cart.display_cart()

# 从购物车中删除一个商品
cart.remove_item(p2)

# 显示购物车中的商品
cart.display_cart()

ATM存款例子

以下是一个使用OOP编程实现银行ATM存款的例子,具体功能包括:

1. 用户可以登录到他们的帐户
2. 用户可以查询他们的余额
3. 用户可以向他们的帐户存入一定金额
4. 用户可以从他们的帐户中取出一定金额

class Account:
    def __init__(self, name, account_number, balance):
        self.name = name
        self.account_number = account_number
        self.balance = balance

    def deposit(self, amount):
        self.balance += amount
        print(f"Deposit of {amount} successful. New balance is {self.balance}")

    def withdraw(self, amount):
        if self.balance >= amount:
            self.balance -= amount
            print(f"Withdrawal of {amount} successful. New balance is {self.balance}")
        else:
            print("Insufficient balance")

    def get_balance(self):
        print(f"Your account balance is {self.balance}")

class ATM:
    def __init__(self):
        self.accounts = {}

    def add_account(self, account):
        self.accounts[account.account_number] = account

    def login(self, account_number):
        if account_number in self.accounts:
            return self.accounts[account_number]
        else:
            return None
#testing code

atm = ATM()

# 添加一些账户
account1 = Account("Alice", "123456", 1000)
account2 = Account("Bob", "654321", 500)
atm.add_account(account1)
atm.add_account(account2)

# 用户登录
account = None
while not account:
    account_number = input("Enter your account number: ")
    account = atm.login(account_number)
    if not account:
        print("Invalid account number")

# 显示余额并进行存款和取款操作
account.get_balance()
account.deposit(200)
account.withdraw(700)
account.get_balance()
当用户输入正确的帐户号码后,程序将输出其余额,然后用户可以进行存款和取款操作。存款和取款操作都将更新账户余额,并显示新的余额。

输出结果:

Enter your account number: 123456
Your account balance is 1000
Deposit of 200 successful. New balance is 1200
Withdrawal of 700 successful. New balance is 500
Your account balance is 500
上面的代码其实有些bug,比如如果重复添加一样的账号,后面的会覆盖前面的,实际应用中代码是不允许的,必须有对应的异常处理, how to fix?

学生类

创建一个学生类,包括属性(例如姓名、年龄、成绩)和方法(例如学习、休息、参加考试)。然后创建几个不同的学生对象,并调用它们的方法,例如计算他们的平均成绩。给出python代码

class Student:
    def __init__(self, name, age, grades):
        self.name = name
        self.age = age
        self.grades = grades

    def study(self):
        print(f"{self.name} is studying.")

    def rest(self):
        print(f"{self.name} is taking a break.")

    def take_exam(self):
        print(f"{self.name} is taking an exam.")

    def get_average_grade(self):
        return sum(self.grades) / len(self.grades)

# 创建几个不同的学生对象
student1 = Student("Alice", 18, [80, 90, 70])
student2 = Student("Bob", 19, [85, 80, 95])
student3 = Student("Charlie", 20, [90, 85, 80])

# 调用它们的方法
student1.study()
student2.rest()
student3.take_exam()

# 计算平均成绩
average_grade = (student1.get_average_grade() + student2.get_average_grade() + student3.get_average_grade()) / 3
print(f"The average grade is {average_grade}.")

另一个汽车类例子

创建一个简单的汽车类,包括属性(例如品牌、型号、颜色、价格)和方法(例如启动、加速、刹车)。然后创建几辆不同的汽车对象,并调用它们的方法。

class Car:
    def __init__(self, brand, model, color, price):
        self.brand = brand
        self.model = model
        self.color = color
        self.price = price
        self.is_running = False
        self.speed = 0

    def start(self):
        self.is_running = True
        print(f"The {self.brand} {self.model} is starting.")

    def accelerate(self, speed):
        if not self.is_running:
            print(f"The {self.brand} {self.model} is not running.")
            return

        self.speed += speed
        print(f"The {self.brand} {self.model} is accelerating to {self.speed} km/h.")

    def brake(self):
        if not self.is_running:
            print(f"The {self.brand} {self.model} is not running.")
            return

        self.speed = 0
        print(f"The {self.brand} {self.model} is braking and stops.")

# 创建几辆不同的汽车对象
car1 = Car("BMW", "X5", "Black", 1000000)
car2 = Car("Tesla", "Model S", "Red", 1500000)
car3 = Car("Toyota", "Camry", "White", 500000)

# 调用它们的方法
car1.start()
car1.accelerate(80)
car1.accelerate(100)
car1.brake()

car2.start()
car2.accelerate(120)
car2.brake()

car3.start()
car3.accelerate(60)
car3.brake()

以上代码创建了一个汽车类,包括品牌、型号、颜色、价格等属性和启动、加速、刹车等方法。然后创建了三辆不同的汽车对象,并调用了它们的方法。每个汽车对象都可以启动、加速、刹车。

输出结果:

The BMW X5 is starting.
The BMW X5 is accelerating to 80 km/h.
The BMW X5 is accelerating to 180 km/h.
The BMW X5 is braking and stops.
The Tesla Model S is starting.
The Tesla Model S is accelerating to 120 km/h.
The Tesla Model S is braking and stops.
The Toyota Camry is starting.
The Toyota Camry is accelerating to 60 km/h.
The Toyota Camry is braking and stops.

总之,编程范式是一种编程方法和理念的总称,是一种特定的编程风格或编程思想,它规定了程序的组织方式、处理数据的方法和编写代码的风格等。常见的编程范式包括面向过程编程(Procedural Programming)、面向对象编程(Object-Oriented Programming)、函数式编程(Functional Programming)等。不同的编程范式在程序设计思想、编码规范、开发效率和程序性能等方面都有不同的特点和优劣,选择合适的编程范式可以提高程序的质量和效率。

使用OOP面向对象改写snake game

涉及三个类:SnakeGame, Snake, Food

使用oop重构snake game


my_game = SnakeGame()
my_game.play()

三个类相互交互构成完整游戏,如果我们将这些类实现隐藏在单独的一个模块里面比如snakegame.py
基于这个我们要实现一个贪吃蛇游戏,可以这么编写:

from snakegame import SnakeGame
my_game = SnakeGame()
my_game.play()

看,简单的三行代码,就能实现一个简单的贪吃蛇游戏,更多细节被封装在独立的模块里面,这就是程序抽象、封装的好处,这里没有考虑扩展性,如果引入扩展性,就可以应对更复杂的使用场景,比如是否支持不同游戏等级,是否可以支持游戏计分,是否支持多人同时玩游戏等...

拓展练习:
pygame显示中文,标题,比分
记录历史比分
增加蛇的眼睛

中文显示:

使用系统支持中文的字体,可以透过下面代码,查看系统支持中文的字体,选择一个支持的中文字体:

fonts = pygame.font.get_fonts()
print(fonts)
有时系统没有中文字体,我们可以将使用的中文字体和程序打包在一起分发给用户使用

记录历史比分

最直观的是文件操作(Todo)

添加蛇的眼睛

使用pygame绘制圆

pygame.draw.circle()

在上面Snake类的draw函数里面增加绘制圆的代码,主要是确定两只眼睛的坐标,分水平移动和上下移动:

head = self.body[0]
head_x = head[0] * self.cell_size
head_y = head[1] * self.cell_size

if self.direction == "LEFT" or self.direction == "RIGHT":
    eye1_pos = head_x + self.cell_size // 2, head_y + self.cell_size // 4
    eye2_pos = head_x + self.cell_size // 2, head_y + 3* self.cell_size // 4
elif self.direction == "UP" or self.direction == "DOWN":
    eye1_pos = head_x + self.cell_size // 4, head_y + self.cell_size // 2
    eye2_pos = head_x + 3* self.cell_size // 4, head_y + self.cell_size // 2
else:
    pass
pygame.draw.circle(self.screen, (0, 0, 0), eye1_pos, 4)
pygame.draw.circle(self.screen, (0, 0, 0), eye2_pos, 4)

运行时发现,只有水平方向移动的时候,眼睛位置正确,但是垂直移动的时候发现蛇的眼睛没有变化过来
后来发现Snake自身的direction属性没有更新,一直是默认的“RIGHT”,修改Snake的move方法:

def move(self, direction):

head = self.body[0]
if direction == "RIGHT":
    new_head = (head[0] + 1, head[1])
elif direction == "LEFT":
    new_head = (head[0] - 1, head[1])
elif direction == "UP":
    new_head = (head[0], head[1] - 1)
elif direction == "DOWN":
    new_head = (head[0], head[1] + 1)
self.body.insert(0, new_head)
self.body.pop()
self.direction = direction # 前面代码漏了这一行

异常处理try/except/finally

Python中的异常处理机制是用于在程序运行时处理错误或异常情况的一种方式。它可以让程序在出现异常时不会崩溃,并能够提供更好的错误提示和处理方法。下面是介绍Python中的异常处理,包括try/except语句和finally语句
1. try/except语句

try/except语句是Python中处理异常的一种方式。它的基本结构如下:

    try:
    # 可能会出现异常的代码块
except ExceptionType:
    # 出现指定类型的异常时执行的代码块

其中,try代码块中包含可能会出现异常的代码,如果try代码块中的代码出现了指定类型的异常,那么就会执行except代码块中的代码。如果没有出现指定类型的异常,那么就会跳过except代码块,继续执行程序。
以下是一个例子,展示如何使用try/except语句来处理除以0的异常:

try:
    a = 10 / 0
except ZeroDivisionError:
    print("除数不能为0!")

finally语句
finally语句是Python中用于在try/except语句结束后执行清理工作的一种方式。它的基本结构如下:

try:
    # 可能会出现异常的代码块
except ExceptionType:
    # 出现指定类型的异常时执行的代码块
finally:
    # 不管有没有出现异常,都会执行的代码块

以下是一个例子,展示如何使用try/except/finally语句来处理文件的读写异常:

try:
    f = open("file.txt", "r")
    # 对文件进行读写操作
except FileNotFoundError:
    print("文件不存在!")
finally:
    f.close()

在上面的例子中,如果文件不存在,就会执行except代码块中的代码,如果文件存在,就会执行try代码块中的代码。无论如何,都会执行finally代码块中的代码来关闭文件。

try:
    a = 10 / 0
except ZeroDivisionError:
    print("除数不能为0!")

这个例子中,我们在try语句块中执行了一个除零操作,这会引发一个ZeroDivisionError异常。如果这个异常出现了,就会执行except语句块中的代码,打印出"除数不能为0!"的信息。

3. 处理键不存在异常


my_dict = {"key1": 1, "key2": 2}

try:
    value = my_dict["key3"]
except KeyError:
    print("这个键不存在!")


在这个例子中,我们创建了一个包含两个键值对的字典my_dict。然后我们尝试访问一个不存在的键"key3",这会抛出一个KeyError异常。如果这个异常出现了,就会执行except语句块中的代码,打印出"这个键不存在!"的信息。

小练习:

处理用户输入的错误

while True:
    try:
        num = int(input("请输入一个整数:"))
        break
    except ValueError:
        print("请输入一个有效的整数!")
print("你输入的数字是:", num)



在这个程序中,我们要求用户输入一个整数,并使用try/except块对用户输入进行处理。如果用户输入的不是整数,就会抛出一个ValueError异常,程序会输出错误信息并要求用户重新输入。如果输入的是一个整数,程序会打印出这个数字。

处理网络连接异常

import requests

try:

response = requests.get("http://www.example.com")
response.raise_for_status()

except requests.exceptions.HTTPError as errh:

print("HTTP错误:", errh)

except requests.exceptions.ConnectionError as errc:

print("连接错误:", errc)

except requests.exceptions.Timeout as errt:

print("超时错误:", errt)

except requests.exceptions.RequestException as err:

print("未知错误:", err)

else:

print("响应内容:", response.content)

在这个程序中,我们尝试连接一个URL,并对网络连接异常进行处理。如果出现HTTP错误、连接错误、超时错误或其他未知错误,程序都会输出相应的错误信息。如果能够正常连接并获得响应,程序会输出响应内容。

给snake增加历史高分记录

文件操作,记录上一次的最高分
程序逻辑:

  • 程序初始化的时候,读取文件,获取上一次最高的分
  • 游戏结束的时候,比较当前的分与历史最高的分
  • 如果大于上一次最高分,则该最高分保存到文件high_score.txt文件

代码变更

    # 加载历史最高分
    def load_high_score(self):
        with open("high_score.txt", "r") as f:
            lines = f.readlines()
            for line in lines:
                print(line)
            f.close()
        try:
            self.high_score = int(lines[0])
        except:
            print('invalid score')

    # 保存当前最高分
    def save_high_score(self):
        with open("high_score.txt", "w") as f:
            f.write(f"{self.high_score}")
# play函数,最开始初始化游戏的时候,加载历史最高分

self.load_high_score()

显示最高分

    def draw_score(self):
        high_score_text = self.score_font.render(f'Top: {self.high_score}', True, (255, 255, 255))
        self.screen.blit(high_score_text, (SnakeGame.SCREEN_WIDTH, 100))


        score_text = self.score_font.render(f'{self.score_text}: {self.score}', True, (255, 255, 255))
        self.screen.blit(score_text, (SnakeGame.SCREEN_WIDTH, 200))

退出游戏的时候

        pygame.quit()
        if int(self.score) > self.high_score:
            self.high_score = int(self.score)
            self.save_high_score()

special program for Mother's Day

import turtle
t=turtle.Turtle()
s=turtle.Screen()
s.setup(850,800)
s.bgcolor('black')
t.color('violet')
t.begin_fill()
t.penup()

t.left(110)
t.fd(50)
t.pendown()
t.speed(0)
t.circle(30)
t.penup()
t.backward(150)
t.pendown()
t.lt(10)
t.fd(90)
t.lt(50)
t.fd(10)
t.lt(10)
t.fd(58)
t.lt(70)
t.fd(90)
t.lt(90)
t.fd(20)
t.lt(90)
t.fd(70)
t.rt(80)
t.fd(6)
t.rt(99)
t.fd(130)
t.lt(105)
t.fd(30)
t.rt(85)
t.fd(80)
t.lt(90)
t.fd(20)
t.lt(90)
t.fd(80)
t.rt(90)
t.fd(30)
t.rt(90)
t.fd(80)
t.lt(90)
t.fd(20)
t.lt(90)
t.fd(80)
t.rt(90)
t.fd(30)
t.lt(110)
t.fd(130)
t.rt(99)
t.fd(6)
t.rt(80)
t.fd(67)
t.lt(88)
t.fd(25)
t.end_fill()

t.penup()
t.goto(-140,85)
t.pendown()
t.color('yellow')
t.write("HAPPY",align="center",font=("arial",49,"bold"))
t.penup()
t.goto(-110,-10)
t.pendown()
t.color('lightblue')
t.write("M",align="center",font=("arial",59,"bold"))
t.penup()
t.goto(-10,-10)
t.pendown()
t.color('lightblue')
t.write("THER'S",font=("arial",49,"bold"))
t.penup()
t.goto(65,-111)
t.pendown()
t.color('red')
t.write("DAY",font=("arial",49,"bold"))
t.penup()
t.goto(-205,-120)
t.pendown()
t.color("yellow","tomato")
t.begin_fill()
for i in range(60):
    t.fd(100)
    t.lt(165)
t.end_fill()
t.penup()
t.goto(-185,5)
t.pendown()
t.color("red","green")
t.begin_fill()
for i in range(60):
    t.fd(85)
    t.lt(165)
t.end_fill()

t.penup()
t.goto(-310,29)
t.pendown()
t.color("blue","magenta")
t.begin_fill()
for i in range(60):
    t.fd(70)
    t.lt(165)
t.end_fill()
t.penup()
t.goto(-300,120)
t.pendown()
t.color("yellow","cyan")
t.begin_fill()
for i in range(60):
    t.fd(55)
    t.lt(165)
t.end_fill()
t.color('cyan')
t.penup()
t.goto(75,-170)
t.pendown()
t.write("Thinking Of you,",font=("italic",19))
t.penup()
t.goto(75,-230)
t.pendown()
t.write("And Hoping You,",font=("arial",19))
t.penup()
t.goto(75,-260)
t.pendown()
t.write("Have a beautiful day,",font=("arial",19))
t.penup()
t.goto(75,-290)
t.pendown()
t.write("From The Staff of",font=("arial",19))
t.penup()
t.goto(75,-330)
t.pendown()
t.color('yellow')
t.write("Geekedu!!!!!",font=("arial",21))
t.width(10)
t.penup()
t.fd(200)
t.lt(69)
t.fd(470)

t.pendown()
t.color("blue","maroon")
t.begin_fill()
t.rt(90)
t.circle(55)
t.lt(180)
t.circle(90)
t.end_fill()
t.color('maroon')
t.begin_fill()
t.lt(90)
t.fd(70)
t.rt(150)
t.fd(20)
t.lt(90)
t.fd(50)
t.end_fill()
t.color('black')
t.write("MAY",font=("verdana",24,"bold"))
t.hideturtle()
turtle.exitonclick()

网络爬虫初步

  • 透过requets获取网络数据
  • API

例子httpcat API使用

httpcat是个有趣的免费API,根据输入的http status code,返回一张cat图片
参考详细内容

GUI入门-PyQt6

介绍一下构建GUI(Graphic User Interface)图形用户界面应用
PyQt6 是一个用于创建桌面应用程序的 Python GUI 工具包。它是 PyQt 库的最新版本,提供了许多强大的功能和工具,用于开发功能丰富的图形用户界面。PyQt6 基于 Qt 库,Qt 是一个跨平台的应用程序开发框架,可以用于开发 Windows、macOS、Linux 等多个操作系统上的应用程序。
参考详细内容

使用PyQt6实现简单的贪吃蛇

基本实现来自前面pygame的snake实现,只是在游戏界面的初始化和游戏界面渲染部分使用PyQt6特有的组件实现,移动、碰撞处理、蛇身体增长,几乎一样

参考详细内容

复习与练习

猜数字-程序给出1~100之间的一个秘密数字,用户根据大小提示以最少次数猜出来

import random

def guess_number():
    secret_number = random.randint(1, 100)  # 生成一个1到100之间的随机数
    attempts = 0

    while True:
        user_guess = int(input("猜一个1到100之间的数字:"))
        attempts += 1

        if user_guess < secret_number:
            print("太小了,请再试一次。")
        elif user_guess > secret_number:
            print("太大了,请再试一次。")
        else:
            print(f"恭喜你,猜对了!你用了{attempts}次猜中了答案。")
            break

guess_number()

简易计算器

控制台形式的计算器,支持四则运算

def add(x, y):
    return x + y

def subtract(x, y):
    return x - y

def multiply(x, y):
    return x * y

def divide(x, y):
    if y != 0:
        return x / y
    else:
        return "错误:除数不能为零"

print("欢迎使用简易计算器!")

while True:
    print("请选择要进行的操作:")
    print("1. 相加")
    print("2. 相减")
    print("3. 相乘")
    print("4. 相除")
    print("5. 退出")

    choice = input("请输入操作的编号:")

    if choice == '5':
        print("谢谢使用,再见!")
        break

    num1 = float(input("请输入第一个数字:"))
    num2 = float(input("请输入第二个数字:"))

    if choice == '1':
        result = add(num1, num2)
        print(f"结果:{result}")
    elif choice == '2':
        result = subtract(num1, num2)
        print(f"结果:{result}")
    elif choice == '3':
        result = multiply(num1, num2)
        print(f"结果:{result}")
    elif choice == '4':
        result = divide(num1, num2)
        print(f"结果:{result}")
    else:
        print("无效的选择,请重新输入。")

todo任务列表

tasks = []
completed_tasks = []
def show_menu():
    print("ToDo 清单应用")
    print("1. 显示任务列表")
    print("2. 添加任务")
    print("3. 完成任务")
    print("4. 显示已经完成的任务列表")
    print("5. 退出")

def show_tasks():
    if len(tasks) == 0:
        print("没有任务。")
    else:
        for i, task in enumerate(tasks):
            print(f"{i+1}. {task}")
def show_completed_task():
    if len(completed_tasks) == 0:
        print("没有完成过任务。")
    else:
        for i, task in enumerate(completed_tasks):
            print(f"{i+1}. {task}")

def add_task():
    task = input("请输入任务:")
    tasks.append(task)
    print("任务已添加。")

def complete_task():
    show_tasks()
    task_index = int(input("请输入要完成的任务的编号:"))
    
    if 1 <= task_index <= len(tasks):
        completed_task = tasks.pop(task_index - 1)
        print(f"任务 '{completed_task}' 已完成。")
        completed_tasks.append(completed_task)
    else:
        print("无效的任务编号。")

while True:
    show_menu()
    choice = input("请选择操作:")

    if choice == '1':
        show_tasks()
    elif choice == '2':
        add_task()
    elif choice == '3':
        complete_task()
    elif choice == '4':
        show_completed_task()
    elif choice == '5':
        print("谢谢使用,再见!")
        break
    else:
        print("无效的选择,请重新输入。")

根据game loop模式重构上面的程序

游戏循环模式
使用游戏循环模式重构猜数字游戏
猜数字游戏重构

如法炮制,可以将上面的程序看作是循环的游戏,重新组织代码:
基本上所有的程序都遵循这一模式:

初始化
循环开始:
  - 处理程序输入
  - 更新程序状态
  - 显示程序状态
第一次看到这样的代码重构,可能有些困惑,看起来功能一样,但是代码行数倒是增加了一些,有什么好处?
遵循模式的使用强迫你考虑可能没有想到的问题。例如,在创建“猜数字”游戏时,将用户输入、数据更新和渲染分开可能不是首先想到的。然而,根据经验丰富的开发者的说法,这种分离是至关重要的。所以,作为初学者,我们现在遵循这个建议,以后会理解它为什么重要。并且请相信我:当你理解了这些想法背后的所有精妙之处时,你会感到惊叹不已!

拓展:天气应用-使用网络API获取指定城市天气信息

import requests

def get_weather(city):
    api_key = '6a645a2f6bd3be51f5a30b36c3577a81'  # 替换为你的API密钥
    url = f'http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric'

    response = requests.get(url)
    data = response.json()

    if data['cod'] == 200:
        weather_description = data['weather'][0]['description']
        temperature = data['main']['temp']
        humidity = data['main']['humidity']
        wind_speed = data['wind']['speed']

        print(f"天气情况:{weather_description}")
        print(f"温度:{temperature}°C")
        print(f"湿度:{humidity}%")
        print(f"风速:{wind_speed} m/s")
    else:
        print("无法获取天气信息,请检查城市名称是否正确。")

city = input("请输入城市名称:")
get_weather(city)

黑白棋 - 另一个pygame小游戏

import pygame
import sys

# 游戏参数
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
BOARD_SIZE = 8
CELL_SIZE = SCREEN_HEIGHT // BOARD_SIZE

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 128, 0)


def create_board():
    board = [[' ' for _ in range(BOARD_SIZE)] for _ in range(BOARD_SIZE)]
    board[3][38] = 'W'
    board[3][39] = 'B'
    board[4][40] = 'B'
    board[4][41] = 'W'
    return board


def draw_board(screen, board, player):
    screen.fill(GREEN)

    for row in range(BOARD_SIZE):
        for col in range(BOARD_SIZE):
            pygame.draw.rect(screen, BLUE, (col * CELL_SIZE, row * CELL_SIZE, CELL_SIZE, CELL_SIZE))

            
            if board[row][col] == 'W':
                pygame.draw.circle(screen, WHITE,
                                   (col * CELL_SIZE + CELL_SIZE // 2, row * CELL_SIZE + CELL_SIZE // 2),
                                   CELL_SIZE // 2 - 4)
                
            elif board[row][col] == 'B':
                pygame.draw.circle(screen, BLACK,
                                   (col * CELL_SIZE + CELL_SIZE // 2, row * CELL_SIZE + CELL_SIZE // 2),
                                   CELL_SIZE // 2 - 4)
    if player == 'W':
        pygame.draw.circle(screen, WHITE,
                                   (540, 80),
                                   CELL_SIZE // 2 - 4)
    else:
        pygame.draw.circle(screen, BLACK,
                                   (540, 80),
                                   CELL_SIZE // 2 - 4)

    pygame.display.flip()


def is_valid_move(board, row, col, player):
    if board[row][col] != ' ':
        return False

    other_player = 'B' if player == 'W' else 'W'
    directions = [(0, -1), (0, 1), (-1, 0), (1, 0),
                  (-1, -1), (-1, 1), (1, -1), (1, 1)]

    for drow, dcol in directions:
        r, c = row, col
        r += drow
        c += dcol

        if (0 <= r < BOARD_SIZE) and (0 <= c < BOARD_SIZE) and (board[r][c] == other_player):
            r += drow
            c += dcol

            while (0 <= r < BOARD_SIZE) and (0 <= c < BOARD_SIZE):
                if board[r][c] == player:
                    return True
                elif board[r][c] == ' ':
                    break
                r += drow
                c += dcol

    return False


def make_move(board, row, col, player):
    if not is_valid_move(board, row, col, player):
        return False

    other_player = 'B' if player == 'W' else 'W'
    board[row][col] = player
    directions = [(0, -1), (0, 1), (-1, 0), (1, 0),
                  (-1, -1), (-1, 1), (1, -1), (1, 1)]

    for drow, dcol in directions:
        r, c = row, col
        r += drow
        c += dcol

        if (0 <= r < BOARD_SIZE) and (0 <= c < BOARD_SIZE) and (board[r][c] == other_player):
            r += drow
            c += dcol
            flip_list = []

            while (0 <= r < BOARD_SIZE) and (0 <= c < BOARD_SIZE):
                if board[r][c] == player:
                    for flip_row, flip_col in flip_list:
                        board[flip_row][flip_col] = player
                    break
                elif board[r][c] == ' ':
                    break
                else:
                    flip_list.append((r, c))
                r += drow
                c += dcol

    return True


def is_game_over(board):
    for row in range(BOARD_SIZE):
        for col in range(BOARD_SIZE):
            if board[row][col] == ' ':
                return False
    return True


def count_pieces(board):
    black_count = 0
    white_count = 0
    for row in range(BOARD_SIZE):
        for col in range(BOARD_SIZE):
            if board[row][col] == 'B':
                black_count += 1
            elif board[row][col] == 'W':
                white_count += 1
    return black_count, white_count


def main():
    pygame.init()
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption("黑白棋游戏")
    clock = pygame.time.Clock()

    board = create_board()
    current_player = 'B'

    while not is_game_over(board):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

            if event.type == pygame.MOUSEBUTTONDOWN:
                mouse_x, mouse_y = pygame.mouse.get_pos()
                col = mouse_x // CELL_SIZE
                row = mouse_y // CELL_SIZE

                if make_move(board, row, col, current_player):
                    current_player = 'W' if current_player == 'B' else 'B'

        draw_board(screen, board, current_player)
        black_count, white_count = count_pieces(board)
        pygame.display.set_caption(f"黑棋: {black_count}  白棋: {white_count}")

        pygame.display.flip()
        clock.tick(60)

    black_count, white_count = count_pieces(board)
    pygame.display.set_caption(f"黑棋: {black_count}  白棋: {white_count}")

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()


if __name__ == '__main__':
    main()

最新黑白棋实现参考详细内容

Flask网络应用 - 天气应用

使用Flask框架构建一个简单的天气网络应用,获取指定城市的天气信息

需要安装flask
pip install flask -i https://pypi.tuna.tsinghua.edu.cn/simple
openweathermap 免费的API服务,获取API_KEY
  • 新建一个目录比如weather_app
  • 在该目录下面再建一个子目录templates
  • 在目录weather_app下面新建文件weather_app.py,内容如下:

参考详细内容

主题:最终项目

学习目标:

应用课程中所学的知识来创建一个完整的项目
练习解决实际问题的能力
展示对Python的深入理解和技能
任务:

给学生时间来思考和设计一个自己的项目,可以是一个小型应用程序、一个游戏或一个工具。
鼓励学生在项目中应用课程中所学的知识,例如面向对象编程、异常处理、网络爬虫和GUI编程。
在班级中展示学生的项目,并鼓励同学们提供反馈和建议。

总结(update 2023-05-13)

宏观层面:

  • 初学者对于语言的介绍不用太多关注,快速安装好开发环境即可
  • 学习就是要注意熟悉各种pattern,能够举一反三
  • 程序离不开存储、执行,目前主流的编程语言离不开:数据类型、变量、各种运算符操作以及执行控制
  • Python 丰富的生态,各种三方库,可以快速实现一个复杂问题的解决方案
  • 强大的语言是能够让用户很自然表达解决问题的方案

微观层面:

  • Python的基础语法,稍微练习几次就能熟练掌握;重点掌握基础数据类型的使用,list, dict等
  • 针对特定应用,掌握必要的第三方库,比如编写2D game,可以使用Pygame; 网络数据抓取选择request以及其他相关的库;GUI图形用户节目程序开发推荐PyQt库;Machine Learning生态也是很丰富
  • 同一类型问题,多编写几个程序实践一下,尽量少拷贝粘贴,自行输入代码
  • 有一定programming基础可以更多了解高阶的主题,有两个方向:特定问题域的深入;更一般性计算机科学的学习

课程小结:

  • 第一课:语言介绍,基础数据类型和变量以及一些常规操作
  • 第二课:输入与输出,字符串格式化输出
  • 第三课:语句,执行控制,条件,循环
  • 第四课:python list, dict的等数据类型使用,文件读写操作
  • 第五课:python三方库使用,import等关键字,pygame简单演示,文字、图片、播放wav,mp3等
  • 第六课:snake game分解,pygame基础游戏编写结构分析,snakegame游戏逻辑分解(基于过程的编程范式)
  • 第七课:OOP面向对象初步,介绍class的基本概念,可以用class 建模现实的一些概念,比如animal,student,
    bank账户等; 将sanke game用OOP编程方式改写,大部分代码复用
  • 第八课:目标是异常处理入门,snake game加入一些额外的功能,计分; 有时间初级一些网络数据抓取,API使用
  • 第九课:GUI图形用户程序开发初步,重点推荐PyQt6,可以实现一个比较简单的例子? 还可以提及多线程概念
  • 第十课:课程小结,选个主题练习编写一个中等复杂程度的应用,课后自行再不断完善?

额外内容:pgzero 配置环境

参考详细内容

额外练习:完善黑白棋

增加翻转棋子的功能
修改make_move函数,判断需要翻转的棋子,加入到list里面,然后设置一个便利flipped
鼠标点击的时候,判断是否flipped,则重新绘制draw_board
增加棋盘上的格子线
使用pygame.color函数定义一些常量
参考详细内容

python入门测试题

https://zhuanlan.zhihu.com/p/87891142
https://blog.csdn.net/Dream_Gao1989/article/details/114590217
https://zhuanlan.zhihu.com/p/87894542
https://www.runoob.com/python/python-100-examples.html
入门问答

不断小结

  • 解决问题的能力,分析复杂问题到最小可解决的部分