├── 01.Python的起源.md ├── 01_Python基础 ├── ch_01_hello.py ├── ch_02_注释.py ├── ch_03_个人信息.py ├── ch_04_买苹果.py ├── ch_05_买苹果改进.py └── ch_06_格式化字符串.py ├── 02.第一个Python程序.md ├── 02_分支 ├── ch_01_判断年龄.py ├── ch_02_判断年龄改进版.py ├── ch_03_逻辑运算演练.py ├── ch_04_女友的节日.py ├── ch_05_火车站案件.py └── ch_06_石头剪刀布.py ├── 03.Python基础.md ├── 03_循环 ├── ch_01_循环.py ├── ch_02_程序计数.py ├── ch_03_累加求和.py ├── ch_04_累加求和进阶版.py ├── ch_05_break.py ├── ch_06_continue.py ├── ch_07_打印小星星.py ├── ch_08_print函数的结尾.py ├── ch_09_嵌套打印小星星.py ├── ch_10_九九乘法表.py └── ch_11_转义字符.py ├── 04.程序执行原理.md ├── 04_函数 ├── __pycache__ │ ├── ch_01_九九乘法表.cpython-38.pyc │ └── ch_10_分隔线模块.cpython-38.pyc ├── ch_01_九九乘法表.py ├── ch_02_快速体验.py ├── ch_03_第一个函数.py ├── ch_04_第一个函数改造.py ├── ch_05_函数的参数.py ├── ch_06_函数的返回值.py ├── ch_07_函数的嵌套调用.py ├── ch_08_打印分割线.py ├── ch_09_打印多条分隔线.py ├── ch_10_体验模块.py └── ch_10_分隔线模块.py ├── 05.变量的使用.md ├── 05_高级数据类型 ├── ch_01_列表基础使用.py ├── ch_02_del 关键字.py ├── ch_03_列表的数据统计.py ├── ch_04_列表排序.py ├── ch_05_列表遍历.py ├── ch_06_元组基本使用.py ├── ch_07_元组遍历.py ├── ch_08_格式化字符串.py ├── ch_09_字典的定义.py ├── ch_10_字典基本使用.py ├── ch_11_字典的其他操作.py ├── ch_12_字典的遍历.py ├── ch_13_字典的应用场景.py ├── ch_14_字符串定义和遍历.py ├── ch_15_字符串统计操作.py ├── ch_16_字符串判断方法.py ├── ch_17_字符串的查找和替换.py ├── ch_18_字符串的文本对齐.py ├── ch_19_字符串拆分和连接.py ├── ch_20_for循环语法演练.py └── ch_21_遍历字典的列表.py ├── 06.判断语句.md ├── 06_名片管理系统 ├── __pycache__ │ └── cards_tools.cpython-38.pyc ├── cards_main.py └── cards_tools.py ├── 07.循环.md ├── 07_语法进阶 ├── ch_01_引用.py ├── ch_02_局部变量.py ├── ch_03_全局变量.py ├── ch_04_全局变量.py ├── ch_05_修改全局变量.py ├── ch_06_全局变量的位置.py ├── ch_07_全局变量命名.py ├── ch_08_多个返回值.py ├── ch_09_交换数字.py ├── ch_10_参数传递.py ├── ch_11_函数内部通过方法修改可变参数.py ├── ch_12_加等于运算符.py ├── ch_13_函数的缺省参数.py ├── ch_14_函数缺省参数的定义.py ├── ch_15_缺省参数注意点.py ├── ch_16_多值参数.py ├── ch_17_多值参数求和.py ├── ch_18_元组和字典的拆包.py ├── ch_19_递归函数的特点.py └── ch_20_递归求和.py ├── 08.函数.md ├── 08_面向对象基础 ├── ch_01_第一个面向对象.py ├── ch_02_新建两个对象.py ├── ch_03_设置对象属性.py ├── ch_04_在外界设置属性的问题.py ├── ch_05_初始化方法.py ├── ch_06_利用参数设置属性初始值.py ├── ch_07___del__方法.py ├── ch_08___str__.py ├── ch_09_小明爱跑步.py ├── ch_10_小明爱跑步拓展.py ├── ch_11_摆放家具_01_家具类.py ├── ch_12_摆放家具_02_房子类.py ├── ch_13_摆放家具_03_添加家具.py ├── ch_14_士兵突击_01_枪类.py ├── ch_15_士兵突击_02_士兵类.py ├── ch_16_士兵突击_03_士兵开火.py ├── ch_17_私有属性和方法.py └── ch_18_伪私有属性和方法.py ├── 09.列表.md ├── 09_面向对象特性 ├── ch_01_不使用继承开发动物和狗.py ├── ch_02_使用继承开发动物和狗.py ├── ch_03_继承的传递性.py ├── ch_04_继承的传递性注意事项.py ├── ch_05_覆盖父类方法.py ├── ch_06_扩展父类方法.py ├── ch_07_父类的私有属性和私有方法.py ├── ch_08_父类的公有方法.py ├── ch_09_多继承.py ├── ch_10_多继承的使用注意事项.py ├── ch_11_多态案例.py ├── ch_12_类属性.py ├── ch_13_属性获取机制.py ├── ch_14_使用对象名访问类属性的问题.py ├── ch_15_类方法.py ├── ch_16_静态方法.py ├── ch_17_方法综合案例.py ├── ch_18___new__.py ├── ch_19_单例.py └── ch_20_单例初始化一次.py ├── 10.元组,字典,字符串.md ├── 10_异常 ├── ch_01_简单的异常捕获.py ├── ch_02_捕获错误类型.py ├── ch_03_捕获未知错误.py ├── ch_04_完整的异常语法.py ├── ch_05_异常的传递.py └── ch_06_抛出异常 ├── 11.综合应用--名片管理系统.md ├── 11_模块 ├── __pycache__ │ ├── ch_01_测试模块1.cpython-38.pyc │ ├── ch_02_测试模块2.cpython-38.pyc │ └── ch_09___name__模块.cpython-38.pyc ├── ch_01_测试模块1.py ├── ch_02_测试模块2.py ├── ch_03_import导入模块.py ├── ch_04_import同时指定别名.py ├── ch_05_from_import导入.py ├── ch_06_from_import_注意事项.py ├── ch_07_from_import导入全部.py ├── ch_08_模块的搜索顺序.py ├── ch_09___name__模块.py ├── ch_09___name__测试导入.py ├── ch_10_导入包.py └── ch_message │ ├── __init__.py │ ├── __pycache__ │ ├── __init__.cpython-38.pyc │ ├── receive_message.cpython-38.pyc │ └── send_message.cpython-38.pyc │ ├── receive_message.py │ └── send_message.py ├── 12.变量进阶.md ├── 12_发布模块 ├── MANIFEST ├── build │ └── lib │ │ └── ch_message │ │ ├── __init__.py │ │ ├── receive_message.py │ │ └── send_message.py ├── ch_message │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-38.pyc │ │ ├── receive_message.cpython-38.pyc │ │ └── send_message.cpython-38.pyc │ ├── receive_message.py │ └── send_message.py ├── dist │ └── ch_message-1.0.tar.gz └── setup.py ├── 13.函数参数和返回值.md ├── 13_读取文件 ├── README ├── ch_01_读取文件.py ├── ch_02_读取文件后文件指针会改变.py ├── ch_03_写入文件.py ├── ch_04_分行读取文件.py ├── ch_05_复制文件.py ├── ch_06_复制大文件.py ├── ch_07_python2字符串.py └── ch_08_eval计算器.py ├── 14.面向对象编程.md ├── 15.面向对象封装.md ├── 16.私有属性和私有方法及继承.md ├── 17.多态,类属性和类方法.md ├── 18.单例.md ├── 19.异常.md ├── 20.模块.md ├── 21.文件.md ├── 22.eval函数.md ├── 23.项目实战.md ├── 24.项目实战2 - 游戏框架搭建.md ├── 25.项目实战.md ├── 26.vim.md ├── README.md ├── img ├── img1.png ├── img10.png ├── img11.png ├── img12.png ├── img13.png ├── img14.png ├── img15.png ├── img16.png ├── img17.png ├── img18.png ├── img19.png ├── img2.png ├── img20.png ├── img21.png ├── img22.png ├── img23.png ├── img24.png ├── img25.png ├── img26.png ├── img27.png ├── img28.png ├── img29.png ├── img3.png ├── img30.png ├── img31.png ├── img32.png ├── img33.png ├── img34.png ├── img35.png ├── img36.png ├── img37.png ├── img38.png ├── img39.png ├── img4.png ├── img40.png ├── img41.png ├── img42.png ├── img43.png ├── img44.png ├── img45.png ├── img46.png ├── img47.jpg ├── img48.png ├── img49.jpg ├── img5.jpg ├── img50.png ├── img51.png ├── img52.png ├── img53.png ├── img54.png ├── img55.png ├── img56.gif ├── img57.png ├── img58.png ├── img59.png ├── img6.jpg ├── img60.png ├── img61.png ├── img62.png ├── img63.png ├── img64.png ├── img65.png ├── img66.png ├── img67.png ├── img68.png ├── img69.png ├── img7.png ├── img70.png ├── img71.png ├── img72.png ├── img73.png ├── img75.png ├── img76.png ├── img8.png └── img9.png └── 飞机大战 ├── __pycache__ └── plane_sprites.cpython-38.pyc ├── ch_01_pygame入门.py ├── ch_02_使用Rect描述英雄.py ├── ch_03_创建游戏主屏幕.py ├── ch_04_绘制图像.py ├── ch_05_绘制英雄图像.py ├── ch_06_update方法.py ├── ch_07_认识游戏循环.py ├── ch_08_更新英雄的位置.py ├── ch_09_事件监听.py ├── ch_10_演练精灵.py ├── images ├── again.png ├── background.png ├── bomb.png ├── bomb_supply.png ├── bullet1.png ├── bullet2.png ├── bullet_supply.png ├── enemy1.png ├── enemy1_down1.png ├── enemy1_down2.png ├── enemy1_down3.png ├── enemy1_down4.png ├── enemy2.png ├── enemy2_down1.png ├── enemy2_down2.png ├── enemy2_down3.png ├── enemy2_down4.png ├── enemy2_hit.png ├── enemy3_down1.png ├── enemy3_down2.png ├── enemy3_down3.png ├── enemy3_down4.png ├── enemy3_down5.png ├── enemy3_down6.png ├── enemy3_hit.png ├── enemy3_n1.png ├── enemy3_n2.png ├── gameover.png ├── life.png ├── me1.png ├── me2.png ├── me_destroy_1.png ├── me_destroy_2.png ├── me_destroy_3.png ├── me_destroy_4.png ├── pause_nor.png ├── pause_pressed.png ├── resume_nor.png └── resume_pressed.png ├── plane_main.py └── plane_sprites.py /01.Python的起源.md: -------------------------------------------------------------------------------- 1 | #python 2022/8/14 2 | 3 | ## 1.0 起源 4 | 5 | >Python的创始人为吉多·范罗苏姆(Gudio van Rossum) 6 | 7 | 1991年,第一个Python**解释器**诞生,它是用C语言实现的,并能调用C语言的库文件 8 | 9 | ## 1.1 解释器(科普) 10 | 11 | **计算机不能直接理解任何机器语言以外的语言**,所以必须要把程序员所写的程序语言翻译成机器语言,计算机才能执行程序。**将其它语言翻译成机器语言的工具,被称为编译器**。 12 | 13 | 编译器翻译的方式有两种:一个是**编译**,另一个是**解释**,两种方式之间的区别在于**翻译时间点的不同**。当编译器**以解释方式运行的时候**,也称之为**解释器**。 14 | 15 | ![编译器与解释器](img/img1.png) 16 | 17 | - **编译型语言(如C/C++)**:程序在执行之前需要一个专门的编译过程,把程序编译成机器语言的文件,运行时不需要重新翻译,直接使用编译的结果就行。程序执行效率高,依赖编译器,跨平台性能差些。 18 | - **解释性语言(如Python)**:解释型语言编写的程序不进行预先编译,以文本方式存储程序代码,会将代码一句一句直接运行。在发布程序时,看起来节省了编译工序,但是在运行程序的时候,必须先解释再运行。 19 | 20 | 编译型语言和解释型语言对比 21 | - 速度--编译型语言比解释型语言执行速度快 22 | - 跨平台性--解释型语言比编译型语言跨平台性号 23 | 24 | ## 1.2 Python的设计目标 25 | 26 | - 一门**简单直观**的语言并与主要竞争者一样强大 27 | - **开源**,以便任何人都可以为它做贡献 28 | - 代码**像纯英语那样容易理解** 29 | - 适用于**短期**开发的日常任务 30 | 31 | ## 1.3 Python的设计哲学 32 | 33 | 1. 优雅 34 | 2. 明确 35 | 3. 简单 36 | 37 | - Python开发者的哲学是:用一种方法,最好是只有一种方法来做一件事 38 | - 如果面临多种选择,Python开发者一般会拒绝花哨的语法,而选择明确没有或者很少有歧义的语法 39 | 40 | >在Python社区,吉多被称为“仁慈的独裁者” 41 | 42 | ## 02 为什么选择Python? 43 | 44 | - 代码量少 45 | - 人生苦短,我用Python 46 | 47 | ## 0.3 Python特点 48 | 49 | - Python是**完全面向对象**的语言 50 | - **函数、模块、数字、字符串**都是对象,在**Python中一切皆对象** 51 | - 完全支持继承、重载、多重继承 52 | - 支持重载运算符,也支持泛型设计 53 | - Python**拥有一个强大的标准库**,Python语言的核心只包含 **数字、字符串、列表、字典、文件** 等常见类型和函数,而由Python标准库提供了 **系统管理、网络通信、文本处理、数据库接口、图形系统、XML处理** 等额外的功能 54 | - Python社区提供了**大量第三方模块**,使用方式与标准库类似。它们的功能覆盖 **科学计算、人工智能、机器学习、Web开发、数据库接口、图形系统** 多个领域 55 | 56 | ## 面向对象的思维方式 57 | 58 | - **面向对象** 是一种 **思维方式**,也是一门 **程序设计技术** 59 | - 要解决一个问题前,首先考虑**由谁**来做,怎么做事情是 谁 的职责,最好把事情做好就行! 60 | - **对象** 就是 **谁** 61 | - 要解决复杂的问题,就可以找**多个不同的对象,各司其职**,共同实现,最终完成需求 62 | 63 | ## 0.4 Python的优缺点 64 | 65 | ### 4.1 优点 66 | 67 | - 简单、易学 68 | - 免费、开源 69 | - 面向对象 70 | - 丰富的库 71 | - 可扩展性 72 | - 如果需要一段关键代码运行得更快或者希望某些算法不公开,可以把这部分程序用`C/C++`编写,然后在`Python`程序中使用它们 73 | - ... 74 | 75 | ### 4.2 缺点 76 | 77 | - 运行速度 78 | - 国内市场较小 79 | - 中文资料匮乏 80 | -------------------------------------------------------------------------------- /01_Python基础/ch_01_hello.py: -------------------------------------------------------------------------------- 1 | print("hello") 2 | print("world") -------------------------------------------------------------------------------- /01_Python基础/ch_02_注释.py: -------------------------------------------------------------------------------- 1 | # 这是一个注释 2 | print("hello world") 3 | 4 | # 这是第二个注释 5 | print("hello hello") # 输出"hello hello" 6 | 7 | """ 8 | 这是一个多行注释 9 | 10 | 在多行注释之间,可以写很多内容 11 | """ 12 | print("Hello Python") -------------------------------------------------------------------------------- /01_Python基础/ch_03_个人信息.py: -------------------------------------------------------------------------------- 1 | """ 2 | - 姓名:小明 3 | - 年龄: 18岁 4 | - 性别:是男生 5 | - 身高: 1.75米 6 | - 体重: 75.0公斤 7 | """ 8 | 9 | # 在 Python 中,定义变量时是不需要指定变量的类型的 10 | # 在运行的时候,Python 解释器,会根据与赋值语句等号右侧的数据 11 | # 自动推导出变量中保存数据的准确类型 12 | 13 | name = "小明" 14 | age = 18 15 | # bool 表示是一个布尔类型,真 True 或者假 False 16 | gender = True 17 | height = 1.75 18 | weight = 75.0 19 | print(name) -------------------------------------------------------------------------------- /01_Python基础/ch_04_买苹果.py: -------------------------------------------------------------------------------- 1 | # 1.输入苹果的单价 2 | price_str = input("苹果的单价:") 3 | # 2.输入苹果的重量 4 | weight_str = input("苹果的重量:") 5 | # 3.计算支付的总金额 6 | # 注意:两个字符串变量之间是不能直接用乘法的 7 | # 将数据转换成小数,用小数来计算最终的金额 8 | price = float(price_str) 9 | weight = float(weight_str) 10 | money = price * weight 11 | print(money) -------------------------------------------------------------------------------- /01_Python基础/ch_05_买苹果改进.py: -------------------------------------------------------------------------------- 1 | # 1.提示用户输入苹果的单价 2 | price = float(input("苹果的单价:")) 3 | # 2.提示用户输入苹果的重量 4 | weight = float(input("苹果的重量:")) 5 | # 3.计算金额 6 | money = price * weight 7 | 8 | print(money) -------------------------------------------------------------------------------- /01_Python基础/ch_06_格式化字符串.py: -------------------------------------------------------------------------------- 1 | """ 2 | 1. 定义字符串变量`name`,输出 我的名字叫小明,请多多关照! 3 | 2. 定义整数 变量`student_no`,输出 我的学号是 000001 4 | 3. 定义小数`price`、`weight`、`money`输出 苹果单价 9.00元/斤, 购买了5.00斤, 需要支付45.00元 5 | 4. 定义一个小数 `scale` ,输出 数据比例是 10.00% 6 | """ 7 | name = "小明" 8 | print("我的名字叫 %s ,请多多关照!" % name) 9 | 10 | student_no = 100 11 | print("我的学号是 %06d" % student_no) 12 | 13 | price = 9.00 14 | weight = 5.00 15 | money = price * weight 16 | print("苹果单价 %.2f元/斤, 购买了%.3f斤, 需要支付%.4f元" % (price, weight, money)) 17 | 18 | scale = 0.25 19 | print("数据比例是 %.2f%%" % (scale * 100)) -------------------------------------------------------------------------------- /02.第一个Python程序.md: -------------------------------------------------------------------------------- 1 | #python 2022/8/15 2 | 3 | # 第一个Python程序 4 | 5 | ## 目标 6 | 7 | - 第一个`HelloPython`程序 8 | - `Python2.x`与`3.x`版本简介 9 | - 执行`Python`程序的三种方式 10 | - 解释器--`python/python3` 11 | - 交互式--`ipython` 12 | - 集成开发环境--`PyCharm` 13 | 14 | ## 01.第一个HelloPython程序 15 | 16 | ### 1.1 Python源程序的基本概念 17 | 18 | 1. Python源程序就是一个特殊格式的文本文件,可以使用任意文本编辑软件做`Python`的开发 19 | 2. Python程序的 文件扩展名 通常都是`.py` 20 | 21 | ### 1.2 演练步骤 22 | 23 | - 在桌面下,新建`认识Python`目录 24 | - 在`认识Python`目录下新建`01-HelloPython.py`文件 25 | - 使用 **gedit编辑** `01-HelloPython.py`并且输入以下内容 26 | 27 | ```python 28 | print("hello python") 29 | print("hello world") 30 | ``` 31 | 32 | - 在终端输入以下命令执行`01-HelloPython.py` 33 | 34 | ```linux 35 | $ python 01-HelloPython.py 36 | ``` 37 | 38 | >`print`是`python`学习的第一个函数 39 | >`print`函数的作用,可以把`""`中的内容,输出到屏幕上 40 | 41 | ```python 42 | $ mkdir 认识Python 43 | $ cd 认识Python 44 | $ touch 01-HelloPython.py 45 | $ gedit 01-HelloPython.py 46 | 47 | print("hello python") 48 | print("hello world") 49 | ``` 50 | 51 | ### 1.3 演练扩展--认识错误(BUG) 52 | 53 | 关于错误 54 | - 编写的程序**不能正常执行,或者执行的结果不是我们期望的** 55 | - 俗称`BUG`,是程序员在开发时非常常见的 56 | - 在学习语言时,不仅要**学会语言的语法,而且还要学会如何认识错误和解决错误的方法** 57 | 58 | >每个程序员都是在不断地修改错误中成长的 59 | 60 | 常见错误 61 | 1. 手误,例如使用`pirnt("Hello world")` 62 | 63 | ```md 64 | NameError: name 'pirnt' is not defined 65 | 名称错误:'pirnt'名字没有定义 66 | ``` 67 | 68 | 2. 将多条`print`写在一行 69 | 70 | ```md 71 | SyntaxError: invalid syntax 72 | 语法错误:语法无效 73 | ``` 74 | 75 | >每行代码负责完成一个动作 76 | 77 | 3. 缩进错误 78 | 79 | ```md 80 | IndentationError: unexpected indext 81 | ``` 82 | 83 | - Python是一个格式非常严格的程序设计语言 84 | - 目前而言,每行代码之前都不要增加空格 85 | 86 | 4. python 2.x默认不支持中文 87 | 88 | ## 02. Python 2.x 与 3.x版本简介 89 | 90 | - **Python 2.x**的解释器名称是**python** 91 | - 当代码中有输出中文,而使用的是python解释器时,会放生**语法错误** 92 | - `SyntaxError: Non-ASCII charcter` 93 | - **Python 3.x**的解释器名称是**python3** 94 | 95 | ## 03.执行Python程序的三种方式 96 | 97 | ### 3.1 解释器python/Python3 98 | 99 | ```linux 100 | # 使用 python 2.x 解释器 101 | $ python xxx.py 102 | 103 | # 使用 python 3.x 解释器 104 | $ python3 xxx.py 105 | ``` 106 | 107 | **Python的解释器**如今有多个语言的实现,包括: 108 | - `CPython` -- 官方版本的C语言实现 109 | - `Jython` -- 可以运行Java平台 110 | - `IronPython` -- 可以运行在.NET和Mono平台 111 | - `PyPy` -- Python实现的,支持JIT即时编译 112 | 113 | ### 3.2.交互式运行Python程序 114 | 115 | - 直接在终端中运行的解释器,而不输入要执行的文件名 116 | - 在Python的`Shell`中直接输入**Python的代码**,会立即看到程序执行结果 117 | 118 | 1. 交互式运行Python的优缺点 119 | 120 | 优点 121 | - 适合于学习/验证Python语法或者局部代码 122 | 123 | 缺点 124 | - 代码不能保存 125 | - 不适合运行太大的程序 126 | 127 | 2. 退出 官方的解释器 128 | 129 | **1>直接输入exit()** 130 | 131 | ```shell 132 | >>> exit() 133 | ``` 134 | 135 | **2>使用热键退出** 136 | 137 | 在Python解释器中,按热键`ctrl + d`可以退出解释器 138 | 139 | 3. **IPython** 140 | 141 | - IPython中的"I"代表**交互interactive** 142 | 143 | 特点 144 | - IPython是一个python**交互式shell**,比默认的`python shell`好用得多 145 | - **支持自动补全** 146 | - **自动缩进** 147 | - **支持`bash shell`命令(可以直接输入linux终端命令)** 148 | - **内置了许多很有用得功能和函数** 149 | - IPython是基于BSD开源的 150 | 151 | 版本 152 | - Python 2.x使用的解释器是 **ipython** 153 | - Python 3.x使用的解释器是 **ipython3** 154 | - 要退出解释器可以有以下两种方式 155 | 156 | 1>直接输入exit 157 | 158 | ```ipython 159 | >>> exit 160 | ``` 161 | 162 | 2>使用热键退出 163 | 164 | 在Ipython解释器中,按热键`ctrl + d`,`IPython`会询问是否退出解释器 165 | 166 | ### 3.3.Python的IDE -- PyCharm 167 | 168 | 1. 集成开发环境(IDE) 169 | 170 | 集成开发环境(`IDE`, Integrated Development Environment) -- **集成了开发软件需要的所有工具** ,一般包括以下工具: 171 | - 图形用户界面 172 | - 代码编辑器(支持 **代码补全/自动缩进**) 173 | - 编译器/解释器 174 | - 调试器(**断点/单步执行**) 175 | - ... 176 | 177 | 2. PyCharm介绍 178 | 179 | - `PyCharm`是Python的一款非常优秀的集成开发环境 180 | - `PyCharm`除了具有一般IDE所必备功能外,还可以在`Windows/Linux/macOS`下使用 181 | - `PyCharm`适合开发大型项目 182 | - 一个项目通常会包括 **很多源文件** 183 | - 每个 **源文件** 的代码行数是有限的,通常在几百行之内 184 | - 每个 **源文件** 各司其职,共同完成复杂的业务功能 185 | 186 | ## 0.4.命名规则 187 | 188 | - 以后的 **项目名** 前面都以 数字编号,随着知识点递增,编号递增 189 | - 例如:01_Python基础、02_分治、03_循环 190 | - 每个项目下的文件名都以`hm_xx_知识点`方式来命名 191 | - 其中**xx**是演练文件的序号 192 | - 注意 193 | 1. 命名文件名建议只是用**小写字母**、**数字**和**下划线** 194 | 2. **文件名不能以数字开始** 195 | -------------------------------------------------------------------------------- /02_分支/ch_01_判断年龄.py: -------------------------------------------------------------------------------- 1 | # 1. 定义一个整数变量记录年龄 2 | age = 20 3 | # 2. 判断是否满了18岁 4 | if age >= 18: 5 | # 3.如果满了18岁,可以进网吧 6 | print("已成年,可以进网吧!") 7 | print("Welcome!") 8 | 9 | print("OK") -------------------------------------------------------------------------------- /02_分支/ch_02_判断年龄改进版.py: -------------------------------------------------------------------------------- 1 | age = int(input("请输入年龄:")) 2 | if age >= 18: 3 | print("Welcome!") 4 | else: 5 | print("快回去做作业") 6 | 7 | # 这句代码如论条件成立与否都会执行 8 | print("OK!") -------------------------------------------------------------------------------- /02_分支/ch_03_逻辑运算演练.py: -------------------------------------------------------------------------------- 1 | age = int(input("请输入年龄:")) 2 | if age >= 0 and age <= 120: 3 | print("legal") 4 | 5 | python_score = int(input("Python成绩: ")) 6 | c_score = int(input("C语言成绩: ")) 7 | if python_score >= 60 or c_score > 60: 8 | print("pass") 9 | 10 | is_employee = bool(input("是否是本公司员工: ")) 11 | if is_employee: 12 | print("Welcome!") 13 | else: 14 | print("Worn!") -------------------------------------------------------------------------------- /02_分支/ch_04_女友的节日.py: -------------------------------------------------------------------------------- 1 | holiday_name = "情人节" 2 | if holiday_name == "情人节": 3 | print("买花/看电影") 4 | elif holiday_name == "平安夜": 5 | print("买水果/吃大餐") 6 | elif holiday_name == "生日": 7 | print("吃蛋糕") 8 | else: 9 | print("每天都是节日啊!") -------------------------------------------------------------------------------- /02_分支/ch_05_火车站案件.py: -------------------------------------------------------------------------------- 1 | """ 2 | 1. 定义布尔型变量 `has_ticket` 表示是否有车票 3 | 2. 定义整型变量 `knife_length` 表示到的长度,单位:厘米 4 | 3. 首先检测是否有车票,如果有,才允许进行 案件 5 | 4. 安检时,需要检查刀的长度,判断是都超过20厘米 6 | 7 | - 如果超过20厘米,提示刀的长度,不允许上车 8 | - 如果不超过,安检通过 9 | 5. 如果没有车票,不允许进入 10 | """ 11 | has_ticket = True 12 | knife_length = 15 13 | if has_ticket: 14 | print("车票检查通过,准备开始安检") 15 | if knife_length <= 20: 16 | print("安检通过,祝您旅途愉快") 17 | else: 18 | print("携带道具长度为 %d厘米" % knife_length) 19 | print("不允许上车") 20 | else: 21 | print("请先买票!") -------------------------------------------------------------------------------- /02_分支/ch_06_石头剪刀布.py: -------------------------------------------------------------------------------- 1 | """ 2 | 1. 从控制台输入要出的拳--石头(1)/剪刀(2)/布(3) 3 | 2. 电脑 **随机** 出拳--先假定电脑只会出石头,完成完整代码功能 4 | 3. 比较胜负 5 | """ 6 | # 导入随机工具包 7 | # 在导入工具包时,应该将导入的语句,放在文件的顶部 8 | # 因为,这样可以方便下方的代码,在任何需要的时候,使用工具包中的工具 9 | import random 10 | player = int(input("请输入您出的拳 石头(1)/剪刀(2)/布(3): ")) 11 | computer = random.randint(1, 3) 12 | print("玩家出的拳头是 %d - 电脑出的拳是 %d" % (player, computer)) 13 | # 玩家胜利的三种情况 14 | if ((player == 1 and computer == 2) 15 | or (player == 2 and computer == 3) 16 | or (player == 3 and computer == 1)): 17 | print("玩家赢了!") 18 | # 平局 19 | elif player == computer: 20 | print("平居") 21 | # 电脑获胜 22 | else: 23 | print("电脑获胜!") -------------------------------------------------------------------------------- /03.Python基础.md: -------------------------------------------------------------------------------- 1 | #python 2022/8/16 2 | 3 | ## 01.注释 4 | 5 | ### 1.1 注释的作用 6 | 7 | >使用自己熟悉的语言,在程序中对某些代码进行标注说明,增强程序的可读性 8 | 9 | ### 1.2 单行注释 10 | 11 | - 以`#`开头,`#`右边的所有东西都被当作说明文字,而不是真正要执行的程序,只起到辅助说明作用 12 | - 为保证程序的可读性,在`#`后要添加一个空格 13 | - 示例代码如下 14 | 15 | ```python 16 | # 这是一个注释 17 | print("hello world") 18 | ``` 19 | 20 | 在代码后面增加的单行注释 21 | 22 | - 在程序开发时,同样可以使用`#`在代码后面(旁边)增加说明性的文字 23 | - 但是,需要注意的是,为了**保证代码的可读性,注释和代码之间** 至少要有 **两个空格** 24 | 25 | ```python 26 | print("Hello world") # 输出"Hello world" 27 | ``` 28 | 29 | ### 1.3 多行注释(块注释) 30 | 31 | - 如果希望编写的 注释信息很多,一行无法显示,就可以使用多行注释 32 | - 要在Python程序中使用多行注释,可以用 一对 连续的 三个 引号(单引号和双引号都可以) 33 | - 示例代码如下: 34 | 35 | ```python 36 | """ 37 | 这是一个多行注释 38 | 39 | 在多行注释之间,可以写很多内容 40 | """ 41 | print("Hello Python") 42 | ``` 43 | 44 | ### 1.4 什么时候需要使用注释? 45 | 46 | 1. 注释不是越多越好,对于一目了然的代码,不需要添加注释 47 | 2. 对于复杂的操作,应该在操作开始前写上若干行注释 48 | 3. 对于 不是一目了然的代码,应该在其行尾添加注释 49 | 4. 绝不要描述代码,假设阅读代码的人比你更懂Python,他只是不知道你的代码要做什么 50 | 51 | >在一些正规的开发团队,通常会有 **代码审核** 的惯例,就是一个团队中彼此阅读对方的代码 52 | 53 | 关于代码规范 54 | 55 | - `Python`官方提供一系列PEP(Python Enhancement Proposals)文档 56 | - 其中第8篇文档专门针对Python的代码格式 给出了建议,也就是俗称的 PEP8 57 | - 文档地址: [PEP8](https://www.python.org/dev/peps/pep-0008) 58 | 59 | >任何语言的程序员,编写出符合规范的代码,是开始程序生涯的第一步 60 | 61 | ## 02.算数运算符 62 | 63 | **计算机**,顾名思义就是负责进行**数学计算**并且**存储计算结果**的电子设备 64 | 65 | ### 2.1 算数运算符 66 | 67 | - 算数运算符是 运算符的一种 68 | - 是完成基本的算数运算使用的符号,用来处理四则运算 69 | 70 | | 运算符 | 描述 | 实例 | 71 | | ------ | ------ | ------------------------------- | 72 | | `+` | 加 | `10+20=30` | 73 | | `-` | 减 | `10-20=-10` | 74 | | `*` | 乘 | `10*20=200` | 75 | | `/` | 除 | `10/20=0.5` | 76 | | `//` | 取整除 | 返回除法的整数部分(商) `9//2=4` | 77 | | `%` | 取余数 | 返回除法的余数 `9%2=1` | 78 | | `**` | 幂 | 又称为次方、乘方`2**3=8` | 79 | 80 | - 在Python中`*`运算符还可以用于字符串,计算结果就是字符串重复指定次数的结果 81 | 82 | ```python 83 | "+" * 5 # 输出 +++++ 84 | ``` 85 | 86 | ### 2.2 算数运算符的优先级 87 | 88 | - 和数学中的运算符的优先级一致,在Python中进行数学计算时,同样也是: 89 | - 先乘除后加减 90 | - 同级运算符是 从左至右 计算 91 | - 可以使用小括号`()`调整计算的优先级 92 | - 以下表格的算数优先级由高到低顺序排列 93 | 94 | | 运算符 | 描述 | 95 | | ---------- | ------------------ | 96 | | `**` | 幂(最高优先级) | 97 | | `* / % //` | 乘、除、取余、取整 | 98 | | `+ -` | 加法、减法 | 99 | 100 | -------------------------------------------------------------------------------- /03_循环/ch_01_循环.py: -------------------------------------------------------------------------------- 1 | # 打印 5 遍 Hello Python 2 | # 1. 定义一个整数变量,记录循环次数 3 | i = 1 4 | # 2. 开始循环 5 | while i <= 5: 6 | # 1> 希望在循环内执行的代码 7 | print("Hello Python") 8 | # 2> 处理计数器 9 | i += 1 10 | 11 | # 3. 观察一下,循环结束后,计数器 i 的数值是多少 12 | print("循环结束后, i = %d" % i) # 4 -------------------------------------------------------------------------------- /03_循环/ch_02_程序计数.py: -------------------------------------------------------------------------------- 1 | # 打印 5 遍 Hello Python 2 | # 1. 定义一个整数变量,记录循环次数 3 | i = 0 # 从0开始计数 4 | # 2. 开始循环 5 | while i < 5: 6 | # 1> 希望在循环内执行的代码 7 | print("Hello Python") 8 | # 2> 处理计数器 9 | i += 1 10 | 11 | # 3. 观察一下,循环结束后,计数器 i 的数值是多少 12 | print("循环结束后, i = %d" % i) # 4 -------------------------------------------------------------------------------- /03_循环/ch_03_累加求和.py: -------------------------------------------------------------------------------- 1 | # 计算 0!100 之间所有数字的累计求和结果 2 | # 0. 定义最终结果的变量 3 | result = 0 4 | # 1. 定义一个整数的变量记录循环的次数 5 | i = 0 6 | 7 | # 2. 开始循环 8 | while i <= 100: 9 | print(i) 10 | # 每一次循环,都让 result 这个变量和 i 这个计数器相加 11 | result += i 12 | i += 1 13 | print("0~100 之间的数字求和结果 = %d" % result) -------------------------------------------------------------------------------- /03_循环/ch_04_累加求和进阶版.py: -------------------------------------------------------------------------------- 1 | # 计算 0~100 之间 所有 偶数 的累计求和结果 2 | i, sum = 0, 0 3 | while i <= 100: 4 | # 判断变量 i 中的数值,是否是一个偶数 5 | # 偶数 i % 2 == 0 6 | # 奇数 i % 2 != 0 7 | if i % 2 == 0: 8 | print(i) 9 | sum += i 10 | i += 1 11 | print("sum = %d" % sum) -------------------------------------------------------------------------------- /03_循环/ch_05_break.py: -------------------------------------------------------------------------------- 1 | i = 0 2 | while i < 10: 3 | # break 某一条件满足时,退出循环,不再执行后续重复的代码 4 | # i == 3 5 | if i == 3: 6 | break 7 | print(i) 8 | i += 1 9 | 10 | print("over") -------------------------------------------------------------------------------- /03_循环/ch_06_continue.py: -------------------------------------------------------------------------------- 1 | i = 0 2 | # 输出 0~10 不包括3 3 | while i < 10: 4 | # - `continue` 某一条件满足时,不执行后续重复的代码 5 | # i == 3 6 | if i == 3: 7 | # 注意:在循环中,如果使用 continue 这个关键字 8 | # 在使用关键字之前,需要确认循环的计数是否修改, 9 | # 否则可能会导致死循环 10 | i += 1 11 | continue 12 | 13 | print(i) 14 | i += 1 15 | 16 | print("over") -------------------------------------------------------------------------------- /03_循环/ch_07_打印小星星.py: -------------------------------------------------------------------------------- 1 | # 在控制台连续输出五行 * ,每一行星号的数量次数递增 2 | # * 3 | # ** 4 | # *** 5 | # **** 6 | # ***** 7 | 8 | # 1.定义一个计数器变量,从数字1开始,循环会比较方便 9 | row = 1 10 | 11 | # 2.开始循环 12 | while row <= 5: 13 | print("*" * row) 14 | row += 1 15 | -------------------------------------------------------------------------------- /03_循环/ch_08_print函数的结尾.py: -------------------------------------------------------------------------------- 1 | # 默认情况下,print 函数输出内容之后,会自动在内容末尾增加换行 2 | # 如果不希望末尾增加换行,可以在 print 函数输出内容的后面增加 , end="" 3 | # 其中 "" 中间可以指定 print 函数输出内容之后,继续希望显示的内容 4 | print("*", end="---") 5 | print("*") 6 | # 输出 *---* 7 | 8 | -------------------------------------------------------------------------------- /03_循环/ch_09_嵌套打印小星星.py: -------------------------------------------------------------------------------- 1 | # 在控制台连续输出五行 * ,每一行星号的数量次数递增 2 | # * 3 | # ** 4 | # *** 5 | # **** 6 | # ***** 7 | # 1> 完成5行内容的简单输出 8 | # 2> 分析每行内部的 * 应该如何处理? 9 | 10 | row = 1 11 | while row <= 5: 12 | 13 | # 每一行要打印的星星就是和当前的行数是一致的 14 | # 增加一个小的循环,专门负责当前行中,每一列的星星显示 15 | # 1. 定义一个列计数器变量 16 | col = 1 17 | # 2.开始循环 18 | while col <= row: 19 | print("*", end="") 20 | col += 1 21 | print() # 每打印一行换行一次 22 | row += 1 -------------------------------------------------------------------------------- /03_循环/ch_10_九九乘法表.py: -------------------------------------------------------------------------------- 1 | # 打印九九乘法表 2 | row = 1 3 | while row <= 9: 4 | col = 1 5 | while col <= row: 6 | print("%d * %d = %d" % (col, row, row * col), end="\t") # 使用横向制表位对齐文本 7 | col += 1 8 | print() 9 | row += 1 10 | -------------------------------------------------------------------------------- /03_循环/ch_11_转义字符.py: -------------------------------------------------------------------------------- 1 | # \t 在控制台输出一个 制表符,协助在输出文本时 垂直方向 保持对齐 2 | print("1\t2\t3") 3 | print("10\t20\t30") 4 | # \n 在控制台输出一个 换行符 5 | print("hello\npython") 6 | # \" 在控制台输出一个 双引号 7 | print("hello\"hello") # hello"hello -------------------------------------------------------------------------------- /04.程序执行原理.md: -------------------------------------------------------------------------------- 1 | #python 2022/8/16 2 | 3 | ## 目标 4 | 5 | - 计算机中的 **三大件** 6 | - 程序执行的原理 7 | - 程序的作用 8 | 9 | ## 01.计算机中的三大件 10 | 11 | 计算机中包含有较多的硬件,但是一个程序要运行,有三个核心的硬件,分别是: 12 | 13 | 1. CPU 14 | - 中央处理器,是一块超大规模的集成电路 15 | - 负责 **处理数据/计算** 16 | 2. 内存 17 | - **临时** 存储数据(断电之后,数据会消失) 18 | - 速度快 19 | - 空间小 20 | - 价格高 21 | 3. 硬盘 22 | - **永久** 存储数据 23 | - 速度慢 24 | - 空间大 25 | - 价格便宜 26 | 27 | 28 | ## 02.程序执行的原理 29 | 30 | ```md 31 | 32 | CPU <-------> 内存 <-------> 硬盘 33 | |执行的程序| |没有执行的程序| 34 | 35 | ``` 36 | 37 | 1. 程序 **运行之前**,是 **保存在硬盘** 中的 38 | 2. 当要运行一个程序时 39 | 40 | - 操作系统会首先 让**CPU**把程序复制到 **内存** 中 41 | - **CPU** 执行 **内存** 中的 **程序代码** 42 | 43 | >**程序要执行,首先要被加载到内存** 44 | 45 | ### 2.1 Python程序执行原理 46 | 47 | ```md 48 | 49 | CPU <-------> 内存 <-------> 硬盘 50 | |Python解释器| |Python程序| 51 | 52 | ``` 53 | 54 | 1. 操作系统会首先让CPU把 **Python解释器** 的程序复制到 **内存** 中 55 | 2. **Python解释器** 根据语法规则,**从上向下** 让**CPU**翻译**Python程序中的代码** 56 | 3. **CPU** 负责执行翻译完成的代码 57 | 58 | **Python的解释器有多大?** 59 | 60 | - 执行以下终端命令可以查看Python解释器的大小 61 | 62 | ```linux 63 | # 1.确认解释器所在位置 64 | $ which python 65 | 66 | # 2.查看 python 文件大小(只是一个软链接) 67 | $ ls -lh /usr/bin/python 68 | 69 | # 3.查看具体文件大小 70 | $ ls -lh /usr/bin/python2.7 71 | ``` 72 | 73 | >`which`查找执行终端命令所在的位置 74 | >提示:建立 **软链接** 的目的,是为了方便使用者不用记住使用的解释器是 **哪一个具体版本** 75 | 76 | ## 03.程序的作用 77 | 78 | >程序就是 **用来处理数据** 的! 79 | 80 | - **新闻软件** 提供 **新闻内容、评论**……是数据 81 | - **电商软件** 提供的 **商品信息、配送信息**……是数据 82 | - **运动类软件** 提供的 **运动数据**……是数据 83 | - **地图类软件** 提供的 **地图信息、定位信息、车辆信息**……是数据 84 | - **即时通讯软件** 提供的 **聊天信息、好友信息**……是数据 85 | - …… 86 | 87 | ### 3.1 思考QQ程序的启动过程 88 | 89 | 1. QQ在**运行之前**,是保存在 **硬盘** 中的 90 | 2. **运行之后**,QQ程序就会被加载到 **内存** 中 91 | 92 | ### 3.2 登陆过程 93 | 94 | 1. 读取用户输入的**QQ号码** 95 | 2. 读取用户输入的**QQ密码** 96 | 3. 将 **QQ号码** 和 **QQ密码** 发送给腾讯的服务器,等待服务器确认用户信息 97 | 98 | 思考1 99 | 100 | >在QQ这个程序将 QQ号码 和 QQ密码 发送给服务器之前,是否需要先存储以下QQ号码 和 密码? 101 | 102 | 需要!-- 否则QQ这个程序就不知道把什么内容发送给服务器了! 103 | 104 | 思考2 105 | 106 | >QQ这个程序把QQ号码 和 QQ密码 保存在哪里? 107 | 108 | 保存在 **内存** 中,因为QQ程序自己就在内存中 109 | 110 | 思考3 111 | 112 | >QQ程序是怎么保存用户的 QQ号码 和 QQ密码的? 113 | 114 | 1. 在内存中为 QQ号码 和 QQ密码 各自分配一块空间 115 | 116 | - 在QQ程序结束之前,这两块空间是由QQ程序负责管理的,其它任何程序都不允许使用 117 | - 在QQ自己使用完成之前,这两块空间始终都只负责保存QQ号码 和 QQ密码 118 | 119 | 2. **使用一个别名 标记 QQ号码 和 QQ密码 在内存中的位置** 120 | 121 | >在程序内部,为QQ号码和QQ密码**在内存中分配的空间**就叫作 **变量** 122 | >**程序就是用来处理数据的,而变量就是用来存储数据的** 123 | -------------------------------------------------------------------------------- /04_函数/__pycache__/ch_01_九九乘法表.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/04_函数/__pycache__/ch_01_九九乘法表.cpython-38.pyc -------------------------------------------------------------------------------- /04_函数/__pycache__/ch_10_分隔线模块.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/04_函数/__pycache__/ch_10_分隔线模块.cpython-38.pyc -------------------------------------------------------------------------------- /04_函数/ch_01_九九乘法表.py: -------------------------------------------------------------------------------- 1 | def multiple_table(): 2 | # 打印九九乘法表 3 | row = 1 4 | while row <= 9: 5 | col = 1 6 | while col <= row: 7 | print("%d * %d = %d" % (col, row, row * col), end="\t") # 使用横向制表位对齐文本 8 | col += 1 9 | print() 10 | row += 1 11 | -------------------------------------------------------------------------------- /04_函数/ch_02_快速体验.py: -------------------------------------------------------------------------------- 1 | # 导入工具包 2 | import ch_01_九九乘法表 3 | # 调用工具包中的函数 4 | ch_01_九九乘法表.multiple_table() -------------------------------------------------------------------------------- /04_函数/ch_03_第一个函数.py: -------------------------------------------------------------------------------- 1 | # 注意:定义好函数之后,只表示这个函数封装了一段代码而已 2 | # 如果步主动调用函数,函数是不会主动执行的 3 | def say_hello(): 4 | 5 | print("hello 1") 6 | print("hello 2") 7 | print("hello 3") 8 | 9 | # 调用函数 10 | say_hello() -------------------------------------------------------------------------------- /04_函数/ch_04_第一个函数改造.py: -------------------------------------------------------------------------------- 1 | name = "小明" 2 | 3 | # Python 解释器知道下方定义了一个函数 4 | def say_hello(): 5 | """打招呼""" 6 | print("hello 1") 7 | print("hello 2") 8 | print("hello 3") 9 | 10 | print(name) 11 | 12 | # 只有在程序中,主动调用函数,才会让函数执行 13 | say_hello() 14 | 15 | print(name) -------------------------------------------------------------------------------- /04_函数/ch_05_函数的参数.py: -------------------------------------------------------------------------------- 1 | def sum_2_num(num1, num2): 2 | """对两个数字的求和""" 3 | 4 | # num1 = 10 5 | # num2 = 20 6 | res = num1 + num2 7 | print("%d + %d = %d" % (num1, num2, res)) 8 | 9 | sum_2_num(10, 20) -------------------------------------------------------------------------------- /04_函数/ch_06_函数的返回值.py: -------------------------------------------------------------------------------- 1 | def sum_2_num(num1, num2): 2 | """对两个数字求和""" 3 | 4 | return num1 + num2 5 | # return 表示返回,下方的代码不会被执行到 6 | # num = 1000 7 | 8 | # 调用函数,并使用 result 变量接受计算结果 9 | result = sum_2_num(10, 20) 10 | 11 | print("计算结果是 %d" % result) -------------------------------------------------------------------------------- /04_函数/ch_07_函数的嵌套调用.py: -------------------------------------------------------------------------------- 1 | def test1(): 2 | 3 | print("*" * 50) 4 | print("test 1") 5 | print("*" * 50) 6 | 7 | def test2(): 8 | 9 | print("-" * 50) 10 | print("test 2") 11 | 12 | # 函数的嵌套调用 13 | test1() 14 | 15 | print("-" * 50) 16 | 17 | test2() -------------------------------------------------------------------------------- /04_函数/ch_08_打印分割线.py: -------------------------------------------------------------------------------- 1 | def print_line(char, times): 2 | 3 | print(char * times) 4 | 5 | print_line("-", 10) -------------------------------------------------------------------------------- /04_函数/ch_09_打印多条分隔线.py: -------------------------------------------------------------------------------- 1 | def print_line(char, times): 2 | 3 | print(char * times) 4 | 5 | 6 | def print_lines(c, t): 7 | 8 | i = 0 9 | while i < 5: 10 | print_line(c, t) 11 | i += 1 12 | 13 | 14 | print_lines("U", 20) 15 | -------------------------------------------------------------------------------- /04_函数/ch_10_体验模块.py: -------------------------------------------------------------------------------- 1 | import ch_10_分隔线模块 2 | 3 | ch_10_分隔线模块.print_line("M", 6) 4 | 5 | print(ch_10_分隔线模块.name) -------------------------------------------------------------------------------- /04_函数/ch_10_分隔线模块.py: -------------------------------------------------------------------------------- 1 | def print_line(char, times): 2 | 3 | print(char * times) 4 | 5 | 6 | def print_lines(c, t): 7 | 8 | i = 0 9 | while i < 5: 10 | print_line(c, t) 11 | i += 1 12 | 13 | name = "Charlie" -------------------------------------------------------------------------------- /05.变量的使用.md: -------------------------------------------------------------------------------- 1 | #python 2022/8/17 2 | 3 | # 变量的基本使用 4 | 5 | >程序就是用来处理数据的,而变量就是用来存储数据的 6 | 7 | ## 目标 8 | 9 | - 变量的定义 10 | - 变量的类型 11 | - 变量的命名 12 | 13 | ## 01.变量定义 14 | 15 | - 在Python中,每个变量 **在使用前都必须赋值**,变量 **赋值以后** 该变量 **才会被创建** 16 | - 等号(`=`)用来给变量赋值 17 | 18 | - `=`左边是一个变量名 19 | - `=`右边是存储在变量中的值 20 | 21 | ```md 22 | 变量名 = 值 23 | ``` 24 | 25 | >变量定义之后,后续就可以直接使用了 26 | 27 | 1)变量演练1 -- iPython 28 | 29 | ```python 30 | # 定义qq_number的变量用来保存 qq号码 31 | In[1] : qq_number = "1234567" 32 | # 输出 qq_number中保存的内容 33 | In[2] : qq_number 34 | Out[2] : '1234567' 35 | ``` 36 | 37 | >使用交互式方式,如果要查看变量内容,直接输入变量名即可,不需要使用`print`函数 38 | 39 | 2)变量演练2 -- PyCharm 40 | 41 | ```python 42 | # 定义qq_number的变量用来保存 qq号码 43 | qq_number = "1234567" 44 | # 输出 qq_number中保存的内容 45 | print(qq_number) 46 | ``` 47 | 48 | >使用解释器执行,如果要输出变量的内容,必须要使用`print`函数 49 | 50 | 3)超市卖苹果,只要买就返回5元钱 51 | 52 | ```python 53 | # 定义苹果价格变量 54 | price = 8.5 55 | # 定义购买重量 56 | weight = 7.5 57 | # 计算金额 58 | money = price * weight* 59 | # 只要买苹果就返 5 元 60 | money = money - 5 61 | # 输出价格 62 | print(money) 63 | ``` 64 | 65 | 提问 66 | 67 | - 上述代码,一共定义了几个变量? 68 | - 三个:`price/weight/money` 69 | - `money = money - 5`是在定义新的变量还是在使用变量? 70 | - 直接使用之前已经定义的变量 71 | - **变量名 只有在第一次出现 才是 定义变量** 72 | - **变量名 再次出现,不是定义变量,而是直接使用之前定义过的变量** 73 | - 在程序开发中,可以修改之前定义变量中保存的值吗? 74 | - 可以 75 | - 变量中存储的值,就是可以 **变** 的 76 | 77 | ## 02.变量的类型 78 | 79 | - 在内存中创建一个变量,会包括 80 | 81 | 1. 变量的名称 82 | 2. 变量保存的数据 83 | 3. 变量存储数据的类型 84 | 4. 变量的地址(标示) 85 | 86 | ### 2.1 变量类型的演练 -- 个人信息 87 | 88 | 需求 89 | 90 | - 定义变量保存小明的个人信息 91 | - 姓名:小明 92 | - 年龄:18岁 93 | - 性别:男 94 | - 身高:1.75米 95 | - 体重:75.0公斤 96 | 97 | >利用 **单步调试** 确认变量中保存数据的类型 98 | 99 | 提问 100 | 101 | 1. 在演练中,一共有几种数据类型? 102 | 103 | - 4种 104 | - `str`--字符串 105 | - `bool`--布尔型(真假) 106 | - `int`--整数 107 | - `float`--浮点数(小数) 108 | 109 | 2. 在`Python`中定义变量时需要指定数据类型吗? 110 | 111 | - 不需要 112 | - `Python`可以根据`=`等号右侧的值,自动推导出变量中存储数据的类型 113 | 114 | ### 2.2 变量的类型 115 | 116 | - 在`Python`中定义变量是**不需要指定类型**(在其他很多高级语言中都需要) 117 | - 数据类型可以分为 **数字型** 和 **非数字型** 118 | - 数字型 119 | - 整型(`int`) 120 | - 浮点型(`flaot`) 121 | - 布尔型(`bool`) 122 | - 真`True` `非 0 数` --非零即真 123 | - 假`False` `0` 124 | - 复数型(`complex`) 125 | - 主要用于科学计算,例如:平面场问题、波动问题、电感电容等问题 126 | - 非数字型 127 | - 字符串 128 | - 列表 129 | - 元组 130 | - 字典 131 | 132 | >提示:在Python2.x中, **整数**根据保存数值的长度还分为: 133 | >- `int`(整数) 134 | >- `long`(长整数) 135 | 136 | - 使用`type`函数可以查看一个变量的类型 137 | 138 | ```python 139 | In [1]: type(name) 140 | Out [1]: str 141 | ``` 142 | 143 | ### 2.3 不同数据类型变量之间的计算 144 | 145 | 1) **数字型变量 之间可以直接计算** 146 | 147 | - 在 Python 中,两个数字型变量是可以直接进行 算数运算的 148 | - 如果变量是`bool`型,在计算时 149 | - `True`对应的数字是`1` 150 | - `False`对应的数字是`0` 151 | 152 | **演练步骤** 153 | 154 | 1. 定义整数`i = 10` 155 | 2. 定义 浮点数`f = 10.5` 156 | 3. 定义布尔型`b = True` 157 | 158 | - 在 iPython 中,使用上述三个变量相互进行算数运算 159 | 160 | ![不同数据类型变量之间的计算](img/img2.png) 161 | 162 | 2) 字符串变量 之间使用 + 拼接字符串 163 | 164 | - 在 Python 中,字符串之间可以使用`+`拼接**生成新的字符串** 165 | 166 | 3) 字符串变量 可以和 整数 使用 `*`重复拼接相同的字符串 167 | 168 | ![字符串变量之间的运算](img/img3.png) 169 | 170 | 4) 数字型变量 和 字符串 之间 不能进行其他计算 171 | 172 | ### 2.4 变量的输入 173 | 174 | - 所谓`输入`,就是 用代码获取 用户通过 键盘 输入的信息 175 | - 例如:去银行取钱,在ATM上输入密码 176 | - 在Python中,如果要获取用户在 键盘 上输入信息,需要使用到 `input` 函数 177 | 178 | 1) 关于函数 179 | 180 | - 一个 提前准备号的功能(别人或者自己写的代码),可以直接使用,而不用关心内部的细节 181 | - 目前语句学过的函数 182 | 183 | | 函数 | 说明 | 184 | | ---------- | --------------- | 185 | | `print(x)` | 将x输出到控制台 | 186 | | `type(x)` | 查看x的变量类型 | 187 | 188 | 2) input 函数实现键盘输入 189 | 190 | - 在 Python 中可以使用`input`函数从键盘等待用户的输入 191 | - **用户输入的任何内容 Python都认为是一个 字符串** 192 | - 语法如下: 193 | 194 | ```md 195 | 字符串变量 = input("提示信息: ") 196 | ``` 197 | 198 | 3) **类型转换函数** 199 | 200 | | 函数 | 说明 | 201 | | ---------- | --------------------- | 202 | | `int(x)` | 将 x 转换为一个整数 | 203 | | `float(x)` | 将 x 转换到一个浮点数 | 204 | 205 | ### 2.5 变量的格式化输出 206 | 207 | >苹果单价`9.00`元/斤。购买了`5.00`斤,需支付`45.00`元 208 | 209 | - 在 Python 中可以使用`print`函数将信息输出到控制台 210 | - 如果希望输出文字信息的同时,**一起输出 数据**,就需要使用到 **格式化操作符** 211 | - `%`被称为 **格式化操作符**,专门用于处理字符串中的格式 212 | - 包含`%`的字符串,被称为 **格式化字符串** 213 | - `%`和不同的 **字符** 连用,不同类型的数据 需要使用 **不同的格式化字符** 214 | 215 | | 格式化字符 | 含义 | 216 | | ---------- | --------------------------------------------------------------------- | 217 | | `%s` | 字符串 | 218 | | `%d` | 有符号十进制整数,`%06d`表示输出的整数显示位数,不足的地方使用 0 补全 | 219 | | `%f` | 浮点数,`%.2f`表示小数点后只显示两位 | 220 | | `%%` | 输出`%` | 221 | 222 | - 语法格式如下: 223 | 224 | ```python 225 | print("格式化字符串" % 变量1) 226 | print("格式化字符串" % (变量1, 变量2...)) 227 | ``` 228 | 229 | 格式化输出演练-- 基本练习 230 | 231 | 1. 定义字符串变量`name`,输出 我的名字叫小明,请多多关照! 232 | 2. 定义整数 变量`student_no`,输出 我的学号是 000001 233 | 3. 定义小数`price`、`weight`、`money`输出 苹果单价 9.00元/斤,购买了5.00斤, 需要支付45.00元 234 | 4. 定义一个小数 `scale` ,输出 数据比例是 10.00% 235 | 236 | ```python 237 | name = "小明" 238 | print("我的名字叫 %s ,请多多关照!" % name) 239 | 240 | student_no = 100 241 | print("我的学号是 %06d" % student_no) 242 | 243 | price = 9.00 244 | weight = 5.00 245 | money = price * weight 246 | print("苹果单价 %.2f元/斤, 购买了%.3f斤, 需要支付%.4f元" % (price, weight, money)) 247 | 248 | # 输出10.00% 249 | scale = 0.25 250 | print("数据比例是 %.2f%%" % (scale * 100)) 251 | ``` 252 | 253 | ## 03.变量的命名 254 | 255 | ### 3.1.标识符和关键字 256 | 257 | 1. 标识符 258 | 259 | >标识符就是程序员定义的 变量名、函数名 260 | >名字 需要有 见名知意 的效果 261 | 262 | - 标识符可以有 **字母、下划线 和 数字** 组成 263 | - **不能以数字开头** 264 | - **不能与关键字重名** 265 | 266 | 思考:下面的标识符哪些是正确的,哪些不正确为什么? 267 | 268 | ```md 269 | fromNo12 270 | from#12 271 | my_Boolean 272 | my-Boolean 273 | Obj2 274 | 2ndObj 275 | myInt 276 | My_tExt 277 | _test 278 | test!32 279 | haha(da)tt 280 | jack_rose 281 | jack&rose 282 | GUI 283 | G.U.I 284 | ``` 285 | 286 | 2. 关键字 287 | 288 | - **关键字** 就是在 `Python`内部已经使用的标识符 289 | - **关键字** 具有特殊的功能和含义 290 | - 开发者 **不允许定义和关键字相同的名字的标识符** 291 | 292 | 通过以下命令可以查看`Python`中的关键字 293 | 294 | ```python 295 | import keyword 296 | print(keyword.kwlist) 297 | ``` 298 | 299 | ![Python关键字列表](img/img4.png) 300 | 301 | >- `import`关键字 可以导入一个 ”工具包“ 302 | >- 在`Python`中不同的工具包,提供有不同的工具 303 | 304 | ### 3.2.变量的命名规则 305 | 306 | >**命名规则** 可以被视为一种 **惯例**,并无绝对与强制 307 | >目的是为了 **增强代码的识别和可读性** 308 | 309 | **注意`Python`中的 标识符 是 区分大小写的** 310 | 311 | 1. 在定义变量时,为了保证代码格式,`=`的左右应该各保留一个空格 312 | 2. 在`Python`中,如果 变量名 需要由 两个或多个单词 组成时,可以按照以下方式命名 313 | 314 | a. 每个单词都使用小写字母 315 | b. 单词与单词之间使用 `_` **下划线**连接 316 | c. 例如:`first_name`, `last_name`, `qq_password` 317 | 318 | 驼峰命名法 319 | 320 | - 当 变量名 是由两个或多个单词组成时,还可以利用驼峰命名法来命名 321 | - 小驼峰命名法 322 | - 第一个单词以小写字母开始,后续单词的首字母大写 323 | - 例如: `firstName`, `lastName` 324 | - 大驼峰命名法 325 | - 每一个单词的首字母都采用大写字母 326 | - 例如:`FirstName`, `LastName`, `CamelCase` -------------------------------------------------------------------------------- /05_高级数据类型/ch_01_列表基础使用.py: -------------------------------------------------------------------------------- 1 | name_list = ["zhangsan", "lisi", "wangwu"] 2 | 3 | # 1. 取值和取索引 4 | print(name_list[2]) # wangwu 5 | 6 | # 知道数据的内容,想确定数据在列表中的位置 7 | # 使用index方法需要注意,如果传递的数据不在列表中,程序会报错! 8 | print(name_list.index("lisi")) # 1 9 | 10 | # 2. 修改 11 | name_list[1] = "李四" 12 | 13 | # 不能通过索引添加数据 14 | # name_list[3] = "zhoubo" 15 | 16 | # 3. 增加 17 | # append 方法可以向列表的末尾追加数据 18 | name_list.append("哈士奇") 19 | # insert 可以在列表的指定索引位置插入数据 20 | name_list.insert(1, "小李广") 21 | # extend 将其他列表的所有内容追加到指定列表的末尾 22 | temp_list = ["宋江", "卢俊义", "吴用", "公孙胜"] 23 | name_list.extend(temp_list) 24 | 25 | # 4. 删除 26 | # remove 可以从列表中删除指定数据 27 | name_list.remove("李四") 28 | # pop 默认可以将列表最后一个元素删除 29 | name_list.pop() 30 | # pop 可以指定要删除元素的索引 31 | name_list.pop(1) 32 | # clear 清空整个列表 33 | name_list.clear() 34 | 35 | print(name_list) -------------------------------------------------------------------------------- /05_高级数据类型/ch_02_del 关键字.py: -------------------------------------------------------------------------------- 1 | name = ["宋江", "卢俊义", "吴用", "公孙胜"] 2 | 3 | # 使用 del 关键字(delete)删除列表元素 4 | # 提示:在日常开发中,要从列表删除数据,建议使用列表提供的方法 5 | del name[3] 6 | 7 | # del 本质上是用来将一个变量从内存中删除 8 | 9 | s = "小明" 10 | del s 11 | # 注意:如果使用 del 关键字将变量从内存中删除 12 | # 后续的代码就不能再使用这个变量了 13 | # print(s) # s is not defined 14 | 15 | print(name) -------------------------------------------------------------------------------- /05_高级数据类型/ch_03_列表的数据统计.py: -------------------------------------------------------------------------------- 1 | name_list = ["张三", "李四", "王五", "张三"] 2 | 3 | # len(length 长度) 函数可以统计列表中元素的总数 4 | list_len = len(name_list) 5 | print("列表中包含 %d 个元素" % list_len) 6 | 7 | # count 方法可以统计列表中某一个数据出现的次数 8 | count = name_list.count("张三") 9 | print("张三出现了 %d 次" % count) 10 | 11 | # 从列表中删除数据,如果值不存在则报错 12 | name_list.remove("张三") 13 | print(name_list) -------------------------------------------------------------------------------- /05_高级数据类型/ch_04_列表排序.py: -------------------------------------------------------------------------------- 1 | import re 2 | from unicodedata import name 3 | 4 | 5 | name_list = ["songjiang", "lujunyi", "wuyong", "gongsunsheng", "guansheng"] 6 | num_list = [6, 8, 4, 1, 10] 7 | 8 | # 升序 9 | name_list.sort() # sort in place 10 | num_list.sort() 11 | 12 | # 降序 13 | name_list.sort(reverse=True) # 以降序的方式排序 14 | num_list.sort(reverse=True) 15 | 16 | # 逆序 (反转) 17 | name_list.reverse() 18 | num_list.reverse() 19 | 20 | print(name_list) 21 | print(num_list) -------------------------------------------------------------------------------- /05_高级数据类型/ch_05_列表遍历.py: -------------------------------------------------------------------------------- 1 | name_list = ["小李广-花荣", "呼保义-宋江", "玉麒麟-卢俊义", "黑旋风-李逵"] 2 | 3 | # 使用迭代遍历列表 4 | """ 5 | 顺序从列表中依次获取数据,每一次循环过程中,数据都会保存在my_name 这个变量中, 6 | 在循环体内部可以访问当前这一次获取到的数据 7 | """ 8 | for my_name in name_list: 9 | print("我的名字是 %s" % my_name) -------------------------------------------------------------------------------- /05_高级数据类型/ch_06_元组基本使用.py: -------------------------------------------------------------------------------- 1 | info_tuple = ("zhangsan", 18, 1.75) 2 | 3 | # 1. 取值和取索引 4 | print(info_tuple[0]) 5 | # 已知数据的内容,想得到该数据在元组中的索引 6 | print(info_tuple.index("zhangsan")) 7 | 8 | # 2. 统计计数 9 | print(info_tuple.count("zhangsan")) 10 | # 统计元组中包含元素的个数 11 | print(len(info_tuple)) -------------------------------------------------------------------------------- /05_高级数据类型/ch_07_元组遍历.py: -------------------------------------------------------------------------------- 1 | from distutils.log import info 2 | 3 | 4 | info_tuple = ("宋江", "及时雨", "天魁星") 5 | 6 | # 使用迭代遍历元组 7 | for my_info in info_tuple: 8 | # 使用格式化字符串拼接 my_info 这个变量不方便! 9 | # 因为元组中通常保存的数据类型是不同的! 10 | print(my_info) 11 | -------------------------------------------------------------------------------- /05_高级数据类型/ch_08_格式化字符串.py: -------------------------------------------------------------------------------- 1 | info_tuple = ("小明", 21, 1.85) 2 | 3 | # 格式化字符串后面的 `()` 本质上就是元组 4 | print("%s 年龄是 %d 身高是 %.2f" % info_tuple) 5 | 6 | info_str = "%s 年龄是 %d 身高是 %.2f" % info_tuple 7 | print(info_str) -------------------------------------------------------------------------------- /05_高级数据类型/ch_09_字典的定义.py: -------------------------------------------------------------------------------- 1 | # 字典是一个无序的数据集合 2 | xiaoming = { 3 | "name":"宋江", 4 | "绰号":"及时雨", 5 | "地位":"梁山统领三代目", 6 | "星宿":"天魁星" 7 | } 8 | 9 | print(xiaoming) -------------------------------------------------------------------------------- /05_高级数据类型/ch_10_字典基本使用.py: -------------------------------------------------------------------------------- 1 | d = {"姓名":"燕青", "绰号":"浪子"} 2 | 3 | # 1.取值 4 | print(d["姓名"]) 5 | # 在取值的时候,如果指定的 key 不存在,程序会报错! 6 | 7 | # 2.增加/修改 8 | # 如果 key 不存在,会新增键值对;如果存在,会修改键值对 9 | d["姓名"] = "柴进" 10 | d["别名"] = "小旋风" 11 | 12 | # 3.删除 13 | # 在删除指定键值对的时候,如果指定的 key 不存在,程序会报错! 14 | # 返回删除的键对应的值 15 | print(d.pop("绰号")) 16 | 17 | print(d) -------------------------------------------------------------------------------- /05_高级数据类型/ch_11_字典的其他操作.py: -------------------------------------------------------------------------------- 1 | d = {"姓名":"燕青", "绰号":"小乙哥"} 2 | 3 | # 1.统计键值对数量 4 | print(len(d)) 5 | 6 | # 2.合并字典 7 | temp_dict = {"上司":"卢俊义", "绰号":"浪子"} 8 | d.update(temp_dict) 9 | # 注意:如果被合并的字典中包含已经存在的键值对,会覆盖原有的键值对 10 | 11 | # 3.清空字典 12 | d.clear() 13 | 14 | print(d) -------------------------------------------------------------------------------- /05_高级数据类型/ch_12_字典的遍历.py: -------------------------------------------------------------------------------- 1 | xiaoming_dict = {"name":"小明", 2 | "qq":"123456", 3 | "phone":"10086"} 4 | 5 | # 迭代遍历字典 6 | # 变量k是每一次循环中,获取到的键值对的key 7 | for k in xiaoming_dict: 8 | print("%s - %s" % (k, xiaoming_dict[k])) 9 | -------------------------------------------------------------------------------- /05_高级数据类型/ch_13_字典的应用场景.py: -------------------------------------------------------------------------------- 1 | # 使用多个键值对,存储描述一个 `物体` 的相关信息--描述更复杂的数据信息 2 | # 将多个字典放在一个列表中,再进行遍历,在循环体内部针对每一个字典进行相同的处理 3 | card_list = [ 4 | {"name":"xiaoming", 5 | "qq":"123456", 6 | "phone":"10086"}, 7 | {"name":"zhangsan", 8 | "qq":"456789", 9 | "phone":"10010"} 10 | ] 11 | 12 | for card_info in card_list: 13 | print(card_info) -------------------------------------------------------------------------------- /05_高级数据类型/ch_14_字符串定义和遍历.py: -------------------------------------------------------------------------------- 1 | str1 = "hello python" 2 | str2 = "我的外号是'小花荣'" 3 | 4 | print(str2) # 我的外号是'小花荣' 5 | print(str1[6]) # p 6 | 7 | # 迭代遍历 8 | for char in str1: 9 | print(char, end=" ") -------------------------------------------------------------------------------- /05_高级数据类型/ch_15_字符串统计操作.py: -------------------------------------------------------------------------------- 1 | hello_str = "hello hello" 2 | 3 | # 1.统计字符串长度 4 | print(len(hello_str)) # 11 5 | 6 | # 2.统计某个小字符串出现的次数 7 | print(hello_str.count("llo")) # 2 8 | print(hello_str.count("abc")) # 0 9 | 10 | # 3.某一个字符串出现的位置 11 | print(hello_str.index("llo")) # 2 12 | # 注意:如果使用index方法传递的子字符串不存在,程序会报错! 13 | # print(hello_str.index("abc")) -------------------------------------------------------------------------------- /05_高级数据类型/ch_16_字符串判断方法.py: -------------------------------------------------------------------------------- 1 | # 1.判断空白字符 2 | space_str = " \t\n\r " 3 | print(space_str.isspace()) # True 4 | 5 | # 2.判断字符串中是否只包含数字 6 | # 1>都不能判断小数 7 | # num_str = "1.1" 8 | # 2> unicode 字符串 9 | # num_str = "\u00b2" # \u 表示unicode编码 10 | # 3>中文数字 11 | num_str = "一百零八" 12 | 13 | print(num_str) 14 | print(num_str.isdecimal()) 15 | print(num_str.isdigit()) 16 | print(num_str.isnumeric()) -------------------------------------------------------------------------------- /05_高级数据类型/ch_17_字符串的查找和替换.py: -------------------------------------------------------------------------------- 1 | hello_str = "hello world" 2 | 3 | # 1.判断是否可以指定字符串开始 4 | print(hello_str.startswith("Hello")) 5 | 6 | # 2.判断是否可以指定字符串结束 7 | print(hello_str.endswith("d")) 8 | 9 | # 3.查找指定字符串 10 | # index 同样可以查找指定的字符串在大字符串中的索引 11 | # find 如果指定的字符串不存在,会返回 -1 12 | print(hello_str.find("llo")) # 2 13 | print(hello_str.find("abc")) # -1 14 | 15 | # 4.替换字符串 16 | # replace 执行完成之后,会返回一个新的字符串 17 | # 不会修改原有字符串的内容 18 | print(hello_str.replace("world", "python")) # hello python 19 | print(hello_str) # hello world 20 | -------------------------------------------------------------------------------- /05_高级数据类型/ch_18_字符串的文本对齐.py: -------------------------------------------------------------------------------- 1 | # 要求:顺序并且居中对齐输出以下内容 2 | poem = ["\n\t登鹳雀楼 ", 3 | "王之涣", 4 | "\t白日依山尽", 5 | "黄河入海流", 6 | "欲穷千里目", 7 | "更上一层楼"] 8 | 9 | for p_str in poem: 10 | # 先使用 strip 方法去除字符串中的空白字符 11 | # 再使用 center 方法居中显示文本 12 | print("|%s|" % p_str.strip().center(10, " ")) 13 | -------------------------------------------------------------------------------- /05_高级数据类型/ch_19_字符串拆分和连接.py: -------------------------------------------------------------------------------- 1 | # 要求 2 | # 1.将字符串中的空白字符全部去掉 3 | # 2.再使用 " " 作为分隔符,拼接成一个整齐的字符串 4 | poem_str = "\n登鹳雀楼\t 王之涣 \t 白日依山尽 \t \n 黄河入海流 \t\t 欲穷千里目 \n\n 更上一层楼" 5 | print(poem_str) 6 | 7 | # 1.拆分字符串 8 | poem_list = poem_str.split() 9 | print(poem_list) 10 | 11 | # 2.合并字符串 12 | print(" ".join(poem_list)) -------------------------------------------------------------------------------- /05_高级数据类型/ch_20_for循环语法演练.py: -------------------------------------------------------------------------------- 1 | for num in [1,2,3,4]: 2 | print(num) 3 | if num == 2: 4 | break 5 | else: 6 | # 如果循环体内部使用break 7 | # else 下方的代码不会执行 8 | print("遍历") 9 | print("循环结束") -------------------------------------------------------------------------------- /05_高级数据类型/ch_21_遍历字典的列表.py: -------------------------------------------------------------------------------- 1 | students = [ 2 | {"name":"阿土"}, 3 | {"name":"小李"} 4 | ] 5 | 6 | # 在学员列表中搜索指定的姓名 7 | find_name = "阿乐" 8 | 9 | for stu_dict in students: 10 | print(stu_dict) 11 | if stu_dict["name"] == find_name: 12 | print("找到了 %s" % find_name) 13 | # 如果已经找到,就直接退出循环 14 | break 15 | else: 16 | # 如果希望在搜索列表时,所有的字典检查之后,都没有发现需要搜索的目标 17 | # 还希望得到统一的提示 18 | print("没有找到 %s" % find_name) 19 | print("循环结束") -------------------------------------------------------------------------------- /06.判断语句.md: -------------------------------------------------------------------------------- 1 | #python 2022/8/18 2 | 3 | # 判断(if)语句 4 | 5 | ## 目标 6 | 7 | - 开发中的应用场景 8 | - if语句体验 9 | - if语句进阶 10 | - 综合应用 11 | 12 | ## 01.开发中的应用场景 13 | 14 | 生活中的判断几乎是无处不在的,我们每天都会在做各种各样的选择 15 | 16 | **判断的定义** 17 | 18 | - 如果 条件满足,才能做某件事情 19 | - 如果 条件不满足,就做另一件事情,或者说明也不做 20 | 21 | >正是因为有了判断,才使得程序世界丰富多彩,充满变化! 22 | >**判断语句** 又被称为“分支语句”,正是因为有了判断,才让程序有了很多的分支 23 | 24 | ## 02.if语句体验 25 | 26 | ### 2.1 if判断语句基本语法 27 | 28 | 在 `Python` 中,if语句就是用来进行判断的,格式如下: 29 | 30 | ```python 31 | if 要判断的条件: 32 | 条件成立时,要做的事情 33 | ... 34 | ``` 35 | 36 | >注意:代码的缩进为一个 `Tab` 键,或者 4个空格--建议使用空格 37 | >- 在 Python开发中,Tab和空格不要混用! 38 | 39 | - `if`语句以及缩进部分可以看成是一个**完整的代码块** 40 | 41 | ### 2.2 else处理条件不满足的情况 42 | 43 | **思考** 44 | 45 | 在使用 `if` 判断时,只能做到满足条件是要做的事情,如果需要在 不满足条件的时候,做某些事情,该如何做呢? 46 | 47 | **答案** 48 | 49 | `else`, 格式如下: 50 | 51 | ```python 52 | if 要判断的条件: 53 | 条件成立时,要做的事情 54 | ... 55 | else: 56 | 条件不成立时,要做的事情 57 | ... 58 | ``` 59 | 60 | **注意:** 61 | 62 | - `if` 和 `else` 语句以及各自的缩进部分共同是一个 **完整的代码块** 63 | 64 | ## 03.if语句进阶 65 | 66 | ### 3.1 elif 67 | 68 | - 在开发中,使用 `if` 可以**判断条件** 69 | - 使用 `else` 可以处理 **条件不成立** 的情况 70 | - 但是,如果希望 再增加一些条件,条件不同,需要执行的代码也不同时,就可以使用`elif` 71 | - 语法格式如下: 72 | 73 | ```python 74 | if 条件1: 75 | 条件1满足执行的代码 76 | ... 77 | elif 条件2: 78 | 条件2满足执行的代码 79 | ... 80 | elif 条件3: 81 | 条件3满足执行的代码 82 | ... 83 | else: 84 | 以上条件都不满足时,执行代码 85 | ... 86 | ``` 87 | 88 | **注意** 89 | 90 | 1. **`elif` 和 `else` 都必须和 `if` 联合使用,而不能单独使用** 91 | 2. 可以将 `if`, `elif` 和 `else` 以及各自缩进的diamagnetic,看成一个完整的代码块 92 | 93 | ### 3.2 if的嵌套 94 | 95 | >**elif** 的应用场景是:**同时** 判断 **多个条件** ,所有的条件是 **平级** 的 96 | 97 | - 在开发中,使用 `if` 进行条件判断,如果希望 在条件成立的执行语句中,再增加条件判断,就可以使用 if的嵌套 98 | - **if的嵌套** 的应用场景就是:**再之前条件满足的前提下,再增加额外的判断** 99 | - **if的嵌套** 的语法格式,**除了缩进之外** 和之前的没有区别 100 | - 语法格式如下: 101 | 102 | ```python 103 | if 条件1: 104 | 条件1满足执行的代码 105 | ... 106 | if 条件1基础上的条件2: 107 | 条件2满足时,执行的代码 108 | ... 109 | # 条件2不满足的处理 110 | else: 111 | 条件2不满足时,执行的代码 112 | # 条件1不满足的处理 113 | else: 114 | 条件1不满足时,执行的代码 115 | ``` 116 | 117 | if的嵌套 演练--火车站安检 118 | 119 | 需求 120 | 121 | 1. 定义布尔型变量 `has_ticket` 表示是否有车票 122 | 2. 定义整型变量 `knife_length` 表示到的长度,单位:厘米 123 | 3. 首先检测是否有车票,如果有,才允许进行 案件 124 | 4. 安检时,需要检查刀的长度,判断是都超过20厘米 125 | 126 | - 如果超过20厘米,提示刀的长度,不允许上车 127 | - 如果不超过,安检通过 128 | 129 | 5. 如果没有车票,不允许进入 130 | 131 | ```python 132 | has_ticket = True 133 | knife_length = 15 134 | if has_ticket: 135 | print("车票检查通过,准备开始安检") 136 | if knife_length <= 20: 137 | print("安检通过,祝您旅途愉快") 138 | else: 139 | print("携带道具长度为 %d厘米" % knife_length) 140 | print("不允许上车") 141 | else: 142 | print("请先买票!") 143 | ``` 144 | 145 | ## 04.综合应用--石头剪刀布 146 | 147 | 目标 148 | 149 | 1. 强化 **多个条件** 的 **逻辑运算** 150 | 2. 体会 `import` 导入模块("工具包")的使用 151 | 152 | 需求 153 | 154 | 1. 从控制台输入要出的拳--石头(1)/剪刀(2)/布(3) 155 | 2. 电脑 **随机** 出拳--先假定电脑只会出石头,完成完整代码功能 156 | 3. 比较胜负 157 | 158 | | 序号 | 规则 | 159 | | ---- | ------------ | 160 | | 1 | 石头 胜 剪刀 | 161 | | 2 | 剪刀 胜 布 | 162 | | 3 | 布 胜 石头 | 163 | 164 | ### 4.1 随机数的处理 165 | 166 | - 在 `Python` 中,要使用随机数,首先需要导入 随机数 的 模块--“工具包” 167 | 168 | ```python 169 | import random 170 | ``` 171 | 172 | - 导入模块后,可以直接在 模块名称 后面敲一个 `.` 然后按 `Tab` 键,会提示该模块中包含的函数 173 | - `raddom.randint(a, b)` ,返回 `[a, b]` 之间的整数,包含 `a` 和 `b` 174 | - 例如: 175 | 176 | ```python 177 | random.randint(12, 20) # 生成的随机数n:12 <= n <= 20 178 | random.randint(20, 20) # 结果永远是 20 179 | random.randint(20, 10) # 该语句是错误的,下限必须小于上限 180 | ``` 181 | 182 | ```python 183 | # 导入随机工具包 184 | import random 185 | player = int(input("请输入您出的拳 石头(1)/剪刀(2)/布(3): ")) 186 | computer = random.randint(1, 3) 187 | print("玩家出的拳头是 %d - 电脑出的拳是 %d" % (player, computer)) 188 | # 玩家胜利的三种情况 189 | if ((player == 1 and computer == 2) 190 | or (player == 2 and computer == 3) 191 | or (player == 3 and computer == 1)): 192 | print("玩家赢了!") 193 | # 平局 194 | elif player == computer: 195 | print("平居") 196 | # 电脑获胜 197 | else: 198 | print("电脑获胜!") 199 | ``` 200 | 201 | # 运算符 202 | 203 | ## 目标 204 | 205 | - 比较(关系)运算符 206 | - 逻辑运算符 207 | - 运算符的优先级 208 | 209 | ## 01.比较(关系)运算符 210 | 211 | | 运算符 | 描述 | 212 | | ------ | ---- | 213 | | `==` |检查两个操作数的值是否 **相等**,如果是,则条件成立,返回True | 214 | | `!=` |检查两个操作数的值是否 **不相等**,如果是,则条件成立,返回True | 215 | | `>` |检测左操作数的值是否 **大于** 右操作数的值,如果是,则条件成立,返回True | 216 | | `<` |检测左操作数的值是否 **小于** 右操作数的值,如果是,则条件成立,返回True | 217 | | `>=` |检测左操作数的值是否 **大于等于** 右操作数的值,如果是,则条件成立,返回True | 218 | | `<=` |检测左操作数的值是否 **小于等于** 右操作数的值,如果是,则条件成立,返回True | 219 | 220 | >Python 2.x 中判断 **不等于** 还可以使用 `<>` 运算符 221 | 222 | ## 02.逻辑运算 223 | 224 | - 在程序开发中,通常 **在判断条件时**,回需要同时判断多个条件 225 | - 只有多个条件都满足,才能执行后续代码,这个时候需要使用到 **逻辑运算符** 226 | - 逻辑运算符 可以把 多个条件 按照 逻辑 进行 连接 变成 更复杂的条件 227 | - Python 中的 逻辑运算符 包括:`与and`, `或or`, `非not` 三种 228 | 229 | ### 2.1 and 230 | 231 | ```md 232 | 条件1 and 条件2 233 | ``` 234 | 235 | - **与/并且** 236 | - 两个条件同时满足,返回`True` 237 | - 只要有一个不满足,就返回`False` 238 | 239 | ### 2.2 or 240 | 241 | ```md 242 | 条件1 or 条件2 243 | ``` 244 | 245 | - **或/或者** 246 | - 两个条件只要有一个满足,返回 `True` 247 | - 两个都不满足,返回 `False` 248 | 249 | ### 2.3 not 250 | 251 | ```md 252 | not 条件 253 | ``` 254 | 255 | - **非/不是** 256 | - 将条件取反,如果条件为假,则返回 `True` 257 | 258 | 逻辑运算演练 259 | 260 | 1. 练习1:定义一个整数变量 `age` ,缩写代码判断年龄是否正确 261 | 262 | - 要求人的年龄在0-120之间 263 | 264 | 2. 练习2:定义两个整数变量 `python_score`, `c_score` ,缩写代码判断成绩 265 | 266 | - 要求只要有一门成绩 > 60分就及格 267 | 268 | 3. 练习3:定义一个布尔型变量,`is_employee`,缩写代码判断是否是公司员工 269 | 270 | - 如果不是提示不允许入内 271 | 272 | ```python 273 | age = int(input("请输入年龄:")) 274 | if age >= 0 and age <= 120: 275 | print("legal") 276 | 277 | python_score = int(input("Python成绩: ")) 278 | c_score = int(input("C语言成绩: ")) 279 | if python_score >= 60 or c_score > 60: 280 | print("pass") 281 | 282 | is_employee = bool(input("是否是本公司员工: ")) 283 | if is_employee: 284 | print("Welcome!") 285 | else: 286 | print("Worn!") 287 | ``` -------------------------------------------------------------------------------- /06_名片管理系统/__pycache__/cards_tools.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/06_名片管理系统/__pycache__/cards_tools.cpython-38.pyc -------------------------------------------------------------------------------- /06_名片管理系统/cards_main.py: -------------------------------------------------------------------------------- 1 | # 无限循环,由用户决定何时结束 2 | import cards_tools 3 | while True: 4 | 5 | # 显示功能菜单 6 | cards_tools.show_menu() 7 | 8 | action_str = input("请选择希望执行的操作:") 9 | print("您选择的操作是 【%s】" % action_str) 10 | 11 | # 1,2,3 针对名片的操作 12 | if action_str in ["1", "2", "3"]: 13 | # 如果在程序开发时,不希望立刻编写分支内部的代码 14 | # 可以使用 pass 关键字,表示一个占位符,能够保证程序结构正确! 15 | # 程序运行时,pass 关键字不会执行任何的操作 16 | 17 | # 新增名片 18 | if action_str == "1": 19 | cards_tools.new_card() 20 | # 显示全部 21 | elif action_str == "2": 22 | cards_tools.show_all() 23 | # 查询名片 24 | else: 25 | cards_tools.search_card() 26 | # 0 退出系统 27 | elif action_str == "0": 28 | print("-" * 50) 29 | print("退出系统") 30 | print("欢迎再次使用【名片管理系统】") 31 | # pass 32 | break 33 | # 其他内容输入错误,提示用户 34 | else: 35 | print("您输入的不正确,请重新选择") 36 | -------------------------------------------------------------------------------- /06_名片管理系统/cards_tools.py: -------------------------------------------------------------------------------- 1 | # 记录所有的名片字典 2 | card_list = [] 3 | 4 | 5 | def show_menu(): 6 | """显示菜单""" 7 | print("*" * 50) 8 | print("欢迎使用 【名片管理系统】V1.0") 9 | print() 10 | print("1. 新增名片") 11 | print("2. 显示全部") 12 | print("3. 搜索名片") 13 | print() 14 | print("0. 退出系统") 15 | print("*" * 50) 16 | 17 | 18 | def new_card(): 19 | """新增名片""" 20 | print("-" * 50) 21 | print("新增名片") 22 | # 1.提示用户输入名片的详细信息 23 | name_str = input("请输入姓名:") 24 | phone_str = input("请输入电话:") 25 | qq_str = input("请输入QQ:") 26 | email_str = input("请输入邮箱:") 27 | 28 | # 2.使用用户输入的信息建立一个名片字典 29 | card_dict = {"name": name_str, "phone": phone_str, 30 | "qq": qq_str, "email": email_str} 31 | 32 | # 3.及那个名片字典添加到列表中 33 | card_list.append(card_dict) 34 | print(card_list) 35 | 36 | # 4.提示用户添加成功 37 | print("添加 %s 的名片成功" % name_str) 38 | 39 | 40 | def show_all(): 41 | """显示所有名片""" 42 | print("-" * 50) 43 | print("显示所有名片") 44 | 45 | # 判断是否存在名片记录,如果没有,提示用户且返回 46 | if len(card_list) == 0: 47 | print("当前名片没有任何记录,请使用新增功能添加名片!") 48 | # return 可以返回一个函数执行结果 49 | # 下方的代码不会被执行 50 | # 如果 return 后面没有任何的内容,表示会返回到调用函数的位置 51 | # 并且不会返回任何的结果 52 | return 53 | 54 | # 打印表头 55 | for name in ["姓名", "电话", "QQ", "邮箱"]: 56 | print(name, end="\t\t") 57 | print() 58 | # 打印分隔线 59 | print("=" * 50) 60 | # 遍历名片列表依次输出字典信息 61 | for card_dict in card_list: 62 | # print(card_dict) 63 | print("%s\t\t%s\t\t%s\t\t%s" % (card_dict["name"], card_dict["phone"], 64 | card_dict["qq"], card_dict["email"])) 65 | 66 | 67 | def search_card(): 68 | """搜索名片""" 69 | print("-" * 50) 70 | print("搜索名片") 71 | 72 | # 1.提示用户输入要搜索的姓名 73 | find_name = input("请输入要搜索的姓名:") 74 | # 2.遍历名片列表,查询要搜索的姓名,如果没有找到,需要提示用户 75 | for card_dict in card_list: 76 | if card_dict["name"] == find_name: 77 | print("姓名\t\t电话\t\tQQ\t\t邮箱") 78 | print("=" * 50) 79 | print("%s\t\t%s\t\t%s\t\t%s" % (card_dict["name"], card_dict["phone"], 80 | card_dict["qq"], card_dict["email"])) 81 | 82 | # 针对找到的名片进行修改/删除操作 83 | deal_card(card_dict) 84 | 85 | break 86 | else: 87 | print("抱歉,没有找到 %s" % find_name) 88 | 89 | 90 | def deal_card(find_dict): 91 | """处理查找到的名片""" 92 | action_str = input("请输入您想执行的操作" 93 | "[1] 修改 [2] 删除 [3] 返回上级菜单:") 94 | if action_str == "1": 95 | find_dict["name"] = input_card_info(find_dict["name"], "姓名【回车不修改】: ") 96 | find_dict["phone"] = input_card_info(find_dict["phone"], "电话【回车不修改】: ") 97 | find_dict["qq"] = input_card_info(find_dict["qq"], "QQ号【回车不修改】: ") 98 | find_dict["email"] = input_card_info(find_dict["email"], "邮箱【回车不修改】: ") 99 | print("修改成功") 100 | elif action_str == "2": 101 | card_list.remove(find_dict) 102 | print("删除成功") 103 | 104 | 105 | def input_card_info(dict_value, tip_message): 106 | """修改名片信息 107 | :param dict_value: 字典中原有的值 108 | :param tip_message: 输入的提示信息 109 | :return: 如果用户输入了内容,就返回内容,否则返回字典中原有的值 110 | """ 111 | # 1.提示用户输入内容 112 | result_str = input(tip_message) 113 | # 2.针对用户的输入进行判断,如果用户输入内容,直接返回结果 114 | if len(result_str) > 0: 115 | return result_str 116 | # 3.如果用户没有输入内容,返回字典中原有的值 117 | else: 118 | return dict_value 119 | -------------------------------------------------------------------------------- /07.循环.md: -------------------------------------------------------------------------------- 1 | #python 2022/8/19 2 | 3 | # 循环 4 | 5 | ## 目标 6 | 7 | - 程序的三大流程 8 | - while循环基本使用 9 | - break 和 continue 10 | - while 循环嵌套 11 | 12 | ## 01.程序的三大流程 13 | 14 | - 在程序开发中,一共有三种流程方式 15 | - **顺序** -- **从上向下**,顺序执行代码 16 | - **分支** -- 根据条件判断,决定执行代码的 **分支** 17 | - **循环** -- 让 **特定代码 重复** 执行 18 | 19 | ![程序的三大流程](img/img5.jpg) 20 | 21 | ## 02.while循环基本使用 22 | 23 | - 循环的作用就是让 **指定的代码** 重复的执行 24 | - `while` 循环最常用的应用场景就是 **让执行的代码 按照 指定的次数 重复**执行 25 | 26 | ### 2.1 while 语句基本语法 27 | 28 | ``` 29 | 初始条件设置 - 通常是重复执行的 计数器 30 | 31 | while 条件(判断 计数器 是否达到 目标次数): 32 | 条件满足时,做的事情1 33 | 条件满足时,做的事情2 34 | ...(省略)... 35 | 处理条件(计数器 + 1) 36 | ``` 37 | 38 | 注意 39 | 40 | - `while` 语句以及缩进部分是一个 **完整的代码块** 41 | - 循环结束后,之前定义的计数器条件的数值是依旧存在的 42 | 43 | **死循环** 44 | 45 | >由于程序员的原因,忘记 在循环内部 修改循环的判断条件,导致循环持续执行,程序无法终止! 46 | 47 | ### 2.2 赋值运算符 48 | 49 | - 在 Python 中,使用 `=` 可以给变量赋值 50 | - 在算术运算时,为了简化代码的编写,`Python`还提供了一系列的 与 算数运算符 对应的 赋值运算符 51 | - 注意:**赋值运算符中间不能使用空格** 52 | 53 | | 运算符 | 描述 | 实例 | 54 | | ------ | -------------------- | ---- | 55 | | `=` | 简单的赋值运算符 | `c = a + b` 将 `a + b` 的运算符结果赋值为 `c` | 56 | | `+=` | 加法赋值运算符 | `i += 1` 等价于 `i = i + 1` | 57 | | `-=` | 减法赋值运算符 | | 58 | | `*=` | 乘法赋值运算符 | | 59 | | `/=` | 除法赋值运算符 | | 60 | | `//=` | 取整除赋值运算符 | | 61 | | `%=` | 取模(余数)赋值运算符 | | 62 | | `**=` | 幂赋值运算符 | | 63 | 64 | ### 2.3 Python 中的计数方法 65 | 66 | 常见的计数方法有两种,可以分别称为 67 | 68 | - **自然计数法(从 1 开始)** -- 更符合人类的习惯 69 | - **程序计数法(从 0 开始)** -- 几乎所有的程序语言都选择从0开始计数 70 | 71 | 因此,在编写程序,应该尽量养成习惯;**除非需求的特殊要求,否则 循环 的计数都从0开始** 72 | 73 | ### 2.4 循环计算 74 | 75 | >在程序开发中,通常会遇到 利用循环 重复计算 的需求 76 | 77 | 遇到这种需求,可以: 78 | 79 | 1. 在 `while` 上定义一个变量,用于 **存放最终计算结果** 80 | 2. 在循环体内部,每次循环都用 **最新的计算结果,更新** 之前定义的变量 81 | 82 | 需求 83 | 84 | - 计算 0~100 之间所有数字的累计求和结果 85 | 86 | ```python 87 | # 计算 0!100 之间所有数字的累计求和结果 88 | # 0. 定义最终结果的变量 89 | result = 0 90 | # 1. 定义一个整数的变量记录循环的次数 91 | i = 0 92 | 93 | # 2. 开始循环 94 | while i <= 100: 95 | print(i) 96 | # 每一次循环,都让 result 这个变量和 i 这个计数器相加 97 | result += i 98 | i += 1 99 | print("0~100 之间的数字求和结果 = %d" % result) 100 | ``` 101 | 102 | 需求进阶 103 | 104 | - 计算 0~100 之间 所有 **偶数** 的累计求和结果 105 | 106 | 开发步骤 107 | 108 | 1. 编写循环 确认 要计算的数字 109 | 2. 添加 结果 变量,在循环内部 处理计算结果 110 | 111 | ```python 112 | # 计算 0~100 之间 所有 偶数 的累计求和结果 113 | i, sum = 0, 0 114 | while i <= 100: 115 | # 判断变量 i 中的数值,是否是一个偶数 116 | # 偶数 i % 2 == 0 117 | # 奇数 i % 2 != 0 118 | if i % 2 == 0: 119 | print(i) 120 | sum += i 121 | i += 1 122 | print("sum = %d" % sum) 123 | ``` 124 | 125 | ## 03. break 和 continue 126 | 127 | > `break` 和 `continue` 是专门在循环中使用的关键字 128 | 129 | - `break` 某一条件满足时,退出循环,不再执行后续重复的代码 130 | - `continue` 某一条件满足时,不执行后续重复的代码 131 | 132 | > `break` 和 `continue` 只针对 **当前所在循环** 有效 133 | 134 | ```python 135 | i = 0 136 | while i < 10: 137 | # break 某一条件满足时,退出循环,不再执行后续重复的代码 138 | # i == 3 139 | if i == 3: 140 | break 141 | print(i) 142 | i += 1 143 | 144 | print("over") 145 | ``` 146 | 147 | ```python 148 | i = 0 149 | # 输出 0~10 不包括3 150 | while i < 10: 151 | # - `continue` 某一条件满足时,不执行后续重复的代码 152 | # i == 3 153 | if i == 3: 154 | # 注意:在循环中,如果使用 continue 这个关键字 155 | # 在使用关键字之前,需要确认循环的计数是否修改, 156 | # 否则可能会导致死循环 157 | i += 1 158 | continue 159 | 160 | print(i) 161 | i += 1 162 | 163 | print("over") 164 | ``` 165 | 166 | ## 04. while 循环嵌套 167 | 168 | ### 4.1 循环嵌套 169 | 170 | - `while` 嵌套就是:`while` 里面还有 `while` 171 | 172 | ``` 173 | while 条件1: 174 | 条件满足时,做的事情1 175 | 条件满足时,做的事情2 176 | ...(省略)... 177 | 178 | while 条件2: 179 | 条件满足时,做的事情1 180 | 条件满足时,做的事情2 181 | ...(省略)... 182 | 处理条件2 183 | 处理条件1 184 | ``` 185 | 186 | ### 4.2 循环嵌套演练 -- 九九乘法表 187 | 188 | 第一步:用嵌套打印小星星 189 | 190 | 需求 191 | 192 | - 在控制台连续输出五行 `*` ,每一行星号的数量次数递增 193 | 194 | ``` 195 | * 196 | ** 197 | *** 198 | **** 199 | ***** 200 | ``` 201 | 202 | - 使用字符串 `*` 打印 203 | 204 | ```python 205 | # 1.定义一个计数器变量,从数字1开始,循环会比较方便 206 | row = 1 207 | 208 | # 2.开始循环 209 | while row <= 5: 210 | print("*" * row) 211 | row += 1 212 | ``` 213 | 214 | 第 2 步:使用循环嵌套打印小星星 215 | 216 | - 默认情况下,`print` 函数输出内容之后,会自动在内容末尾增加换行 217 | - 如果不希望末尾增加换行,可以在 `print` 函数输出内容的后面增加 `, end=""` 218 | - 其中 `""` 中间可以指定 `print` 函数输出内容之后,继续希望显示的内容 219 | - 语法格式如下: 220 | 221 | ```python 222 | # 向控制台输出内容结束之后,不会换行 223 | print("*", end="") 224 | 225 | # 单纯的换行 226 | print("") 227 | ``` 228 | 229 | >`end=""` 表示向控制台输出内容结束之后,不会换行 230 | 231 | 假设 `python` 没有提供 字符串的 `*` 操作,拼接字符串 232 | 233 | 开发步骤 234 | 235 | - 1> 完成5行内容的简单输出 236 | - 2> 分析每行内部的 `*` 应该如何处理? 237 | 238 | ```python 239 | row = 1 240 | while row <= 5: 241 | 242 | # 每一行要打印的星星就是和当前的行数是一致的 243 | # 增加一个小的循环,专门负责当前行中,每一列的星星显示 244 | # 1. 定义一个列计数器变量 245 | col = 1 246 | # 2.开始循环 247 | while col <= row: 248 | print("*", end="") 249 | col += 1 250 | print() # 每打印一行换行一次 251 | row += 1 252 | ``` 253 | 254 | 第 3 步:九九乘法表 255 | 256 | 需求 输出 九九乘法表,格式 `略` 257 | 258 | ```python 259 | # 打印九九乘法表 260 | row = 1 261 | while row <= 9: 262 | col = 1 263 | while col <= row: 264 | print("%d * %d = %d" % (col, row, row * col), end="\t") # 使用横向制表位对齐文本 265 | col += 1 266 | print() 267 | row += 1 268 | ``` 269 | 270 | ## 05 字符串中的转义字符 271 | 272 | - `\t` 在控制台输出一个 **制表符**,协助在输出文本时 **垂直方向** 保持对齐 273 | - `\n` 在控制台输出一个 **换行符** 274 | 275 | >**制表符** 的功能是在不适用表格的情况下在 **垂直方向** 按列对齐文本 276 | 277 | | 转义字符 | 描述 | 278 | | -------- | ---------- | 279 | | `\\` | 反斜杠符号 | 280 | | `\'` | 单引号 | 281 | | `\"` | 双引号 | 282 | | `\t` | 横向制表符 | 283 | | `\r` | 回车 | 284 | | `\n` | 换行 | 285 | -------------------------------------------------------------------------------- /07_语法进阶/ch_01_引用.py: -------------------------------------------------------------------------------- 1 | def test(num): 2 | 3 | print("在函数内部 %d 对应的内存地址是 %d" % (num, id(num))) 4 | 5 | # 1>定义一个字符串变量 6 | result = "hello" 7 | print("函数要返回数据的内存是 %d" % id(result)) 8 | 9 | # 2>将字符串变量返回,返回的是数据的引用,而不是数据本身 10 | return result 11 | # 1.定义一个数字的变量 12 | a = 10 13 | 14 | # 数据的地址本质上就是一个数字 15 | print("a 变量保存数据的内存地址是 %d" % id(a)) 16 | 17 | 18 | # 2.调用 test 函数,本质上传递的是保存实参数据的引用,而不是实参保存的数据 19 | # 注意:如果函数有返回值,但是没有定义变量接收 20 | # 程序不会报错,但是无法获得返回结果 21 | r = test(a) 22 | 23 | print("%s 的内存地址是 %d" % (r, id(r))) -------------------------------------------------------------------------------- /07_语法进阶/ch_02_局部变量.py: -------------------------------------------------------------------------------- 1 | def demo1(): 2 | 3 | # 定义一个局部变量 4 | # 1> 出生:执行了下方代码之后,,才会被创建 5 | # 2> 死亡:函数执行完成之后 6 | num = 10 7 | print("在demo1函数内部的变量是 %d" % num) 8 | 9 | 10 | def demo2(): 11 | 12 | # 不能在其他函数内使用 13 | # print("%d" % num) 14 | pass 15 | 16 | # 在函数内部定义的变量,不能再其他位置使用 17 | # print("%d" % num) 18 | 19 | demo1() 20 | demo2() -------------------------------------------------------------------------------- /07_语法进阶/ch_03_全局变量.py: -------------------------------------------------------------------------------- 1 | # 全局变量 2 | num = 10 3 | 4 | def demo1(): 5 | 6 | print("demo1() ==> %d" % num) 7 | 8 | 9 | def demo2(): 10 | 11 | print("demo2() ==> %d" % num) 12 | 13 | demo1() 14 | demo2() -------------------------------------------------------------------------------- /07_语法进阶/ch_04_全局变量.py: -------------------------------------------------------------------------------- 1 | # 全局变量 2 | num = 10 3 | 4 | def demo1(): 5 | 6 | # 修改全局变量的值 7 | # 在 python 中,不允许直接修改全局变量的值 8 | # 如果使用赋值语句,会在函数内部,定义一个局部变量 9 | num = 99 10 | print("demo1() ==> %d" % num) 11 | 12 | 13 | def demo2(): 14 | 15 | print("demo2() ==> %d" % num) 16 | 17 | demo1() 18 | demo2() -------------------------------------------------------------------------------- /07_语法进阶/ch_05_修改全局变量.py: -------------------------------------------------------------------------------- 1 | # 全局变量 2 | num = 10 3 | 4 | def demo1(): 5 | 6 | # 希望修改全局变量的值 - 使用 global 声明一下变量即可 7 | # global 关键字会告诉解释器后面的变量是一个全局变量 8 | # 再使用赋值语句时,就不会创建局部变量 9 | global num 10 | num = 99 11 | print("demo1() ==> %d" % num) 12 | 13 | 14 | def demo2(): 15 | 16 | print("demo2() ==> %d" % num) 17 | 18 | demo1() 19 | demo2() -------------------------------------------------------------------------------- /07_语法进阶/ch_06_全局变量的位置.py: -------------------------------------------------------------------------------- 1 | # 注意:再开发时,应该把模块中所有的全局变量 2 | # 定义再所有函数上方,就可以保证所有函数 3 | # 都能够正常访问到每一个全局变量 4 | num = 10 5 | 6 | def demo(): 7 | 8 | 9 | print("%d" % num) 10 | print("%s" % s) 11 | print("%d" % c) 12 | 13 | # 再定义一个全局变量 14 | s = "hello python" 15 | 16 | demo() 17 | 18 | # 再定义一个全局变量 19 | c = 30 # 在调用函数后定义全局变量,会导致程序报错 -------------------------------------------------------------------------------- /07_语法进阶/ch_07_全局变量命名.py: -------------------------------------------------------------------------------- 1 | gl_num = 10 2 | gl_s = "hello python" 3 | gl_c = 3 4 | 5 | 6 | def demo(): 7 | num = 1 8 | print(num) 9 | print(gl_s) 10 | print(gl_c) 11 | -------------------------------------------------------------------------------- /07_语法进阶/ch_08_多个返回值.py: -------------------------------------------------------------------------------- 1 | def measure(): 2 | """测量温度""" 3 | 4 | temp = 39 5 | wetness = 50 6 | 7 | # 元组 - 可以包含多个数据,因此可以使用元组让函数一次返回多个值 8 | # 如果函数返回的类型是元组,小括号可以省略 9 | # return (temp, wetness) 10 | return temp, wetness 11 | 12 | # 元组 13 | res = measure() 14 | print(res) 15 | 16 | # 需要单独的处理温度或者湿度 17 | print(res[0]) 18 | print(res[1]) 19 | 20 | # 如果函数返回的类型是元组,同时希望单独的处理元组中的元素 21 | # 可以使用多个变量,一次接受函数的返回结果 22 | gl_temp, gl_wetness = measure() 23 | print(gl_temp) 24 | print(gl_wetness) -------------------------------------------------------------------------------- /07_语法进阶/ch_09_交换数字.py: -------------------------------------------------------------------------------- 1 | a = 6 2 | b = 100 3 | 4 | # 1.使用其他变量 5 | c = a 6 | a = b 7 | b = c 8 | print(a, b) 9 | 10 | # 2.不使用其他的变量 11 | a = a + b 12 | b = a - b 13 | a = a - b 14 | 15 | print(a, b) 16 | 17 | # 3. 利用元组,等号右边是一个元组,只是将小括号省略了 18 | a, b = b, a 19 | print(a, b) -------------------------------------------------------------------------------- /07_语法进阶/ch_10_参数传递.py: -------------------------------------------------------------------------------- 1 | def demo(num, num_list): 2 | 3 | print("函数内部的代码") 4 | 5 | # 在函数内部,针对参数使用赋值语句 6 | num = 100 7 | num_list = [1,2,3] 8 | print(num) 9 | print(num_list) 10 | print("函数执行完成") 11 | 12 | 13 | gl_num = 99 14 | gl_list = [4, 5, 6] 15 | demo(gl_num, gl_list) 16 | print(gl_num) 17 | print(gl_list) -------------------------------------------------------------------------------- /07_语法进阶/ch_11_函数内部通过方法修改可变参数.py: -------------------------------------------------------------------------------- 1 | def demo(num_list: list): 2 | print("函数内部的代码") 3 | 4 | # 使用方法修改列表的内容 5 | num_list.append(9) 6 | 7 | print(num_list) 8 | 9 | print("函数执行完成") 10 | 11 | gl_list = [1, 2, 3] 12 | demo(gl_list) 13 | print(gl_list) -------------------------------------------------------------------------------- /07_语法进阶/ch_12_加等于运算符.py: -------------------------------------------------------------------------------- 1 | def demo(num, num_list: list): 2 | 3 | print("函数开始") 4 | 5 | # 数值 等价于:num = num + num,不会影响外部变量 6 | num += num 7 | 8 | # 列表变量使用 += 不会做相加再赋值的操作 9 | # 不同于 num_list = num_list + num_list 10 | # 本质上是在调用列表的 extend 方法 11 | # num_list.extend(num_list) 12 | num_list += num_list 13 | print(num) 14 | print(num_list) 15 | 16 | print("函数完成") 17 | 18 | 19 | gl_num = 9 20 | gl_list = [1, 2, 3] 21 | demo(gl_num, gl_list) 22 | print(gl_num) 23 | print(gl_list) -------------------------------------------------------------------------------- /07_语法进阶/ch_13_函数的缺省参数.py: -------------------------------------------------------------------------------- 1 | gl_list = [4, 8, 2] 2 | 3 | # 默认按照升序排序 - 较常用 4 | # gl_list.sort() 5 | # print(gl_list) 6 | 7 | # 如果需要降序排序,需要执行reverse参数 8 | gl_list.sort(reverse=True) 9 | print(gl_list) -------------------------------------------------------------------------------- /07_语法进阶/ch_14_函数缺省参数的定义.py: -------------------------------------------------------------------------------- 1 | def print_info(name, gender=True): 2 | 3 | gender_text = "男生" 4 | if not gender: 5 | gender_text = "女生" 6 | print("%s 是 %s" % (name, gender_text)) 7 | 8 | 9 | # 假设班上的同学,男生居多,所以将默认值设置为男生 10 | # 提示:在指定缺省参数的默认值时,应该使用最常见的值作为默认值! 11 | print_info("小明") 12 | print_info("小红", False) -------------------------------------------------------------------------------- /07_语法进阶/ch_15_缺省参数注意点.py: -------------------------------------------------------------------------------- 1 | def print_info(name, title="学生", gender=True): 2 | 3 | """ 4 | :param title:职位 5 | :param name:姓名 6 | :param gender: True 男生 False 女生 7 | """ 8 | gender_text = "男生" 9 | if not gender: 10 | gender_text = "女生" 11 | print("[%s]%s 是 %s" % (title, name, gender_text)) 12 | 13 | 14 | # 假设班上的同学,男生居多,所以将默认值设置为男生 15 | # 提示:在指定缺省参数的默认值时,应该使用最常见的值作为默认值! 16 | print_info("小明") 17 | print_info("小红",gender=False) -------------------------------------------------------------------------------- /07_语法进阶/ch_16_多值参数.py: -------------------------------------------------------------------------------- 1 | def demo(num, *nums, **person): 2 | 3 | print(num) 4 | print(nums) 5 | print(person) 6 | 7 | 8 | demo(1) # 输出:1 () {} 9 | demo(1, 2, 3, 4, 5) # 输出:1, (2, 3, 4, 5) {} 10 | demo(1, 2, 3, 4, 5, name="小明", age=18) # 输出:1, (2,3,4,5) {name="小明",age=18} -------------------------------------------------------------------------------- /07_语法进阶/ch_17_多值参数求和.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | 4 | def sum_numbers(*args): 5 | 6 | num = 0 7 | # 循环遍历 8 | for n in args: 9 | num += n 10 | 11 | print(args) 12 | return num 13 | 14 | 15 | res = sum_numbers(1, 2, 3, 4, 5) 16 | print(res) -------------------------------------------------------------------------------- /07_语法进阶/ch_18_元组和字典的拆包.py: -------------------------------------------------------------------------------- 1 | def demo(*args, **kwargs): 2 | 3 | print(args) 4 | print(kwargs) 5 | 6 | 7 | # 元组/字典变量 8 | gl_num = (1, 2, 3) 9 | gl_dict = {"name":"小明", "age":18} 10 | 11 | # 会将两个参数都传递给 *args 12 | demo(gl_num, gl_dict) 13 | 14 | # 拆包语法,简化元组/自带你变量的传递 15 | demo(*gl_num, **gl_dict) 16 | 17 | # 等价于 18 | demo(1, 2, 3, name="小明", age=18) -------------------------------------------------------------------------------- /07_语法进阶/ch_19_递归函数的特点.py: -------------------------------------------------------------------------------- 1 | def print_num(num): 2 | 3 | print(num) 4 | # 递归的出口,当参数满足某个条件时,不再执行函数 5 | if num == 1: 6 | return 7 | 8 | # 自己调用自己 9 | print_num(num - 1) 10 | print("完成 %d" % num) 11 | 12 | 13 | print_num(3) -------------------------------------------------------------------------------- /07_语法进阶/ch_20_递归求和.py: -------------------------------------------------------------------------------- 1 | # 1. 定义一个函数 `sum_numbers` 2 | # 2. 能够接受一个 `num` 的整数参数 3 | # 3. 计算 `1+2+……num` 的结果 4 | 5 | def sum_numbers(num): 6 | 7 | # 1.出口 8 | if num == 1: 9 | return 1 10 | 11 | # 2.数字的累加 num + (1 2 3 ... num-1) 12 | # 假设 sum_numbers 能够正确处理 1 2 ... num-1 13 | return num + sum_numbers(num-1) 14 | 15 | 16 | res = sum_numbers(5) 17 | print(res) -------------------------------------------------------------------------------- /08.函数.md: -------------------------------------------------------------------------------- 1 | #python 2022/8/20 2 | 3 | # 函数基础 4 | 5 | ## 目标 6 | 7 | - 函数的快速体验 8 | - 函数的基本使用 9 | - 函数的参数 10 | - 函数的返回值 11 | - 函数的嵌套调用 12 | - 在模块中定义函数 13 | 14 | ## 01.函数的快速体验 15 | 16 | ### 1.1 快速体验 17 | 18 | - 所谓 **函数**,就是把 **具有独立功能的代码块** 组织为一个小模块,在需要的时候 **调用** 19 | - 函数的使用包含两个步骤: 20 | 21 | 1. **定义函数** -- **封装** 独立的功能 22 | 2. **调用函数** -- 享受 **封装** 的成果 23 | 24 | - **函数的作用**,在于开发程序时,使用函数可以提高缩写的效率以及代码的 **重用** 25 | 26 | **演练步骤** 27 | 28 | 1. 新建 `04_函数` 项目 29 | 2. 复制之前完成的 乘法表 文件 30 | 3. 修改文件,增加函数定义 `multiple_table():` 31 | 4. 新建另一个文件,使用 `import` 导入并调用函数 32 | 33 | ## 02.函数基本使用 34 | 35 | ### 2.1 函数的定义 36 | 37 | 定义函数的格式如下: 38 | 39 | ``` 40 | def 函数名(): 41 | 函数封装的代码 42 | ... 43 | ``` 44 | 45 | 1. `def` 是英文 `define` 的缩写 46 | 2. **函数名称** 应该能够表达 **函数封装代码** 的功能,方便后续使用 47 | 3. **函数名称** 的命名应该 符合 **标识符的命名规则** 48 | 49 | - 可以由 **字母,下划线 和 数字** 组成 50 | - **不能以数字开头** 51 | - **不能与关键字重名** 52 | 53 | ### 2.2 函数调用 54 | 55 | 调用函数很简单的,通过 `函数名()` 即可完成对函数的调用 56 | 57 | ### 2.3 第一个函数演练 58 | 59 | 需求 60 | 61 | 1. 编写一个打招呼 `say_hello` 的函数,封装三行打招呼的代码 62 | 2. 在函数下方用打招呼的代码 63 | 64 | ```python 65 | name = "小明" 66 | 67 | # Python 解释器知道下方定义了一个函数 68 | def say_hello(): 69 | 70 | print("hello 1") 71 | print("hello 2") 72 | print("hello 3") 73 | 74 | print(name) 75 | 76 | # 只有在程序中,主动调用函数,才会让函数执行 77 | say_hello() 78 | 79 | print(name) 80 | ``` 81 | 82 | >用 单步执行 观察上述代码的执行过程 83 | 84 | - 定义好的函数之后,只表示这个函数封装了一段代码而已 85 | - 如果不主动调用函数,函数是不会主动执行的 86 | 87 | **思考** 88 | 89 | - 能否将 **函数调用** 放在 **函数定义** 的上方? 90 | - 不能! 91 | - 因为在 **使用函数名** 调用函数之前,必须要保证 `Python` 已经知道函数的存在 92 | - 否则控制台会提示 `NameError: name 'say_hello' is not defined` (名称错误:函数名未被定义) 93 | 94 | ### 2.4 PyCharm的调试工具 95 | 96 | - **F8 Step Over** 可以单步执行代码,会把函数调用看作是一行代码直接执行 97 | - **F7 Step Into** 可以单步执行代码,如果是函数,会进入函数内部 98 | 99 | ### 2.5 函数的文档注释 100 | 101 | - 在开发中,如果希望给函数添加注释,应该在 **定义函数** 的下方,使用 **连续的三对引号** 102 | - 在 **连续的三对引号** 之间缩写对函数的说明文字 103 | - 在 **函数调用** 位置,使用快捷键 `Ctrl + Q` 可以查看函数的说明信息 104 | 105 | >注意:因为 **函数体相对比较独立,函数定义的上方**,应该和 **其他代码(包括注释)保留两个空行** 106 | 107 | ## 03.函数的参数 108 | 109 | **演练需求** 110 | 111 | 1. 开发一个 `sum_2_num` 的函数 112 | 2. 函数能够实现 **两个数字的求和** 功能 113 | 114 | 演练代码如下: 115 | 116 | ```python 117 | def sum_2_num(): 118 | """对两个数字的求和""" 119 | 120 | num1 = 10 121 | num2 = 20 122 | res = num1 + num2 123 | print("%d + %d = %d" % (num1, num2, res)) 124 | 125 | sum_2_num() 126 | ``` 127 | 128 | **思考一下存在什么问题** 129 | 130 | >函数智能处理 **固定数值** 的相加 131 | 132 | **如何解决** 133 | 134 | - 如果能够把需要计算的数字,在调用函数时,床底到函数内部就好了 135 | 136 | ### 3.1 函数参数的使用 137 | 138 | - 在函数明的后面的小括号内部填写 **参数** 139 | - 多个参数之间使用 `,` 分隔 140 | 141 | ```python 142 | def sum_2_num(num1, num2): 143 | """对两个数字的求和""" 144 | 145 | res = num1 + num2 146 | print("%d + %d = %d" % (num1, num2, res)) 147 | 148 | sum_2_num(50, 20) 149 | ``` 150 | 151 | ### 3.2 参数的作用 152 | 153 | - **函数** 把 **具有独立功能的代码** 组织为一个小模块,在需要的时候 调用 154 | - **函数的参数**,增加函数的 **通用性**,针对 **相同的数据处理逻辑**,能够 **适应更多的数据** 155 | 156 | 1. 在函数 **内部**,把参数当做 **变量** 使用,进行需要的数据处理 157 | 2. 函数调用时,按照函数定义的**参数顺序**,把 **希望在函数内部处理的数据,通过参数传递** 158 | 159 | ### 3.3 形参和实参 160 | 161 | - **形参** **定义** 函数时,小括号中的参数,是用来**接受参数**用的,在函数内部 **作为变量使用** 162 | - **实参**:**调用** 函数时,小括号中的参数,是用来把数据传递到 **函数内部** 用的 163 | 164 | ## 04.函数的返回值 165 | 166 | - 在程序开发中,有时候,会希望 **一个函数执行结束后,告诉调用者一个结果**,以便调用者针对具体的结果做后续的处理 167 | - **返回值** 是函数完成工作后,**最后** 给调用者的 **一个结果** 168 | - 在函数中使用 `return` 关键字可以返回结果 169 | - 调用函数一方,可以 **使用变量** 来 **接受** 函数的返回结果 170 | 171 | >注意:`return` 表示返回,后续代码都不会被执行 172 | 173 | ```python 174 | def sum_2_num(num1, num2): 175 | """对两个数字求和""" 176 | 177 | return num1 + num2 178 | 179 | # 调用函数,并使用 result 变量接受计算结果 180 | result = sum_2_num(10, 20) 181 | 182 | print("计算结果是 %d" % result) 183 | ``` 184 | 185 | ## 05.函数的嵌套调用 186 | 187 | - 一个函数里面 右调用了 另外一个函数,这就是 函数嵌套调用 188 | - 如果函数 `test2` 中,调用了另外一个函数 `test1` 189 | - 那么执行调用 `test1` 函数时,会把函数 `test1` 中的任务都执行完 190 | - 才会回到 `test2` 中调用函数 `test1` 的位置,继续执行后续的代码 191 | 192 | ```python 193 | def test1(): 194 | 195 | print("*" * 50) 196 | print("test 1") 197 | print("*" * 50) 198 | 199 | def test2(): 200 | 201 | print("-" * 50) 202 | print("test 2") 203 | 204 | test1() 205 | 206 | print("-" * 50) 207 | 208 | test2() 209 | ``` 210 | 211 | **函数嵌套的演练 -- 打印分隔线** 212 | 213 | >体会一下工作中 **需求是多变** 的 214 | 215 | 1. 定义一个 `print_line` 函数能够打印 `*` 组成的 **一条分隔线** 216 | 217 | ```python 218 | def print_line(): 219 | 220 | print("*" * 50) 221 | ``` 222 | 223 | 2. 定义一个函数能够打印 **由任意字符组成** 的分割线 224 | 225 | ```python 226 | def print_line(char): 227 | 228 | print(char * 50) 229 | ``` 230 | 231 | 3. 定义一个函数能够打印 **任意重复次数** 的分隔 线 232 | 233 | ```python 234 | def print_line(char, times): 235 | 236 | print(char * times) 237 | ``` 238 | 239 | 4. 定义一个函数能够打印5行的分隔线,分隔线要求符合3 240 | 241 | >提示:工作中针对需求的变化,应该冷静思考,**不要轻易修改之前已经完成的,能够正常执行的函数!** 242 | 243 | ```python 244 | def print_line(char, times): 245 | 246 | print(char * times) 247 | 248 | def print_lines(c, t): 249 | i = 0 250 | while i < 5: 251 | print_line(c, t) 252 | i += 1 253 | 254 | print_lines("U", 20) 255 | ``` 256 | 257 | ### 5.1 插入文档字符串 258 | 259 | >Insert documentation string stub 260 | >快速注释函数 261 | 262 | ## 06.使用模块中的函数 263 | 264 | >**模块是 Python 程序架构的一个核心概念** 265 | 266 | - **模块** 就好比 **工具包**,要想使用这个工具,就需要导入 **import** 这个模块 267 | - 每一个以扩展名 `.py` 结尾的 `Python` 源代码文件都是一个 **模块** 268 | - 在模块中定义的 **全局变量、函数** 都是模块能够提供给外界直接使用的工具 269 | 270 | ### 6.1 第一个模块体验 271 | 272 | - 新建 `ch_10_分隔线模块.py` 273 | - 复制 `ch_09_打印多行分隔线.py` 中的内容,最后一行 `print` 代码除外 274 | - 增加一个字符串变量 275 | 276 | ```python 277 | name = "Charlie" 278 | ``` 279 | 280 | - 新建 `ch_11_体验模块.py` 文件,并且编写以下代码: 281 | 282 | ```python 283 | import ch_10_分隔线模块 284 | 285 | ch_10_分隔线模块.print_line("M", 6) 286 | 287 | print(ch_10_分隔线模块.name) 288 | ``` 289 | 290 | - 可以 **在一个 Python 文件** 中 **定义 变量 或者 函数** 291 | - 然后在 另外一个文件中 使用 `import` 导入这个模块 292 | - 导入之后,就可以使用 `模块名.变量` / `模块名.函数` 的方式,使用这个模块中定义的变量或者函数 293 | 294 | >**模块** 可以让 **曾经编写过的代码** 方便的被**复用!** 295 | 296 | ### 6.2 模块名也是一个标识符 297 | 298 | - 标识符可以由 字母、下划线 和 数字 组成 299 | - 不能以数字开头 300 | - 不能与关键字重名 301 | 302 | >注意:如果在给 Python 文件起名字是,以数字开头 是无法在 `PyCharm` 中通过导入这个模块的 303 | 304 | ### 6.3 Pyc文件(了解) 305 | 306 | >`C` 是 `compiled` **编译过** 意思 307 | 308 | **操作步骤** 309 | 310 | 1. 浏览程序目录会发现一个 `__pycache__` 的目录 311 | 2. 目录下会有一个 `ch_10_分隔线模块.cpython-38.pyc` 文件,`cpython-38` 表示 `Python` 解释器的版本 312 | 3. 这个 `pyc` 文件是由 Python 解释器将 **模块的源码** 转换为 **字节码** 313 | 314 | - `Python` 这样保存 **字节码** 是作为一种启动 **速度的优化** 315 | 316 | **字节码** 317 | 318 | - `Python` 在解释程序时是分成两个步骤的 319 | 320 | 1. 首先处理源代码,**编译** 生成一个二进制 **字节码** 321 | 2. 再对 **字节码** 进行处理,才会生成 CPU 能够识别的 **机器码** 322 | 323 | - 有了模块的字节码文件之后,下一次运行程序时,如果在 **上次保存字节码之后** 没有修改过源代码,Python 将会加载 `.pyc` 文件并跳过编译这个步骤 324 | - 当 `Python` 重新编译时,它会自动检查源文件和字节码文件的时间数 325 | - 如果修改了源代码,下次程序运行时,字节码将自动重新创建 -------------------------------------------------------------------------------- /08_面向对象基础/ch_01_第一个面向对象.py: -------------------------------------------------------------------------------- 1 | class Cat: 2 | """这是一个猫类""" 3 | 4 | def eat(self): 5 | print("小猫爱吃鱼") 6 | 7 | def drink(self): 8 | print("小猫要喝水") 9 | 10 | 11 | # 创建猫对象 12 | tom = Cat() 13 | 14 | tom.eat() 15 | tom.drink() 16 | 17 | print(tom) 18 | 19 | addr = id(tom) 20 | print("%x" % addr) -------------------------------------------------------------------------------- /08_面向对象基础/ch_02_新建两个对象.py: -------------------------------------------------------------------------------- 1 | class Cat: 2 | """这是一个猫类""" 3 | 4 | def eat(self): 5 | print("小猫爱吃鱼") 6 | 7 | def drink(self): 8 | print("小猫要喝水") 9 | 10 | 11 | # 创建猫对象 12 | tom = Cat() 13 | tom.eat() 14 | tom.drink() 15 | print(tom) 16 | 17 | # 再创建一个猫对象 18 | jerry = Cat() 19 | jerry.eat() 20 | jerry.drink() 21 | print(jerry) 22 | 23 | snow = jerry 24 | print(snow) # 与 jerry 指向同一个地址 -------------------------------------------------------------------------------- /08_面向对象基础/ch_03_设置对象属性.py: -------------------------------------------------------------------------------- 1 | class Cat: 2 | """这是一个猫类""" 3 | 4 | def eat(self): 5 | # 哪一个对象调用方法,self 就是哪一个对象的引用 6 | print("%s 爱吃鱼" % self.name) 7 | 8 | def drink(self): 9 | print("%s 要喝水" % self.name) 10 | 11 | 12 | # 创建猫对象 13 | tom = Cat() 14 | 15 | # 可以使用 .属性名,通过赋值语句就可以了 16 | tom.name = "Tom" 17 | 18 | tom.eat() 19 | tom.drink() 20 | print(tom) 21 | 22 | # 再创建一个猫对象 23 | jerry = Cat() 24 | 25 | jerry.name = "大懒猫" 26 | 27 | jerry.eat() 28 | jerry.drink() 29 | print(jerry) 30 | 31 | snow = jerry 32 | print(snow) # 与 jerry 指向同一个地址 33 | 34 | -------------------------------------------------------------------------------- /08_面向对象基础/ch_04_在外界设置属性的问题.py: -------------------------------------------------------------------------------- 1 | class Cat: 2 | """这是一个猫类""" 3 | 4 | def eat(self): 5 | # 哪一个对象调用方法,self 就是哪一个对象的引用 6 | print("%s 爱吃鱼" % self.name) 7 | 8 | def drink(self): 9 | print("%s 要喝水" % self.name) 10 | 11 | 12 | # 创建猫对象 13 | tom = Cat() 14 | 15 | # 可以使用 .属性名,通过赋值语句就可以了 16 | # tom.name = "Tom" 17 | 18 | tom.eat() 19 | tom.drink() 20 | tom.name = "Tom" -------------------------------------------------------------------------------- /08_面向对象基础/ch_05_初始化方法.py: -------------------------------------------------------------------------------- 1 | class Cat: 2 | """这是一个猫类""" 3 | 4 | def __init__(self): 5 | print("调用初始化方法") 6 | self.name = "Tom" 7 | 8 | def eat(self): 9 | print("%s 爱吃鱼" % self.name) 10 | 11 | # 使用类名()创建对象时,会自动调用初始化方法 __init__ 12 | tom = Cat() 13 | print(tom.name) 14 | tom.eat() -------------------------------------------------------------------------------- /08_面向对象基础/ch_06_利用参数设置属性初始值.py: -------------------------------------------------------------------------------- 1 | class Cat: 2 | """这是一个猫类""" 3 | 4 | def __init__(self, name): 5 | print("调用初始化方法") 6 | self.name = name 7 | 8 | def eat(self): 9 | print("%s 爱吃鱼" % self.name) 10 | 11 | # 使用类名()创建对象时,会自动调用初始化方法 __init__ 12 | tom = Cat("Tom") 13 | print(tom.name) 14 | tom.eat() 15 | 16 | snow = Cat("Snow") 17 | snow.eat() -------------------------------------------------------------------------------- /08_面向对象基础/ch_07___del__方法.py: -------------------------------------------------------------------------------- 1 | class Cat: 2 | 3 | def __init__(self, name): 4 | self.name = name 5 | print("%s 来了" % self.name) 6 | 7 | def __del__(self): 8 | print("%s 走了" % self.name) 9 | 10 | 11 | # tom 是一个全局变量,在程序执行结束时内存被释放 12 | tom = Cat("Tom") 13 | print(tom.name) 14 | 15 | # del 关键字可以删除一个对象 16 | del tom # 在分割线上方输出 __del__方法内容 17 | 18 | print("-" * 50) -------------------------------------------------------------------------------- /08_面向对象基础/ch_08___str__.py: -------------------------------------------------------------------------------- 1 | class Cat: 2 | 3 | def __init__(self, name): 4 | self.name = name 5 | print("%s 来了" % self.name) 6 | 7 | def __del__(self): 8 | print("%s 走了" % self.name) 9 | 10 | def __str__(self): 11 | 12 | # 必须返回一个字符串 13 | return "我是小猫[%s]" % self.name 14 | 15 | # tom 是一个全局变量,在程序执行结束时内存被释放 16 | tom = Cat("Tom") 17 | print(tom) -------------------------------------------------------------------------------- /08_面向对象基础/ch_09_小明爱跑步.py: -------------------------------------------------------------------------------- 1 | class Person: 2 | 3 | def __init__(self, name, weight) -> None: 4 | 5 | # self.属性 = 形参 6 | self.name = name 7 | self.weight = weight 8 | 9 | def __str__(self) -> str: 10 | 11 | return "我的名字叫%s,体重是%.2f" % (self.name, self.weight) 12 | 13 | def run(self): 14 | print("%s 癌跑步,锻炼身体" % self.name) 15 | self.weight -= 0.5 16 | 17 | def eat(self): 18 | print("%s 是吃货,吃完这顿再减肥" % self.name) 19 | self.weight += 1 20 | 21 | 22 | xm = Person("小明", 75) 23 | xm.run() 24 | xm.eat() 25 | 26 | print(xm) -------------------------------------------------------------------------------- /08_面向对象基础/ch_10_小明爱跑步拓展.py: -------------------------------------------------------------------------------- 1 | class Person: 2 | 3 | def __init__(self, name, weight) -> None: 4 | 5 | # self.属性 = 形参 6 | self.name = name 7 | self.weight = weight 8 | 9 | def __str__(self) -> str: 10 | 11 | return "我的名字叫%s,体重是%.2f" % (self.name, self.weight) 12 | 13 | def run(self): 14 | print("%s 爱跑步,锻炼身体" % self.name) 15 | self.weight -= 0.5 16 | 17 | def eat(self): 18 | print("%s 是吃货,吃完这顿再减肥" % self.name) 19 | self.weight += 1 20 | 21 | 22 | xm = Person("小明", 75) 23 | xm.run() 24 | xm.eat() 25 | 26 | print(xm) 27 | 28 | # 小美爱跑步 29 | xiaomei = Person("小美", 45) 30 | xiaomei.eat() 31 | xiaomei.run() 32 | 33 | print(xiaomei) -------------------------------------------------------------------------------- /08_面向对象基础/ch_11_摆放家具_01_家具类.py: -------------------------------------------------------------------------------- 1 | class HouseItem: 2 | 3 | def __init__(self, name, area) -> None: 4 | 5 | self.name = name 6 | self.area = area 7 | 8 | def __str__(self) -> str: 9 | 10 | return "[%s] 占地 %.2f" % (self.name, self.area) 11 | 12 | 13 | # 1.创建家具 14 | bed = HouseItem("席梦思", 4) 15 | chest = HouseItem("衣柜", 2) 16 | table = HouseItem("餐桌", 1.5) 17 | 18 | print(bed) 19 | print(chest) 20 | print(table) -------------------------------------------------------------------------------- /08_面向对象基础/ch_12_摆放家具_02_房子类.py: -------------------------------------------------------------------------------- 1 | class HouseItem: 2 | 3 | def __init__(self, name, area) -> None: 4 | 5 | self.name = name 6 | self.area = area 7 | 8 | def __str__(self) -> str: 9 | 10 | return "[%s] 占地 %.2f" % (self.name, self.area) 11 | 12 | 13 | class House: 14 | 15 | def __init__(self, house_type, area) -> None: 16 | 17 | # 只有需要外部自定义初始值的属性才需要设置成初始化函数的形参 18 | self.house_type = house_type 19 | self.area = area 20 | # 剩余面积 21 | self.free_area = area 22 | # 家具名称列表 23 | self.item_list = [] 24 | 25 | def __str__(self) -> str: 26 | 27 | # Python 能自动地将一对括号内部地代码连接在一起 28 | return ("户型:%s\n总面积:%.2f[剩余:%.2f]\n家具:%s" 29 | % (self.house_type, self.area, 30 | self.free_area, self.item_list)) 31 | 32 | def add_item(self, item): 33 | 34 | print("要添加 %s" % item) 35 | 36 | 37 | 38 | # 1.创建家具 39 | bed = HouseItem("席梦思", 4) 40 | chest = HouseItem("衣柜", 2) 41 | table = HouseItem("餐桌", 1.5) 42 | 43 | print(bed) 44 | print(chest) 45 | print(table) 46 | 47 | # 2.创建房子对象 48 | my_home = House("两室一厅", 60) 49 | 50 | my_home.add_item(bed) 51 | my_home.add_item(chest) 52 | my_home.add_item(table) 53 | 54 | print(my_home) -------------------------------------------------------------------------------- /08_面向对象基础/ch_13_摆放家具_03_添加家具.py: -------------------------------------------------------------------------------- 1 | class HouseItem: 2 | 3 | def __init__(self, name, area) -> None: 4 | 5 | self.name = name 6 | self.area = area 7 | 8 | def __str__(self) -> str: 9 | 10 | return "[%s] 占地 %.2f" % (self.name, self.area) 11 | 12 | 13 | class House: 14 | 15 | def __init__(self, house_type, area) -> None: 16 | 17 | # 只有需要外部自定义初始值的属性才需要设置成初始化函数的形参 18 | self.house_type = house_type 19 | self.area = area 20 | # 剩余面积 21 | self.free_area = area 22 | # 家具名称列表 23 | self.item_list = [] 24 | 25 | def __str__(self) -> str: 26 | 27 | # Python 能自动地将一对括号内部地代码连接在一起 28 | return ("户型:%s\n总面积:%.2f[剩余:%.2f]\n家具:%s" 29 | % (self.house_type, self.area, 30 | self.free_area, self.item_list)) 31 | 32 | def add_item(self, item: HouseItem): 33 | 34 | print("要添加 %s" % item) 35 | # 1.判断家具的面积 36 | if item.area > self.free_area: 37 | print("%s 的面积过大,无法添加" % item.name) 38 | return 39 | # 2.将家具的名称添加到列表中 40 | self.item_list.append(item.name) 41 | # 3.计算剩余面积 42 | self.free_area -= item.area 43 | 44 | 45 | # 1.创建家具 46 | bed = HouseItem("席梦思", 6) 47 | chest = HouseItem("衣柜", 2) 48 | table = HouseItem("餐桌", 1.5) 49 | 50 | print(bed) 51 | print(chest) 52 | print(table) 53 | 54 | # 2.创建房子对象 55 | my_home = House("两室一厅", 60) 56 | 57 | my_home.add_item(bed) 58 | my_home.add_item(chest) 59 | my_home.add_item(table) 60 | 61 | print(my_home) -------------------------------------------------------------------------------- /08_面向对象基础/ch_14_士兵突击_01_枪类.py: -------------------------------------------------------------------------------- 1 | class Gun: 2 | 3 | def __init__(self, model: str) -> None: 4 | 5 | # 1.枪的型号 6 | self.model = model 7 | # 2.子弹的数量 8 | self.bullet_count = 0 9 | 10 | def add_bullet(self, count: int): 11 | 12 | self.bullet_count += count 13 | 14 | def shoot(self): 15 | 16 | # 1.判断子弹数量 17 | if self.bullet_count <= 0: 18 | print("[%s]没有子弹了" % self.model) 19 | return 20 | # 2.发射子弹 21 | self.bullet_count -= 1 22 | # 3.提示发射信息 23 | print("[%s] 突突突...[%s]" % (self.model, self.bullet_count)) 24 | 25 | 26 | # 1.创建枪对象 27 | ak47 = Gun("AK47") 28 | 29 | ak47.add_bullet(50) 30 | ak47.shoot() -------------------------------------------------------------------------------- /08_面向对象基础/ch_15_士兵突击_02_士兵类.py: -------------------------------------------------------------------------------- 1 | class Gun: 2 | 3 | def __init__(self, model: str) -> None: 4 | 5 | # 1.枪的型号 6 | self.model = model 7 | # 2.子弹的数量 8 | self.bullet_count = 0 9 | 10 | def add_bullet(self, count: int): 11 | 12 | self.bullet_count += count 13 | 14 | def shoot(self): 15 | 16 | # 1.判断子弹数量 17 | if self.bullet_count <= 0: 18 | print("[%s]没有子弹了" % self.model) 19 | return 20 | # 2.发射子弹 21 | self.bullet_count -= 1 22 | # 3.提示发射信息 23 | print("[%s] 突突突...[%s]" % (self.model, self.bullet_count)) 24 | 25 | 26 | class Soldier: 27 | 28 | def __init__(self, name) -> None: 29 | 30 | # 1.姓名 31 | self.name = name 32 | 33 | # 2.枪--新兵没有枪 34 | self.gun = None 35 | 36 | 37 | # 1.创建枪对象 38 | ak47 = Gun("AK47") 39 | 40 | ak47.add_bullet(50) 41 | ak47.shoot() 42 | 43 | # 2.创建士兵许三多 44 | xsd = Soldier("许三多") 45 | xsd.gun = ak47 46 | print(xsd.gun) -------------------------------------------------------------------------------- /08_面向对象基础/ch_16_士兵突击_03_士兵开火.py: -------------------------------------------------------------------------------- 1 | class Gun: 2 | 3 | def __init__(self, model: str) -> None: 4 | 5 | # 1.枪的型号 6 | self.model = model 7 | # 2.子弹的数量 8 | self.bullet_count = 0 9 | 10 | def add_bullet(self, count: int): 11 | 12 | self.bullet_count += count 13 | 14 | def shoot(self): 15 | 16 | # 1.判断子弹数量 17 | if self.bullet_count <= 0: 18 | print("[%s]没有子弹了" % self.model) 19 | return 20 | # 2.发射子弹 21 | self.bullet_count -= 1 22 | # 3.提示发射信息 23 | print("[%s] 突突突...[%s]" % (self.model, self.bullet_count)) 24 | 25 | 26 | class Soldier: 27 | 28 | def __init__(self, name: str) -> None: 29 | 30 | # 1.姓名 31 | self.name = name 32 | 33 | # 2.枪--新兵没有枪 34 | self.gun = None 35 | 36 | def fire(self): 37 | 38 | # 1.判断士兵是否有枪 39 | if self.gun is None: 40 | print("[%s]还么有枪..." % self.name) 41 | return 42 | # 2.高喊口号 43 | print("冲啊...[%s]" % self.name) 44 | # 3.装填子弹 45 | self.gun.add_bullet(50) 46 | # 4.发射 47 | self.gun.shoot() 48 | 49 | # 1.创建枪对象 50 | ak47 = Gun("AK47") 51 | 52 | # ak47.add_bullet(50) 53 | # ak47.shoot() 54 | 55 | # 2.创建士兵许三多 56 | xsd = Soldier("许三多") 57 | xsd.gun = ak47 58 | xsd.fire() 59 | print(xsd.gun) -------------------------------------------------------------------------------- /08_面向对象基础/ch_17_私有属性和方法.py: -------------------------------------------------------------------------------- 1 | class Woman: 2 | 3 | def __init__(self, name) -> None: 4 | 5 | self.name = name 6 | self.__age = 18 7 | 8 | def __secret(self): 9 | # 在对象的方法内部,是可以访问对象的私有属性的 10 | print("%s 的年龄是 %d" % (self.name, self.__age)) 11 | 12 | 13 | a = Woman("小芳") 14 | 15 | # 私有属性,在外界不能直接访问 16 | # print(a.__age) 17 | 18 | # 私有方法,同样不允许在外界直接访问 19 | # a.__secret() -------------------------------------------------------------------------------- /08_面向对象基础/ch_18_伪私有属性和方法.py: -------------------------------------------------------------------------------- 1 | class Woman: 2 | 3 | def __init__(self, name) -> None: 4 | 5 | self.name = name 6 | self.__age = 18 7 | 8 | def __secret(self): 9 | # 在对象的方法内部,是可以访问对象的私有属性的 10 | print("%s 的年龄是 %d" % (self.name, self.__age)) 11 | 12 | 13 | a = Woman("小芳") 14 | 15 | # 伪私有属性,在外界不能直接访问 16 | print(a._Woman__age) 17 | 18 | # 伪私有方法,同样不允许在外界直接访问 19 | a._Woman__secret() 20 | 21 | -------------------------------------------------------------------------------- /09.列表.md: -------------------------------------------------------------------------------- 1 | #python 2022/8/26 2 | 3 | # 高级变量类型 4 | 5 | ## 目标 6 | 7 | - 列表 8 | - 元组 9 | - 字典 10 | - 字符串 11 | - 公共方法 12 | - 变量高级 13 | 14 | ## 知识点回顾 15 | 16 | - Python 中数据类型可以分为 **数字型** 和 **非数字型** 17 | - 数字型 18 | - 整型 (`int`) 19 | - 浮点型(`float`) 20 | - 布尔型(`bool`) 21 | - 真`True` `非0数` -- **非零即真** 22 | - 假 `False` `0` 23 | - 复数型(`complex`) 24 | - 主要用于科学计算,例如:平面场问题、波动问题、电感电容等问题 25 | - 非数字型 26 | - 字符串 27 | - 列表 28 | - 元组 29 | - 字典 30 | - 在 `Python` 中,所有 **非数字型变量** 都支持以下特点 31 | 32 | 1. 都是一个**序列** `sequence`,也可以理解为 **容器** 33 | 2. **取值** `[]` 34 | 3. **遍历** `for in ` 35 | 4. **计算长度、最大/最小值、比较、删除** 36 | 5. **链接** `+` 和 **重复** `*` 37 | 6. **切片** 38 | 39 | ## 01.列表 40 | 41 | ### 1.1 列表的定义 42 | 43 | - `List` (列表) 是 `Python` 中使用 **最频繁** 的数据类型,在其他语言中通常叫作 **数组** 44 | - 专门用于存储 **一串信息** 45 | - 列表用 `[]` 定义,**数据**之间使用 `,` 分隔 46 | - 列表的 **索引** 从 `0` 开始 47 | - **索引** 就是数据在 **列表** 中的位置编号,索引 又可以被称为 **下标** 48 | 49 | >注意:从列表中取值时,如果 **超出索引范围**,程序会报错 50 | 51 | ```python 52 | name_list = ["zhangsan", "lisi", "wangwu"] 53 | ``` 54 | 55 | ![列表](img/img6.jpg) 56 | 57 | ### 1.2 列表常用操作 58 | 59 | - 在 `ipython3` 中定义一个 **列表**,例如:`name_list = []` 60 | - 输入 `name_list` 按下 `TAB` 键,`ipython` 会提示 **列表** 能够使用的 **方法** 如下: 61 | 62 | ![列表方法](img/img7.png) 63 | 64 | | 序号 | 分类 | 关键字/函数/方法 | 说明 | 65 | | ---- | ---- | ----------------------- | ------------------------ | 66 | | 1 | 增加 | `list.insert(索引,数据)` | 在指定位置插入数据 | 67 | | | | `list.append(数据) ` | 在末尾追加数据 | 68 | | | | `list.extend(列表2)` | 将列表2 的数据追加到列表 | 69 | | 2 | 修改 | `list[索引] = 数据` | 修改指定索引的数据 | 70 | | 3 | 删除 | `del list[索引]` | 删除指定索引的数据 | 71 | | | | `list.remove[数据]` | 删除第一个出现的指定数据 | 72 | | | | `list.pop()` | 删除末尾数据 | 73 | | | | `list.pop(索引)` | 删除指定索引数据 | 74 | | | |` list.clear()` | 清空列表 | 75 | | 4 | 统计 | `len(list)` | 列表长度 | 76 | | | | `list.count(数据)` | 数据在列表中出现的次数 | 77 | | 5 | 排序 | `list.sort()` | 升序排序 | 78 | | | | `list.sort(reverse=True)` | 降序排序 | 79 | | | | `list.reverse()` | 逆序、反转 | 80 | 81 | - 使用 `del` 关键字(`delete`) 同样可以删除列表中元素 82 | - `del` 关键字本质上是用来 **将一个变量从内存中删除的** 83 | - 如果使用 `del` 关键字将变量从内存中删除出,后续代码就不能再使用这个变量了 84 | 85 | ```python 86 | del name_list 87 | ``` 88 | 89 | - **关键字** 是 Python 内置的、具有特殊意义的标识符 90 | 91 | ![Python内置关键字](img/img8.png) 92 | 93 | >关键字后面不需要使用括号 94 | 95 | - **函数** 封装了独立功能,可以直接调用 96 | 97 | ``` 98 | 函数名(参数) 99 | ``` 100 | 101 | >函数明需要记忆 102 | 103 | - **方法** 和函数类似,同样是封装了独立的功能 104 | - **方法需要通过对象来调用,表示针对这个对象要做的的操作** 105 | 106 | ``` 107 | 对象.方法名(参数) 108 | ``` 109 | 110 | >在变量后面输入 `.`,然后选择针对这个变量要执行的操作,基益起来比函数要简单很多 111 | 112 | ### 1.3 循环遍历 113 | 114 | - **遍历**就是**从头到尾**依次从**列表**中获取数据 115 | - 在**循环内部**针对**每一个元素**,执行相同的操作 116 | - 在 `Python` 中为了提高列表的遍历效率,专门提供的 **迭代 iteration 遍历** 117 | - 使用 `for` 就能够实现迭代遍历 118 | 119 | ```python 120 | name_list = ["小李广-花荣", "呼保义-宋江", "玉麒麟-卢俊义", "黑旋风-李逵"] 121 | 122 | # 使用迭代遍历列表 123 | """ 124 | 顺序从列表中依次获取数据,每一次循环过程中,数据都会保存在my_name 这个变量中, 125 | 在循环体内部可以访问当前这一次获取到的数据 126 | """ 127 | for my_name in name_list: 128 | print("我的名字是 %s" % my_name) 129 | ``` 130 | 131 | - 列表中**可以存储不同类型的数据** 132 | - 在开发中,更多的应用场景是 133 | 1. **列表**存储相同类型的数据 134 | 2. 通过**迭代遍历**,在循环体内部,针对列表中的每一项元素,执行相同的操作 135 | -------------------------------------------------------------------------------- /09_面向对象特性/ch_01_不使用继承开发动物和狗.py: -------------------------------------------------------------------------------- 1 | class Animal: 2 | 3 | def eat(self): 4 | print("吃") 5 | 6 | def drink(self): 7 | print("喝") 8 | 9 | def run(self): 10 | print("跑") 11 | 12 | def sleep(self): 13 | print("睡") 14 | 15 | 16 | class Dog: 17 | 18 | def eat(self): 19 | print("吃") 20 | 21 | def drink(self): 22 | print("喝") 23 | 24 | def run(self): 25 | print("跑") 26 | 27 | def sleep(self): 28 | print("睡") 29 | 30 | def bark(self): 31 | print("吠") 32 | 33 | 34 | 35 | wangcai = Dog() 36 | wangcai.eat() 37 | wangcai.drink() 38 | wangcai.run() 39 | wangcai.sleep() 40 | wangcai.bark() -------------------------------------------------------------------------------- /09_面向对象特性/ch_02_使用继承开发动物和狗.py: -------------------------------------------------------------------------------- 1 | class Animal: 2 | 3 | def eat(self): 4 | print("吃") 5 | 6 | def drink(self): 7 | print("喝") 8 | 9 | def run(self): 10 | print("跑") 11 | 12 | def sleep(self): 13 | print("睡") 14 | 15 | 16 | class Dog(Animal): 17 | 18 | # 子类拥有父类的所有属性和方法 19 | # def eat(self): 20 | # print("吃") 21 | 22 | # def drink(self): 23 | # print("喝") 24 | 25 | # def run(self): 26 | # print("跑") 27 | 28 | # def sleep(self): 29 | # print("睡") 30 | 31 | def bark(self): 32 | print("吠") 33 | 34 | 35 | 36 | wangcai = Dog() 37 | wangcai.eat() 38 | wangcai.drink() 39 | wangcai.run() 40 | wangcai.sleep() 41 | wangcai.bark() -------------------------------------------------------------------------------- /09_面向对象特性/ch_03_继承的传递性.py: -------------------------------------------------------------------------------- 1 | class Animal: 2 | 3 | def eat(self): 4 | print("吃") 5 | 6 | def drink(self): 7 | print("喝") 8 | 9 | def run(self): 10 | print("跑") 11 | 12 | def sleep(self): 13 | print("睡") 14 | 15 | 16 | class Dog(Animal): 17 | 18 | def bark(self): 19 | print("犬吠") 20 | 21 | 22 | class xiaotianquan(Dog): 23 | 24 | def fly(self): 25 | print("哮天犬会飞") 26 | 27 | 28 | # 创建一个哮天犬的对象 29 | xtq = xiaotianquan() 30 | 31 | xtq.fly() 32 | xtq.bark() 33 | xtq.eat() -------------------------------------------------------------------------------- /09_面向对象特性/ch_04_继承的传递性注意事项.py: -------------------------------------------------------------------------------- 1 | class Animal: 2 | 3 | def eat(self): 4 | print("吃") 5 | 6 | def drink(self): 7 | print("喝") 8 | 9 | def run(self): 10 | print("跑") 11 | 12 | def sleep(self): 13 | print("睡") 14 | 15 | 16 | class Dog(Animal): 17 | 18 | def bark(self): 19 | print("犬吠") 20 | 21 | 22 | class xiaotianquan(Dog): 23 | 24 | def fly(self): 25 | print("哮天犬会飞") 26 | 27 | 28 | 29 | class Cat(Animal): 30 | 31 | def catch(self): 32 | print("抓老鼠") 33 | 34 | 35 | # 创建一个哮天犬的对象 36 | xtq = xiaotianquan() 37 | 38 | xtq.fly() 39 | xtq.bark() 40 | xtq.eat() 41 | 42 | # 哮天犬 和 Cat 之间没有继承关系,不能调用 catch() 43 | # xtq.catch() -------------------------------------------------------------------------------- /09_面向对象特性/ch_05_覆盖父类方法.py: -------------------------------------------------------------------------------- 1 | class Animal: 2 | 3 | def eat(self): 4 | print("吃") 5 | 6 | def drink(self): 7 | print("喝") 8 | 9 | def run(self): 10 | print("跑") 11 | 12 | def sleep(self): 13 | print("睡") 14 | 15 | 16 | class Dog(Animal): 17 | 18 | def bark(self): 19 | print("犬吠") 20 | 21 | 22 | class XiaoTianQuan(Dog): 23 | 24 | def fly(self): 25 | print("哮天犬会飞") 26 | 27 | def bark(self): 28 | print("神犬吠叫") 29 | 30 | 31 | 32 | xtq = XiaoTianQuan() 33 | 34 | # 如果子类中,重写了父类的方法 35 | # 再使用子类对象调用方法时,会调用子类中重写的方法 36 | xtq.bark() -------------------------------------------------------------------------------- /09_面向对象特性/ch_06_扩展父类方法.py: -------------------------------------------------------------------------------- 1 | class Animal: 2 | 3 | def eat(self): 4 | print("吃") 5 | 6 | def drink(self): 7 | print("喝") 8 | 9 | def run(self): 10 | print("跑") 11 | 12 | def sleep(self): 13 | print("睡") 14 | 15 | 16 | class Dog(Animal): 17 | 18 | def bark(self): 19 | print("犬吠") 20 | 21 | 22 | class XiaoTianQuan(Dog): 23 | 24 | def fly(self): 25 | print("哮天犬会飞") 26 | 27 | def bark(self): 28 | # 1.针对子类特有的需求,编写代码 29 | print("神犬吠叫") 30 | 31 | # 2.使用 super(). 调用原本在父类中封装的方法 32 | super().bark() 33 | 34 | # 父类名.方法(self) 调用父类方法,效果同上,但不推荐使用 35 | # Dog.bark(self) 36 | 37 | # 3.增加其他子类的代码 38 | print("恶龙咆哮") 39 | 40 | 41 | 42 | xtq = XiaoTianQuan() 43 | 44 | # 如果子类中,重写了父类的方法 45 | # 再使用子类对象调用方法时,会调用子类中重写的方法 46 | xtq.bark() -------------------------------------------------------------------------------- /09_面向对象特性/ch_07_父类的私有属性和私有方法.py: -------------------------------------------------------------------------------- 1 | class A: 2 | 3 | def __init__(self) -> None: 4 | 5 | self.num1 = 100 6 | self.__num2 = 200 7 | 8 | def __test(self): 9 | print("私有方法 %d %d" % (self.num1, self.__num2)) 10 | 11 | 12 | class B(A): 13 | 14 | def demo(self): 15 | 16 | # 1.在子类的对象方法中,不能访问父类的私有属性 17 | # print("访问父类的私有属性 %d" % self.__num2) 18 | # 2.在子类的对象方法中,不能调用父类的私有方法 19 | # self.__test() 20 | pass 21 | 22 | 23 | # 创建一个子类对象 24 | b = B() 25 | print(b) 26 | 27 | # 在外界不能直接访问对象的私有属性/调用私有方法 28 | # print(b.__num2) 29 | # b.__test() 30 | 31 | b.demo() -------------------------------------------------------------------------------- /09_面向对象特性/ch_08_父类的公有方法.py: -------------------------------------------------------------------------------- 1 | class A: 2 | 3 | def __init__(self) -> None: 4 | 5 | self.num1 = 100 6 | self.__num2 = 200 7 | 8 | def __test(self): 9 | print("父类的私有方法 %d %d" % (self.num1, self.__num2)) 10 | 11 | def test(self): 12 | # 父类的公有方法,可以访问父类的公有方法/公有属性 13 | print("父类的公有方法 %d" % self.__num2) 14 | 15 | self.__test() 16 | 17 | 18 | class B(A): 19 | 20 | def demo(self): 21 | 22 | # 1.在子类的对象方法中,不能访问父类的私有属性 23 | # print("访问父类的私有属性 %d" % self.__num2) 24 | # 2.在子类的对象方法中,不能调用父类的私有方法 25 | # self.__test() 26 | # 3.访问父类的公有属性 27 | print("子类方法 %d" % self.num1) 28 | # 4.通过子类,可以调用父类的公有方法 29 | self.test() 30 | pass 31 | 32 | 33 | # 创建一个子类对象 34 | b = B() 35 | print(b) 36 | 37 | b.demo() 38 | # 在外界访问父类的公有属性/调用公有方法 39 | # print(b.num1) 40 | # b.test() 41 | 42 | # 在外界不能直接访问对象的私有属性/调用私有方法 43 | # print(b.__num2) 44 | # b.__test() 45 | 46 | -------------------------------------------------------------------------------- /09_面向对象特性/ch_09_多继承.py: -------------------------------------------------------------------------------- 1 | class A: 2 | 3 | def test(self): 4 | print("A -- test 方法") 5 | 6 | def demo(self): 7 | print("A -- demo 方法") 8 | 9 | class B: 10 | 11 | def demo(self): 12 | print("B -- demo 方法") 13 | 14 | def test(self): 15 | print("B -- test 方法") 16 | 17 | 18 | class C(A, B): 19 | """多继承可以让子类对象,同时具有多个父类的属性和方法""" 20 | pass 21 | 22 | # 创建子类对象 23 | c = C() 24 | 25 | # 确定 C类对象调用方法的顺序 26 | print(C.__mro__) 27 | 28 | c.test() 29 | c.demo() -------------------------------------------------------------------------------- /09_面向对象特性/ch_10_多继承的使用注意事项.py: -------------------------------------------------------------------------------- 1 | class A: 2 | 3 | def test(self): 4 | print("test 方法") 5 | 6 | 7 | class B: 8 | 9 | def demo(self): 10 | print("demo 方法") 11 | 12 | 13 | class C(A, B): 14 | """多继承可以让子类对象,同时具有多个父类的属性和方法""" 15 | pass 16 | 17 | # 创建子类对象 18 | c = C() 19 | 20 | c.test() 21 | c.demo() -------------------------------------------------------------------------------- /09_面向对象特性/ch_11_多态案例.py: -------------------------------------------------------------------------------- 1 | class Dog(object): 2 | 3 | def __init__(self, name) -> None: 4 | self.name = name 5 | 6 | def game(self): 7 | print("%s 蹦蹦跳跳地玩耍..." % self.name) 8 | 9 | 10 | class XiaoTianDog(Dog): 11 | 12 | def game(self): 13 | print("%s 飞到天上玩耍..." % self.name) 14 | 15 | 16 | class Person(object): 17 | 18 | def __init__(self, name) -> None: 19 | self.name = name 20 | 21 | def game_with_dog(self, dog: Dog): 22 | print("%s 和 %s 快乐地玩耍..." % (self.name, dog.name)) 23 | # 让狗玩耍 24 | dog.game() 25 | 26 | 27 | # 1.创建 狗 对象 28 | # wangcai = Dog("旺财") 29 | wangcai = XiaoTianDog("飞天旺财") 30 | 31 | # 2.创建一个 小明 对象 32 | xiaoming = Person("小明") 33 | 34 | # 3.让小明调用和狗玩的方法 35 | xiaoming.game_with_dog(wangcai) -------------------------------------------------------------------------------- /09_面向对象特性/ch_12_类属性.py: -------------------------------------------------------------------------------- 1 | class Tool(object): 2 | 3 | # 使用赋值语句定义类属性,记录所有工具对象的数量 4 | count = 0 5 | 6 | def __init__(self, name) -> None: 7 | self.name = name 8 | 9 | # 每次创建对象都会调用初始化方法 10 | Tool.count += 1 11 | 12 | 13 | # 1.创建工具对象 14 | tool1 = Tool("斧头") 15 | tool2 = Tool("锤子") 16 | tool3 = Tool("水桶") 17 | 18 | # 2.输出工具对象的数量 19 | print(Tool.count) -------------------------------------------------------------------------------- /09_面向对象特性/ch_13_属性获取机制.py: -------------------------------------------------------------------------------- 1 | class Tool(object): 2 | 3 | # 使用赋值语句定义类属性,记录所有工具对象的数量 4 | count = 0 5 | 6 | def __init__(self, name) -> None: 7 | self.name = name 8 | 9 | # 每次创建对象都会调用初始化方法 10 | Tool.count += 1 11 | 12 | 13 | # 1.创建工具对象 14 | tool1 = Tool("斧头") 15 | tool2 = Tool("锤子") 16 | tool3 = Tool("水桶") 17 | 18 | # 2.输出工具对象的数量 19 | # print(Tool.count) 20 | print("工具对象总数:%d" % tool1.count) -------------------------------------------------------------------------------- /09_面向对象特性/ch_14_使用对象名访问类属性的问题.py: -------------------------------------------------------------------------------- 1 | class Tool(object): 2 | 3 | # 使用赋值语句定义类属性,记录所有工具对象的数量 4 | count = 0 5 | 6 | def __init__(self, name) -> None: 7 | self.name = name 8 | 9 | # 每次创建对象都会调用初始化方法 10 | Tool.count += 1 11 | 12 | 13 | # 1.创建工具对象 14 | tool1 = Tool("斧头") 15 | tool2 = Tool("锤子") 16 | tool3 = Tool("水桶") 17 | 18 | # 2.输出工具对象的数量 19 | tool3.count = 99 20 | print("工具对象总数:%d" % tool3.count) # 99 21 | print("====> %d" % Tool.count) # 3 -------------------------------------------------------------------------------- /09_面向对象特性/ch_15_类方法.py: -------------------------------------------------------------------------------- 1 | class Tool(object): 2 | 3 | # 使用赋值语句定义类属性,记录所有工具对象的数量 4 | count = 0 5 | 6 | @classmethod 7 | def show_tool_count(cls): 8 | 9 | print("工具对象的数量 %d" % cls.count) 10 | 11 | def __init__(self, name) -> None: 12 | self.name = name 13 | 14 | # 每次创建对象都会调用初始化方法 15 | Tool.count += 1 16 | 17 | 18 | # 创建工具对象 19 | tool1 = Tool("锤子") 20 | tool2 = Tool("榔头") 21 | 22 | # 调用类方法 23 | Tool.show_tool_count() -------------------------------------------------------------------------------- /09_面向对象特性/ch_16_静态方法.py: -------------------------------------------------------------------------------- 1 | class Dog: 2 | 3 | @staticmethod 4 | def run(): 5 | # 不访问实例属性/类属性 6 | print("小狗要跑...") 7 | 8 | def __init__(self, name) -> None: 9 | 10 | self.name = name 11 | 12 | # 通过 类名. 调用静态方法 -- 不需要创建对象,就可以调用 13 | Dog.run() -------------------------------------------------------------------------------- /09_面向对象特性/ch_17_方法综合案例.py: -------------------------------------------------------------------------------- 1 | class Game(object): 2 | 3 | # 历史最高分 4 | top_score = 0 5 | 6 | def __init__(self, player_name) -> None: 7 | self.player_name = player_name 8 | 9 | @staticmethod 10 | def show_help(): 11 | print("帮助信息:让僵尸进入大门") 12 | 13 | @classmethod 14 | def show_top_score(cls): 15 | print("历史记录 %d" % cls.top_score) 16 | 17 | def start_game(self): 18 | print("%s 开始游戏" % self.player_name) 19 | 20 | 21 | # 1.查看游戏的帮助信息 22 | Game.show_help() 23 | 24 | # 2.查看历史最高分 25 | Game.show_top_score() 26 | 27 | # 3.创建游戏对象 28 | game = Game("小明") 29 | game.start_game() -------------------------------------------------------------------------------- /09_面向对象特性/ch_18___new__.py: -------------------------------------------------------------------------------- 1 | class MusicPlayer: 2 | 3 | def __new__(cls, *args, **kwargs): 4 | # 1.创建对象时,new方法会被自动调用 5 | print("创建对象,分配空间") 6 | 7 | # 2.为对象分配空间 8 | instance = super().__new__(cls) 9 | 10 | # 3.返回对象的引用 11 | return instance 12 | 13 | def __init__(self) -> None: 14 | print("播放器初始化") 15 | 16 | 17 | # 创建播放器对象 18 | player = MusicPlayer() 19 | 20 | print(player) -------------------------------------------------------------------------------- /09_面向对象特性/ch_19_单例.py: -------------------------------------------------------------------------------- 1 | class MusicPlayer(object): 2 | 3 | # 记录第一个被创建对象的引用 4 | instance = None 5 | 6 | def __new__(cls, *args, **kwargs): 7 | # 1.判断类属性是否是空对象 8 | if cls.instance is None: 9 | # 2.调用父类的方法,为第一个对象分配空间 10 | cls.instance = super().__new__(cls) 11 | 12 | # 3.返回类属性保存的对象引用 13 | return cls.instance 14 | 15 | # 创建多个对象 16 | player1 = MusicPlayer() 17 | print(player1) 18 | 19 | player2 = MusicPlayer() 20 | print(player2) -------------------------------------------------------------------------------- /09_面向对象特性/ch_20_单例初始化一次.py: -------------------------------------------------------------------------------- 1 | class MusicPlayer(object): 2 | 3 | # 记录第一个被创建对象的引用 4 | instance = None 5 | 6 | # 记录是否执行过初始化动作 7 | init_flag = False 8 | 9 | def __new__(cls, *args, **kwargs): 10 | # 1.判断类属性是否是空对象 11 | if cls.instance is None: 12 | # 2.调用父类的方法,为第一个对象分配空间 13 | cls.instance = super().__new__(cls) 14 | 15 | # 3.返回类属性保存的对象引用 16 | return cls.instance 17 | 18 | def __init__(self, name: str) -> None: 19 | # 1.判断是否执行过初始化动作 20 | if MusicPlayer.init_flag: 21 | return 22 | 23 | # 2.如果没有执行过,再执行初始化动作 24 | self.name = name 25 | print("初始化播放器") 26 | 27 | # 3.修改类属性标记 28 | MusicPlayer.init_flag = True 29 | 30 | 31 | # 创建多个对象 32 | player1 = MusicPlayer("QQ音乐") 33 | player2 = MusicPlayer("酷狗音乐") 34 | 35 | print(id(player1) == id(player2)) # True 36 | print(player1.name) # QQ音乐 37 | print(player2.name) # QQ音乐 因为只初始化一次 -------------------------------------------------------------------------------- /10_异常/ch_01_简单的异常捕获.py: -------------------------------------------------------------------------------- 1 | try: 2 | # 不能确定正确执行的代码 3 | num = int(input("请输入一个整数:")) 4 | except: 5 | # 错误的处理代码 6 | print("请输入正确的整数格式") 7 | 8 | print("-" * 50) -------------------------------------------------------------------------------- /10_异常/ch_02_捕获错误类型.py: -------------------------------------------------------------------------------- 1 | try: 2 | # 1. 提示用户输入一个整数 3 | num = int(input("输入一个整数:")) 4 | 5 | # 2. 使用 `8` 除以用户输入的整数并且输出 6 | result = 8 / num 7 | 8 | print(result) 9 | except ZeroDivisionError: 10 | print("除0错误") 11 | except ValueError: 12 | print("请输入正确的整数") -------------------------------------------------------------------------------- /10_异常/ch_03_捕获未知错误.py: -------------------------------------------------------------------------------- 1 | try: 2 | # 1. 提示用户输入一个整数 3 | num = int(input("输入一个整数:")) 4 | 5 | # 2. 使用 `8` 除以用户输入的整数并且输出 6 | res = 8 / num 7 | 8 | print(res) 9 | except ValueError: 10 | print("请输入正确的整数") 11 | except Exception as result: 12 | print("未知错误 %s" % result) -------------------------------------------------------------------------------- /10_异常/ch_04_完整的异常语法.py: -------------------------------------------------------------------------------- 1 | try: 2 | # 1. 提示用户输入一个整数 3 | num = int(input("输入一个整数:")) 4 | 5 | # 2. 使用 `8` 除以用户输入的整数并且输出 6 | res = 8 / num 7 | 8 | print(res) 9 | except ValueError: 10 | print("请输入正确的整数") 11 | except Exception as result: 12 | print("未知错误 %s" % result) 13 | else: 14 | print("尝试成功") 15 | finally: 16 | print("无论是否出现异常都会执行的代码") 17 | 18 | print("-" * 20) -------------------------------------------------------------------------------- /10_异常/ch_05_异常的传递.py: -------------------------------------------------------------------------------- 1 | def demo1(): 2 | return int(input("请输入整数:")) 3 | 4 | 5 | def demo2(): 6 | return demo1() 7 | 8 | # 利用异常的传递性,在主程序捕获异常 9 | try: 10 | print(demo2()) 11 | except Exception as result: 12 | print("未知错误 %s" % result) 13 | -------------------------------------------------------------------------------- /10_异常/ch_06_抛出异常: -------------------------------------------------------------------------------- 1 | def input_password(): 2 | 3 | # 1.提示用户输入密码 4 | pwd = input("请输入密码:") 5 | # 2.判断密码长度 >= 8,返回用户输入的密码 6 | if len(pwd) >= 8: 7 | return pwd 8 | # 3.如果 < 8,主动抛出异常 9 | print("主动抛出异常") 10 | # 1>创建异常对象 - 可以使用错误信息字符串作为参数 11 | ex = Exception("密码长度不够") 12 | # 2>主动抛出异常 13 | raise ex 14 | 15 | 16 | # 提示用户输入密码 17 | try: 18 | print(input_password()) 19 | except Exception as result: 20 | print(result) -------------------------------------------------------------------------------- /11_模块/__pycache__/ch_01_测试模块1.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/11_模块/__pycache__/ch_01_测试模块1.cpython-38.pyc -------------------------------------------------------------------------------- /11_模块/__pycache__/ch_02_测试模块2.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/11_模块/__pycache__/ch_02_测试模块2.cpython-38.pyc -------------------------------------------------------------------------------- /11_模块/__pycache__/ch_09___name__模块.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/11_模块/__pycache__/ch_09___name__模块.cpython-38.pyc -------------------------------------------------------------------------------- /11_模块/ch_01_测试模块1.py: -------------------------------------------------------------------------------- 1 | # 全局变量 2 | title = "模块1" 3 | 4 | # 函数 5 | def say_hello(): 6 | print("我是 %s" % title) 7 | 8 | 9 | # 类 10 | class Dog(object): 11 | pass 12 | -------------------------------------------------------------------------------- /11_模块/ch_02_测试模块2.py: -------------------------------------------------------------------------------- 1 | # 全局变量 2 | title = "模块2" 3 | 4 | # 函数 5 | def say_hello(): 6 | print("我是 %s" % title) 7 | 8 | 9 | # 类 10 | class Cat(object): 11 | pass 12 | -------------------------------------------------------------------------------- /11_模块/ch_03_import导入模块.py: -------------------------------------------------------------------------------- 1 | import ch_01_测试模块1 2 | import ch_02_测试模块2 3 | 4 | ch_01_测试模块1.say_hello() 5 | ch_02_测试模块2.say_hello() 6 | 7 | dog = ch_01_测试模块1.Dog() 8 | print(dog) 9 | 10 | cat = ch_02_测试模块2.Cat() 11 | print(cat) -------------------------------------------------------------------------------- /11_模块/ch_04_import同时指定别名.py: -------------------------------------------------------------------------------- 1 | import ch_01_测试模块1 as DogModule 2 | import ch_02_测试模块2 as CatModule 3 | 4 | DogModule.say_hello() 5 | CatModule.say_hello() 6 | 7 | dog = DogModule.Dog() 8 | print(dog) 9 | 10 | cat = CatModule.Cat() 11 | print(cat) 12 | -------------------------------------------------------------------------------- /11_模块/ch_05_from_import导入.py: -------------------------------------------------------------------------------- 1 | from ch_01_测试模块1 import Dog 2 | from ch_02_测试模块2 import say_hello 3 | 4 | say_hello() 5 | 6 | dog = Dog() 7 | print(dog) -------------------------------------------------------------------------------- /11_模块/ch_06_from_import_注意事项.py: -------------------------------------------------------------------------------- 1 | # from ch_01_测试模块1 import say_hello 2 | from ch_02_测试模块2 import say_hello as say_hello2 3 | from ch_01_测试模块1 import say_hello as say_hello1 4 | 5 | say_hello1() 6 | say_hello2() -------------------------------------------------------------------------------- /11_模块/ch_07_from_import导入全部.py: -------------------------------------------------------------------------------- 1 | from ch_01_测试模块1 import * 2 | from ch_02_测试模块2 import * # 会覆盖掉 title 和 say_hello 3 | 4 | 5 | print(title) 6 | say_hello() 7 | 8 | dog = Dog() 9 | print(dog) -------------------------------------------------------------------------------- /11_模块/ch_08_模块的搜索顺序.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | print(random.__file__) # D:\Python\Anaconda\lib\random.py 4 | 5 | rand = random.randint(0, 10) 6 | 7 | print(rand) -------------------------------------------------------------------------------- /11_模块/ch_09___name__模块.py: -------------------------------------------------------------------------------- 1 | # 全局变量、函数、类,注意:直接执行的代码不是向外界提供的工具! 2 | def say_hello(): 3 | print("你好你好,我是 say hello") 4 | 5 | # 如果直接执行模块,__name__ == "__main__" 6 | # 如果被导入则,__name__ == "ch_09___name__模块" 即模块名 7 | # print(__name__) 8 | 9 | if __name__ == "__main__": 10 | # 文件被导入时,能够直接执行的代码不需要被执行! 11 | # 以下是测试代码,不需要在被导入时执行 12 | print("小明开发的模块") 13 | say_hello() -------------------------------------------------------------------------------- /11_模块/ch_09___name__测试导入.py: -------------------------------------------------------------------------------- 1 | import ch_09___name__模块 2 | 3 | print("-" * 50) -------------------------------------------------------------------------------- /11_模块/ch_10_导入包.py: -------------------------------------------------------------------------------- 1 | import ch_message 2 | 3 | ch_message.send_message.send("hello") 4 | 5 | txt = ch_message.receive_message.receive() 6 | print(txt) -------------------------------------------------------------------------------- /11_模块/ch_message/__init__.py: -------------------------------------------------------------------------------- 1 | from . import send_message 2 | from . import receive_message -------------------------------------------------------------------------------- /11_模块/ch_message/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/11_模块/ch_message/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /11_模块/ch_message/__pycache__/receive_message.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/11_模块/ch_message/__pycache__/receive_message.cpython-38.pyc -------------------------------------------------------------------------------- /11_模块/ch_message/__pycache__/send_message.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/11_模块/ch_message/__pycache__/send_message.cpython-38.pyc -------------------------------------------------------------------------------- /11_模块/ch_message/receive_message.py: -------------------------------------------------------------------------------- 1 | def receive(): 2 | return "这是来自 100xx 的短信" -------------------------------------------------------------------------------- /11_模块/ch_message/send_message.py: -------------------------------------------------------------------------------- 1 | def send(text: str): 2 | print("正在发送 %s" % text) -------------------------------------------------------------------------------- /12.变量进阶.md: -------------------------------------------------------------------------------- 1 | #python 2022/8/30 2 | 3 | ## 目标 4 | 5 | - 变量的引用 6 | - 可变和不可变类型 7 | - 局部变量和全局变量 8 | 9 | ## 01.变量的引用 10 | 11 | >- 变量和数据都是保存在内存中的 12 | >- 在 `Python` 中**函数的参数传递**以及**返回值**都是靠**引用**传递的 13 | 14 | ### 1.1 引用的概念 15 | 16 | - **变量和数据是分开存储的** 17 | - 数据保存在内存中的一个位置 18 | - 变量中保存着数据在内存中的地址 19 | - **变量中记录数据的地址**,就叫做**引用** 20 | - 使用 `id()` 函数可以查看变量中保存数据所在的**内存地址** 21 | 22 | >注意:如果变量已经定义,当给一个变量赋值的时候,本质是**修改了数据的引用** 23 | >- 变量不再对之前的数据引用 24 | >- 变量改为对新赋值的数据引用 25 | 26 | ### 1.2 变量引用的示例 27 | 28 | 在 `Python` 中,变量的名字类似于便签纸贴在数据上 29 | 30 | - 定义一个整数变量 `a` ,并且赋值为 `1` 31 | 32 | | 代码 | 图示 | 33 | | ----- | ---- | 34 | | a = 1 | ![](img/img14.png) | 35 | 36 | - 将变量 `a` 赋值为 `2` 37 | 38 | | 代码 | 图示 | 39 | | ----- | ---- | 40 | | a = 2 | ![](img/img15.png) ![](img/img16.png) | 41 | 42 | - 定义一个整数变量 `b` ,并且将变量 `a` 的值赋值给 `b` 43 | 44 | | 代码 | 图示 | 45 | | ----- | ------------------ | 46 | | b = a | ![](img/img17.png) | 47 | 48 | >变量 `b` 是第2个贴在数字 `2` 上的标签 49 | 50 | ## 02.可变和不可变类型 51 | 52 | - **不可变类型**,内存中的数据不允许被修改: 53 | - 数字类型 `int`, `bool`, `float`, `complex`, `long(2.x)` 54 | - 字符串 `str` 55 | - 元组 `tuple` 56 | - **可变类型**,内存中的数据可以被修改: 57 | - 列表 `list` 58 | - 字典 `dict` 59 | 60 | ```python 61 | a = 1 62 | a = "hello" 63 | a = [1,2,3] 64 | a = [3,2,1] 65 | ``` 66 | 67 | ```python 68 | demo_list = [1, 2, 3] 69 | print("定义列表后的内存地址 %d" % id(demo_list)) 70 | 71 | demo_list.append(9) 72 | demo_list.pop() 73 | demo_list.remove(2) 74 | demo_list[0] = 10 75 | 76 | print("修改数据后的内存地址 %d" % id(demo_list)) 77 | 78 | demo_dict = {"name":"小明"} 79 | 80 | print("定义字典后的内存地址 %d" % id(demo_dict)) 81 | 82 | demo_dict["age"] = 18 83 | demo_dict.pop("name") 84 | demo_dict["name"] = "老王" 85 | 86 | print("修改数据后的内存地址 %d" % id(demo_dict)) 87 | ``` 88 | 89 | >注意:字典的 `key` **只能使用不可变类型的数据** 90 | 91 | 1. **可变类型**的数据变化,是通过**方法**来实现的 92 | 2. 如果给一个可变类型的变量,赋值了一个新的数据,**引用会修改** 93 | - 变量不再对之前的数据引用 94 | - 变量改为对新赋值的数据引用 95 | 96 | **哈希(hash)** 97 | 98 | - `Python` 中内置有一个名字叫作 `hash()` 的函数 99 | - 接受一个**不可变数据类型**的数据作为**参数** 100 | - **返回**结果是一个**整数** 101 | - `哈希` 是一种算法,其作用就是提取数据的**特征码(指纹)** 102 | - 相同的内容得到相同的结果 103 | - 不同的内容得到不同的结果 104 | - 在 `Python` 中,设置字典的**键值对**时,会首先对 `key` 进行 `hash` 以决定如何在内存中保存字典的数据,方便后续对字典的操作:**增、删、改、查** 105 | - 键值对的 `key` 必须是不可变类型数据 106 | - 键值对的 `value` 可以是任意类型的数据 107 | 108 | ## 03.局部变量和全局变量 109 | 110 | - 局部变量就是在函数内部定义的变量,只能在函数内部使用 111 | - 全局变量是在函数外部定义的变量,所有函数内部都可以使用这个变量 112 | 113 | >提示:在其他开发语言中,大多不推荐使用全局变量--可变范围太大,导致程序不好维护 114 | 115 | ### 3.1 局部变量 116 | 117 | - 局部变量是在函数内部定义的变量,只能在函数内部使用 118 | - **函数执行结束后,函数内部的局部变量,会被系统回收** 119 | - 不同的函数,可以定义相同的名字的局部变量,但是各用各的不会产生影响 120 | 121 | **局部变量的作用** 122 | 123 | - **在函数内部使用,临时保存函数内部需要使用的数据** 124 | 125 | ```python 126 | def demo1(): 127 | 128 | # 定义一个局部变量 129 | num = 10 130 | print("在demo1函数内部的变量是 %d" % num) 131 | 132 | 133 | def demo2(): 134 | 135 | # 不能在其他函数内使用 136 | # print("%d" % num) 137 | pass 138 | 139 | # 在函数内部定义的变量,不能再其他位置使用 140 | # print("%d" % num) 141 | 142 | demo1() 143 | demo2() 144 | ``` 145 | 146 | **局部变量的生命周期** 147 | 148 | - 所谓**生命周期**就是变量从**被创建**到**被系统回收**的过程 149 | - 局部变量在函数执行时才会被创建 150 | - **函数执行结束后局部变量被系统回收** 151 | - **局部变量**在生命周期内,可以用来**存储函数内部临时使用到的数据** 152 | 153 | ### 3.2 全局变量 154 | 155 | - 全局变量是在函数外部定义的变量,所有函数内部都可以使用这个变量 156 | 157 | ```python 158 | 159 | ``` 160 | 161 | 注意:函数执行时,需要处理变量时会: 162 | 163 | 1. 首先查找函数内部是否存在执行名称的局部变量,如果有,直接使用 164 | 2. 如果没有,查找函数外部是否存在指定名称的全局变量,如果有,直接使用 165 | 3. 如果还没有,程序报错! 166 | 167 | 1) **函数不能直接修改全局变量的引用** 168 | 169 | - 全局变量是在函数外部定义的变量(没有定义在某一个函数内),所有函数内部都可以使用这个变量 170 | 171 | >提示:在其他的开发语言中,大多不推荐使用全局变量--可变返回太大,导致程序不好维护! 172 | 173 | - 在函数内部,可以**通过全局变量的引用获取对应的数据** 174 | - 但是,**不允许直接修改全局变量的引用**--使用赋值语句修改全局变量的值 175 | 176 | ```python 177 | # 全局变量 178 | num = 10 179 | 180 | def demo1(): 181 | 182 | # 修改全局变量的值 183 | # 在 python 中,不允许直接修改全局变量的值 184 | # 如果使用赋值语句,会在函数内部,定义一个局部变量 185 | num = 99 186 | print("demo1() ==> %d" % num) 187 | 188 | 189 | def demo2(): 190 | 191 | print("demo2() ==> %d" % num) 192 | 193 | demo1() 194 | demo2() 195 | ``` 196 | 197 | 2) **在函数内部修改全局变量的值** 198 | 199 | - 如果在函数中需要修改全局变量,需要使用 `global` 进行声明 200 | 201 | ```python 202 | # 全局变量 203 | num = 10 204 | 205 | def demo1(): 206 | 207 | # 希望修改全局变量的值 - 使用 global 声明一下变量即可 208 | # global 关键字会告诉解释器后面的变量是一个全局变量 209 | # 再使用赋值语句时,就不会创建局部变量 210 | global num 211 | num = 99 212 | print("demo1() ==> %d" % num) 213 | 214 | 215 | def demo2(): 216 | 217 | print("demo2() ==> %d" % num) 218 | 219 | demo1() 220 | demo2() 221 | ``` 222 | 223 | 3) **全局变量定义的位置** 224 | 225 | - 为了保证所有的函数都能够正确使用到全局变量,应该**将全局变量定义在其他函数的上方** 226 | 227 | ```python 228 | a = 10 229 | 230 | def demo(): 231 | print("%d" % a) 232 | print("%d" % b) 233 | print("%d" % c) 234 | 235 | b = 20 236 | demo() 237 | c = 30 238 | ``` 239 | 240 | - 注意:由于全局变量 c,是在调用函数之后才定义的,在执行函数时,变量还没有定义,所以程序会报错! 241 | 242 | - `shebang` 标识用哪个解释器解释程序 243 | - `import` 导入模块 244 | 245 | ![代码结构示意图](img/img18.png) 246 | 247 | 4) **全局变量命名的建议** 248 | 249 | - 为了避免局部变量和全局变量出现混淆,在定义全局变量时,会有些开发要求,例如: 250 | - 全局变量命名前应该增加 `g_` 或 `gl_` 的前缀 -------------------------------------------------------------------------------- /12_发布模块/MANIFEST: -------------------------------------------------------------------------------- 1 | # file GENERATED by distutils, do NOT edit 2 | setup.py 3 | ch_message\__init__.py 4 | ch_message\receive_message.py 5 | ch_message\send_message.py 6 | -------------------------------------------------------------------------------- /12_发布模块/build/lib/ch_message/__init__.py: -------------------------------------------------------------------------------- 1 | from . import send_message 2 | from . import receive_message -------------------------------------------------------------------------------- /12_发布模块/build/lib/ch_message/receive_message.py: -------------------------------------------------------------------------------- 1 | def receive(): 2 | return "这是来自 100xx 的短信" -------------------------------------------------------------------------------- /12_发布模块/build/lib/ch_message/send_message.py: -------------------------------------------------------------------------------- 1 | def send(text: str): 2 | print("正在发送 %s" % text) -------------------------------------------------------------------------------- /12_发布模块/ch_message/__init__.py: -------------------------------------------------------------------------------- 1 | from . import send_message 2 | from . import receive_message -------------------------------------------------------------------------------- /12_发布模块/ch_message/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/12_发布模块/ch_message/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /12_发布模块/ch_message/__pycache__/receive_message.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/12_发布模块/ch_message/__pycache__/receive_message.cpython-38.pyc -------------------------------------------------------------------------------- /12_发布模块/ch_message/__pycache__/send_message.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/12_发布模块/ch_message/__pycache__/send_message.cpython-38.pyc -------------------------------------------------------------------------------- /12_发布模块/ch_message/receive_message.py: -------------------------------------------------------------------------------- 1 | def receive(): 2 | return "这是来自 100xx 的短信" -------------------------------------------------------------------------------- /12_发布模块/ch_message/send_message.py: -------------------------------------------------------------------------------- 1 | def send(text: str): 2 | print("正在发送 %s" % text) -------------------------------------------------------------------------------- /12_发布模块/dist/ch_message-1.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/12_发布模块/dist/ch_message-1.0.tar.gz -------------------------------------------------------------------------------- /12_发布模块/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | 3 | setup(name="ch_message", # 包名 4 | version="1.0", # 版本 5 | description="Charlie's 发送和接收消息模块", # 描述信息 6 | long_description="完整的发送和接收消息模块", # 完整的描述信息 7 | author="CharlieHon", # 作者 8 | author_email="CharlieHon@charlie.com", 9 | url="https://github.com/CharlieHon/Python", # 主页 10 | py_modules=["ch_message.send_message", 11 | "ch_message.receive_message"] # 以列表形式指定压缩包中包含的模块的名称 12 | ) -------------------------------------------------------------------------------- /13.函数参数和返回值.md: -------------------------------------------------------------------------------- 1 | #python 2022/8/31 2 | 3 | ## 目标 4 | 5 | - 函数参数和返回值的作用 6 | - 函数的返回值进阶 7 | - 函数的参数进阶 8 | - 递归函数 9 | 10 | ## 01.函数参数和返回值的作用 11 | 12 | 函数根据**有没有参数**以及返回值,可以相互组合,一共有4中形式 13 | 14 | 1. 无参数,无返回值 15 | 2. 无参数,有返回值 16 | 3. 有参数,无返回值 17 | 4. 有参数,有返回值 18 | 19 | ![函数参数和返回值](img/img19.png) 20 | 21 | >定义函数时,**是否接受参数,或者是否返回结果**,是**根据实际的功能需求**来决定的! 22 | 23 | 1. 如果函数**内部处理的数据不确定**,就可以将外界的数据以参数传递到函数内部 24 | 2. 如果希望一个函数**执行完成后,向外界汇报执行结果**,就可以增加函数的返回值 25 | 26 | ## 02.函数的返回值进阶 27 | 28 | - 在程序开发中,有时候会希望**一个函数执行结束后,告诉调用者一个结果**,以便调用者针对具体的结果做后续的处理 29 | - 返回值是函数完成工作后,最后给调用者的一个结果 30 | - 在函数中使用 `return` 关键字可以返回结果 31 | - 调用函数一方,可以**使用变量来接收函数的返回结果** 32 | 33 | >问题:一个函数执行或能否返回多个结果? 34 | 35 | ```python 36 | def measure(): 37 | """测量温度""" 38 | 39 | temp = 39 40 | wetness = 50 41 | 42 | # 元组 - 可以包含多个数据,因此可以使用元组让函数一次返回多个值 43 | # 如果函数返回的类型是元组,小括号可以省略 44 | # return (temp, wetness) 45 | return temp, wetness 46 | 47 | # 元组 48 | res = measure() 49 | print(res) 50 | 51 | # 需要单独的处理温度或者湿度 52 | print(res[0]) 53 | print(res[1]) 54 | 55 | # 如果函数返回的类型是元组,同时希望单独的处理元组中的元素 56 | # 可以使用多个变量,一次接受函数的返回结果 57 | gl_temp, gl_wetness = measure() 58 | print(gl_temp) 59 | print(gl_wetness) 60 | ``` 61 | 62 | **交换两个数字** 63 | 64 | 1. 有两个整数变量 `a=6`, `b=100` 65 | 2. 不使用其他变量,交换两个变量的值 66 | 67 | 解法1--使用其他变量 68 | 69 | ```python 70 | # 使用临时变量 71 | c = b 72 | b = a 73 | a = c 74 | ``` 75 | 76 | 解法2--使用临时变量 77 | 78 | ```python 79 | # 不使用临时变量 80 | a = a + b 81 | b = a - b 82 | a = a - b 83 | ``` 84 | 85 | 解法3--Python专有,利用元组 86 | 87 | ```python 88 | a, b = b, a 89 | ``` 90 | 91 | ## 03.函数的参数进阶 92 | 93 | ### 3.1 不可变和可变参数 94 | 95 | >问题1:在函数内部,针对参数使用**赋值语句**,会不会影响调用函数时传递的**实参变量**?--**不会** 96 | 97 | - 无论传递的参数是可变还是不可变 98 | - 只要**针对参数使用赋值语句,会在函数内部修改局部变量的引用,不会影响到外部变量的引用** 99 | 100 | >问题2:如果传递的参数是**可变类型**,在函数内部,使用**方法**修改了数据的内容,**同样会影响到外部的数据** 101 | 102 | ```python 103 | def demo(num_list: list): 104 | print("函数内部的代码") 105 | 106 | # 使用方法修改列表的内容 107 | num_list.append(9) 108 | 109 | print(num_list) 110 | 111 | print("函数执行完成") 112 | 113 | gl_list = [1, 2, 3] 114 | demo(gl_list) 115 | print(gl_list) 116 | ``` 117 | 118 | **运算符 `+=`** 119 | 120 | - 在 `python` 中,列表变量调用 `+=` 本质上是在执行列表变量的 `extend` 方法,不会修改变量的引用 121 | 122 | ### 3.2 缺省参数 123 | 124 | - 定义函数时,可以给**某个参数**指定一个默认值,具有默认值的参数就叫做**缺省参数** 125 | - 调用函数时,如果没有传入缺省参数的值,则在函数内部使用定义函数时指定的**参数默认值** 126 | - **函数的缺省参数,将常见的值设置为参数的缺省值,从而简化函数的调用** 127 | - 例如:对列表排序的方法 128 | 129 | ```python 130 | gl_list = [4, 8, 2] 131 | 132 | # 默认按照升序排序 - 较常用 133 | gl_list.sort() 134 | print(gl_list) 135 | 136 | # 如果需要降序排序,需要执行reverse参数 137 | gl_list.sort(reverse=True) 138 | print(gl_list) 139 | ``` 140 | 141 | **指定函数的缺省参数** 142 | 143 | - 在参数后使用赋值语句,可以指定参数的缺省值 144 | 145 | ```python 146 | def print_info(name, gender=True): 147 | 148 | gender_text = "男生" 149 | if not gender: 150 | gender_text = "女生" 151 | print("%s 是 %s" % (name, gender_text)) 152 | 153 | 154 | # 假设班上的同学,男生居多,所以将默认值设置为男生 155 | # 提示:在指定缺省参数的默认值时,应该使用最常见的值作为默认值! 156 | print_info("小明") 157 | print_info("小红", False) 158 | ``` 159 | 160 | 1. 缺省参数,需要**使用最常见的值作为默认值** 161 | 2. 如果一个参数的值**不能确定**,则不应该设置默认值,具体的数值在调用函数时,由外界传递 162 | 163 | **缺省参数的注意事项** 164 | 165 | 1) 缺省参数的定义位置 166 | 167 | - **必须保证带有默认值的缺省参数在参数列表末尾** 168 | - 所以,一下定义是错误的 169 | 170 | ```python 171 | def print_info(name, gender=True, title): 172 | pass 173 | ``` 174 | 175 | 2) 调用带有多个缺省参数的函数 176 | 177 | - **在调用函数时,如果有多个缺省参数,需要指定参数名**,这样解释器才知道参数的对应关系! 178 | 179 | ### 3.3 多值参数 180 | 181 | **定义支持多值参数的函数** 182 | 183 | - 有时候可能需要一个**函数能够处理的参数个数是不确定的,这个时候,就可以使用多值参数** 184 | - `python` 中有两种多值参数: 185 | - **参数名前增加一个 `*` 可以接受元组** 186 | - **参数名前增加两个 `*` 可以接受字典** 187 | - 一般在给多值参数命名时,习惯使用以下两个名字 188 | - `*args` -- 存放元组参数,前面有一个 `*` 189 | - `**kwargs` -- 存放字典参数,前面有两个 `*` 190 | - `args` 是 `arguments` 的缩写,有变量的含义 191 | - `kw` 是 `keywprd` 的缩写,`kwargs` 可以记忆键值对参数 192 | 193 | ```python 194 | def demo(num, *nums, **person): 195 | 196 | print(num) 197 | print(nums) 198 | print(person) 199 | 200 | 201 | demo(1) # 输出:1 () {} 202 | demo(1, 2, 3, 4, 5) # 输出:1, (2, 3, 4, 5) {} 203 | demo(1, 2, 3, 4, 5, name="小明", age=18) # 输出:1, (2,3,4,5) {name="小明",age=18} 204 | ``` 205 | 206 | >提示:多值参数的应用会经常出现在网络上一些大牛开发的框架中,知道多值参数,有利于读懂大牛的代码 207 | 208 | **多值参数案例 -- 计算任意多个数字的和** 209 | 210 | ```python 211 | import argparse 212 | 213 | 214 | def sum_numbers(*args): 215 | 216 | num = 0 217 | # 循环遍历 218 | for n in args: 219 | num += n 220 | 221 | print(args) 222 | return num 223 | 224 | 225 | res = sum_numbers(1, 2, 3, 4, 5) 226 | print(res) 227 | ``` 228 | 229 | **元组和字典的拆包** 230 | 231 | - 在调用带有多值参数的函数时,如果希望: 232 | - 将一个元组变量,直接传递给 `args` 233 | - 将一个字典变量,直接传递给 `kwargs` 234 | - 就可以使用**拆包**,简化参数传递,拆包的方式是: 235 | - 在元组变量前,增加一个 `*` 236 | - 在字典变量前,增加两个 `*` 237 | 238 | ```python 239 | def demo(*args, **kwargs): 240 | 241 | print(args) 242 | print(kwargs) 243 | 244 | 245 | # 元组/字典变量 246 | gl_num = (1, 2, 3) 247 | gl_dict = {"name":"小明", "age":18} 248 | 249 | # 会将两个参数都传递给 *args 250 | demo(gl_num, gl_dict) 251 | 252 | # 拆包语法,简化元组/自带你变量的传递 253 | demo(*gl_num, **gl_dict) 254 | 255 | # 等价于 256 | demo(1, 2, 3, name="小明", age=18) 257 | ``` 258 | 259 | ## 04.函数的递归 260 | 261 | >函数调用自身的**编程技巧**称为递归 262 | 263 | ### 4.1 递归函数的特点 264 | 265 | - 一个函数内部调用自己 266 | - 函数内部可以调用其他函数,当然在函数内部也可以调用自己 267 | - 函数内部的代码是相同的,只是针对参数不同,处理的结果不同 268 | - 当参数满足一个条件时,函数不再执行 269 | - 这个非常重要,通常被称为递归的出口,否则会出现死循环 270 | 271 | ```python 272 | def print_num(num): 273 | 274 | print(num) 275 | # 递归的出口,当参数满足某个条件时,不再执行函数 276 | if num == 1: 277 | return 278 | 279 | # 自己调用自己 280 | print_num(num - 1) 281 | 282 | 283 | print_num(3) 284 | ``` 285 | 286 | ![函数的递归调用](img/img20.png) 287 | 288 | ### 4.2 递归案例--计算数字累加 289 | 290 | 1. 定义一个函数 `sum_numbers` 291 | 2. 能够接受一个 `num` 的整数参数 292 | 3. 计算 `1+2+……num` 的结果 293 | 294 | ```python 295 | # 1. 定义一个函数 `sum_numbers` 296 | # 2. 能够接受一个 `num` 的整数参数 297 | # 3. 计算 `1+2+……num` 的结果 298 | 299 | def sum_numbers(num): 300 | 301 | # 1.出口 302 | if num == 1: 303 | return 1 304 | 305 | # 2.数字的累加 num + (1 2 3 ... num-1) 306 | # 假设 sum_numbers 能够正确处理 1 2 ... num-1 307 | return num + sum_numbers(num-1) 308 | 309 | 310 | res = sum_numbers(5) 311 | print(res) 312 | ``` 313 | 314 | ![递归调用示意图](img/img21.png) 315 | 316 | >提示:递归是一个编程技巧,在处理不确定的循环条件时,格外的有用,例如:**遍历整个文件目录的结构** 317 | 318 | -------------------------------------------------------------------------------- /13_读取文件/README: -------------------------------------------------------------------------------- 1 | hello 1 2 | hello 2 3 | hello 345 4 | thanks -------------------------------------------------------------------------------- /13_读取文件/ch_01_读取文件.py: -------------------------------------------------------------------------------- 1 | # 1.打开文件 2 | file = open("README") 3 | 4 | # 2.读取文件内容 5 | text = file.read() 6 | print(text) 7 | 8 | # 3.关闭文件 9 | file.close() -------------------------------------------------------------------------------- /13_读取文件/ch_02_读取文件后文件指针会改变.py: -------------------------------------------------------------------------------- 1 | # 1.打开文件 2 | file = open("README") 3 | 4 | # 2.读取文件内容 5 | text = file.read() 6 | print(text) 7 | print(len(text)) # 48 8 | print("-" * 50) 9 | 10 | text = file.read() 11 | print(text) 12 | print(len(text)) # 0 文件指针移动到读取内容的末尾,读取不到内容了 13 | 14 | # 3.关闭文件 15 | file.close() -------------------------------------------------------------------------------- /13_读取文件/ch_03_写入文件.py: -------------------------------------------------------------------------------- 1 | # 1.打开文件 2 | file = open("README", "a") 3 | 4 | # 2.写入文件 5 | file.write("DAY") 6 | 7 | # 3.关闭文件 8 | file.close() -------------------------------------------------------------------------------- /13_读取文件/ch_04_分行读取文件.py: -------------------------------------------------------------------------------- 1 | # 1.打开文件 2 | file = open("README") 3 | 4 | # 2.读取文件 5 | while True: 6 | # 每次读取一行 7 | text = file.readline() 8 | 9 | # 判断是否读取到内容 10 | if not text: 11 | break 12 | 13 | print(text, end="") 14 | 15 | # 关闭文件 16 | file.close() -------------------------------------------------------------------------------- /13_读取文件/ch_05_复制文件.py: -------------------------------------------------------------------------------- 1 | # 1.打开文件 2 | file_read = open("README") 3 | file_Write = open("README[复件]", "w") 4 | 5 | # 2.读、写文件 6 | text = file_read.read() 7 | file_Write.write(text) 8 | 9 | # 3.关闭文件 10 | file_read.close() 11 | file_Write.close() -------------------------------------------------------------------------------- /13_读取文件/ch_06_复制大文件.py: -------------------------------------------------------------------------------- 1 | # 1.打开文件 2 | file_read = open("README") 3 | file_Write = open("README[复件]", "w") 4 | 5 | # 2.读、写文件 6 | while True: 7 | # 读取一行内容 8 | text = file_read.readline() 9 | 10 | # 判断是否读取到内容 11 | if not text: 12 | break 13 | file_Write.write(text) 14 | 15 | # 3.关闭文件 16 | file_read.close() 17 | file_Write.close() -------------------------------------------------------------------------------- /13_读取文件/ch_07_python2字符串.py: -------------------------------------------------------------------------------- 1 | # coding=utf8 2 | 3 | # 引号前面的u告诉解释器这是一个 UTF-8 编码格式的字符串 4 | s = u"hello_世界" 5 | 6 | print(s) -------------------------------------------------------------------------------- /13_读取文件/ch_08_eval计算器.py: -------------------------------------------------------------------------------- 1 | input_str = input("请输入算术题:") 2 | print(eval(input_str)) -------------------------------------------------------------------------------- /15.面向对象封装.md: -------------------------------------------------------------------------------- 1 | # 面向对象封装案例 2 | 3 | ## 01.封装 4 | 5 | 1. 封装是面向对象编程的一大特点 6 | 2. 面向对象编程的第一步--将属性和方法封装到一个抽象的类中 7 | 3. 外界使用类创建对象,然后让对象调用方法 8 | 4. 对象方法的细节都被封装在类的内部 9 | 10 | ## 02.小明爱跑步 11 | 12 | 1. 小明体重 `75.0` 公斤 13 | 2. 小明每次跑步会减肥 `0.5` 公斤 14 | 3. 小明每次吃东西体重会增加 `1` 公斤 15 | 16 | ![封装示例](img/img26.png) 17 | 18 | >提示:**在对象的方法内部,是可以直接访问对象的属性** 19 | 20 | ```python 21 | class Person: 22 | 23 | def __init__(self, name, weight) -> None: 24 | 25 | # self.属性 = 形参 26 | self.name = name 27 | self.weight = weight 28 | 29 | def __str__(self) -> str: 30 | 31 | return "我的名字叫%s,体重是%.2f" % (self.name, self.weight) 32 | 33 | def run(self): 34 | print("%s 癌跑步,锻炼身体" % self.name) 35 | self.weight -= 0.5 36 | 37 | def eat(self): 38 | print("%s 是吃货,吃完这顿再减肥" % self.name) 39 | self.weight += 1 40 | 41 | 42 | xm = Person("小明", 75) 43 | xm.run() 44 | xm.eat() 45 | 46 | print(xm) 47 | ``` 48 | 49 | - 在对象的方法内部,是可以直接访问对象的属性 50 | - 同一个类创建的多个对象之间,属性互不干扰 51 | 52 | ## 03.摆放家具 53 | 54 | 1. 房子(House)有户型、总面积和家具名称列表 55 | - 新房子没有任何的家具 56 | 2. 家具(HouseItem)有名字和占地面积,其中 57 | - 席梦思(bed)占地 4 平米 58 | - 衣柜(chest)占地 2 平米 59 | - 餐桌(table)占地 1.5 平米 60 | 3. 将以上三件家具添加到房子中 61 | 4. 打印房子,要求输出:户型、总面积、剩余面积、家具名称列表 62 | 63 | ![摆放家具](img/img27.png) 64 | 65 | **剩余面积** 66 | 67 | 1. 在创建房子对象时,定义一个剩余面积的属性,初始值和总面积相等 68 | 2. 当调用 `add_item` 方法,向房间添加家具时,让剩余面积 -= 家具面积 69 | 70 | **添加家具** 71 | 72 | 1. 判断家具的面积是否超过剩余面积,如果超过,提示不能添加这家家具 73 | 2. 将家具名称追加到家具名称列表 74 | 3. 用房子的剩余面积 -= 家具面积 75 | 76 | ```python 77 | class HouseItem: 78 | 79 | def __init__(self, name, area) -> None: 80 | 81 | self.name = name 82 | self.area = area 83 | 84 | def __str__(self) -> str: 85 | 86 | return "[%s] 占地 %.2f" % (self.name, self.area) 87 | 88 | 89 | class House: 90 | 91 | def __init__(self, house_type, area) -> None: 92 | 93 | # 只有需要外部自定义初始值的属性才需要设置成初始化函数的形参 94 | self.house_type = house_type 95 | self.area = area 96 | # 剩余面积 97 | self.free_area = area 98 | # 家具名称列表 99 | self.item_list = [] 100 | 101 | def __str__(self) -> str: 102 | 103 | # Python 能自动地将一对括号内部地代码连接在一起 104 | return ("户型:%s\n总面积:%.2f[剩余:%.2f]\n家具:%s" 105 | % (self.house_type, self.area, 106 | self.free_area, self.item_list)) 107 | 108 | def add_item(self, item: HouseItem): 109 | 110 | print("要添加 %s" % item) 111 | # 1.判断家具的面积 112 | if item.area > self.free_area: 113 | print("%s 的面积过大,无法添加" % item.name) 114 | return 115 | # 2.将家具的名称添加到列表中 116 | self.item_list.append(item.name) 117 | # 3.计算剩余面积 118 | self.free_area -= item.area 119 | 120 | 121 | # 1.创建家具 122 | bed = HouseItem("席梦思", 4) 123 | chest = HouseItem("衣柜", 2) 124 | table = HouseItem("餐桌", 1.5) 125 | 126 | print(bed) 127 | print(chest) 128 | print(table) 129 | 130 | # 2.创建房子对象 131 | my_home = House("两室一厅", 60) 132 | 133 | my_home.add_item(bed) 134 | my_home.add_item(chest) 135 | my_home.add_item(table) 136 | 137 | print(my_home) 138 | ``` 139 | 140 | **小结** 141 | 142 | - 主程序只负责创建房子对象和家具对象 143 | - 让房子对象调用 `add_item` 方法将家具添加到房子中 144 | - 面积计算、剩余面积、家具列表等处理都被封装到房子类的内部 145 | 146 | ## 04.士兵突击 147 | 148 | >一个对象的属性可以是另外一个类创建的对象 149 | 150 | ### 4.1 需求 151 | 152 | 1. 士兵许三多有一把 AK47 153 | 2. 士兵可以开火 154 | 3. 枪能够发射子弹 155 | 4. 枪装填子弹--增加子弹数量 156 | 157 | ![士兵突击](img/img28.png) 158 | 159 | ### 4.2 开发士兵类 160 | 161 | >假设:每一个新兵都没有枪 162 | 163 | **定义没有初始值的属性** 164 | 165 | 在定义属性时,如果不知道设置什么初始值,可以设置为 `None` 166 | 167 | - `None` 关键字表示什么都没有 168 | - **表示一个空对象,没有方法和属性,是一个特殊的常量** 169 | - 可以将 `None` 赋值给任何一个变量 170 | 171 | **`fire` 方法需求** 172 | 173 | 1. 判断是否有枪,没有枪没法冲锋 174 | 2. 喊一声口号 175 | 3. 装填子弹 176 | 4. 射击 177 | 178 | ```python 179 | class Gun: 180 | 181 | def __init__(self, model: str) -> None: 182 | 183 | # 1.枪的型号 184 | self.model = model 185 | # 2.子弹的数量 186 | self.bullet_count = 0 187 | 188 | def add_bullet(self, count: int): 189 | 190 | self.bullet_count += count 191 | 192 | def shoot(self): 193 | 194 | # 1.判断子弹数量 195 | if self.bullet_count <= 0: 196 | print("[%s]没有子弹了" % self.model) 197 | return 198 | # 2.发射子弹 199 | self.bullet_count -= 1 200 | # 3.提示发射信息 201 | print("[%s] 突突突...[%s]" % (self.model, self.bullet_count)) 202 | 203 | 204 | class Soldier: 205 | 206 | def __init__(self, name: str) -> None: 207 | 208 | # 1.姓名 209 | self.name = name 210 | 211 | # 2.枪--新兵没有枪 212 | self.gun = None 213 | 214 | def fire(self): 215 | 216 | # 1.判断士兵是否有枪 217 | if self.gun == None: 218 | print("[%s]还么有枪..." % self.name) 219 | return 220 | # 2.高喊口号 221 | print("冲啊...[%s]" % self.name) 222 | # 3.装填子弹 223 | self.gun.add_bullet(50) 224 | # 4.发射 225 | self.gun.shoot() 226 | 227 | # 1.创建枪对象 228 | ak47 = Gun("AK47") 229 | 230 | # ak47.add_bullet(50) 231 | # ak47.shoot() 232 | 233 | # 2.创建士兵许三多 234 | xsd = Soldier("许三多") 235 | xsd.gun = ak47 236 | xsd.fire() 237 | print(xsd.gun) 238 | ``` 239 | 240 | ## 05.身份运算符 241 | 242 | 身份运算符用于**比较两个对象的内存地址是否一致**--是否是对同一个对象的引用 243 | 244 | - 在 Python 中针对 `None` 比较时,建议使用 `is` 判断 245 | 246 | | 运算符 | 描述 | 实例 | 247 | | -------- | ---------------------------------- | -------------------------------- | 248 | | `is` | 判断两个标识符是不是引用同一个对象 | `x is y` ,类似于 `id(x)==id(y)` | 249 | | `is not` | 判断两个表示符是不是引用不同对象 | `x is not y` ,类似于 `id(x)!=id(y)` | 250 | 251 | ### 5.1 `is` 与 `==` 区别 252 | 253 | - `is` 用于判断**两个变量引用对象是否为同一个** 254 | - `==` 用于判断**引用变量的值是否相等** 255 | 256 | ```python 257 | a = [1, 2, 3] 258 | b = [1, 2, 3] 259 | 260 | a == b # True 261 | 262 | a is b # False 263 | ``` 264 | 265 | -------------------------------------------------------------------------------- /16.私有属性和私有方法及继承.md: -------------------------------------------------------------------------------- 1 | #python 2022/9/3 2 | 3 | # 私有属性和私有方法 4 | 5 | ## 01.应用场景及定义方式 6 | 7 | **应用场景** 8 | 9 | - 在实际开发中,对象的某些属性或方法可能只希望在对象的内部被使用,而不希望在外部被访问到 10 | - 私有属性就是对象不希望公开的属性 11 | - 私有方法就是对象不希望公开的方法 12 | 13 | **定义方法** 14 | 15 | - 在定义属性或方法时,**在属性名或者方法名前增加两个下划线**,定义的就是私有属性或方法 16 | 17 | ![私有属性/方法示例](img/img29.png) 18 | 19 | ```python 20 | class Woman: 21 | 22 | def __init__(self, name) -> None: 23 | 24 | self.name = name 25 | self.__age = 18 26 | 27 | def __secret(self): 28 | # 在对象的方法内部,是可以访问对象的私有属性的 29 | print("%s 的年龄是 %d" % (self.name, self.__age)) 30 | 31 | 32 | a = Woman("小芳") 33 | 34 | # 私有属性,在外界不能直接访问 35 | # print(a.__age) 36 | 37 | # 私有方法,同样不允许在外界直接访问 38 | # a.__secret() 39 | ``` 40 | 41 | ## 02.伪私有属性和私有方法 42 | 43 | >提示:在日常开放中,不要使用以下这种方式,访问对象的私有属性或方法 44 | 45 | `Python` 中,并没有真正意义的私有 46 | 47 | - 在给属性、方法命名时,**实际是对名称做了一些特殊化处理,使得外界无法访问到** 48 | - 处理方式:在名称前面加上 `_类名` => `_类名__名称` 49 | 50 | ```python 51 | # 伪私有属性,在外界直接访问 52 | print(a._Woman__age) 53 | 54 | # 伪私有方法 55 | a._Woman__secret() 56 | ``` 57 | 58 | # 继承 59 | 60 | ## 目标 61 | 62 | - 单继承 63 | - 多继承 64 | 65 | **面向对象三大特性** 66 | 67 | 1. **封装**:根据职责将属性和方法封装到一个抽象的类中 68 | 2. **继承**:实现代码的重用,相同的代码不需要重复的编写 69 | 3. **多态**:不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度 70 | 71 | ## 01.单继承 72 | 73 | ### 1.1 继承的概念、语法和特点 74 | 75 | **继承的概念:子类拥有父类的所有方法和属性** 76 | 77 | ![继承对比图](img/img30.png) 78 | 79 | 1) **继承的语法** 80 | 81 | ```python 82 | class 类名(父类名): 83 | 84 | pass 85 | ``` 86 | 87 | - 子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发 88 | - 子类中应该根据职责,封装子类特有的属性和方法 89 | 90 | 2) **专业术语** 91 | 92 | - `Dog` 类是 `Animal` 类的子类,`Animal` 类是 `Dog` 类的父类,`Dog` 类从 `Animal` 类继承 93 | - `Dog` 类是 `Animal` 类的派生类,`Animal` 类是 `Dog` 类的基类,`Dog` 类从 `Animal` 类派生 94 | 95 | 3) **继承的传递性** 96 | 97 | - `C` 类从 `B` 类继承,`B` 类又从 `A` 类继承 98 | - 那么 `C` 类就具有 `B` 类和 `A` 类的所有属性和方法 99 | 100 | 子类拥有父类以及父类的父类中封装的所有属性和方法 101 | 102 | ### 1.2 方法的重写 103 | 104 | - 子类拥有父类的所有方法和属性 105 | - 子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发 106 | 107 | **应用场景** 108 | 109 | - 当父类的方法实现不能满足子类需求时,可以对方法进行**重写(override)** 110 | 111 | ![方法的重写](img/img31.png) 112 | 113 | - 重写父类方法有两种情况: 114 | 1. 覆盖父类的方法 115 | 2. 对父类方法进行扩展 116 | 117 | 1) **覆盖父类的方法** 118 | 119 | - 如果在开发中,父类的方法实现和子类的方法实现,完全不同 120 | - 就可以使用覆盖的方式,在子类中重新编写父类的方法实现 121 | - 重写之后,再运行时,只会调用子类中重写的放啊,而不再调用父类封装的方法 122 | 123 | >具体的实现方式,就相当于**在子类中定义了一个和父类同名的方法并且实现** 124 | 125 | 2) **对父类方法进行扩展** 126 | 127 | - 如果在开发中,子类的方法实现中包含父类的方法实现 128 | - 父类原本封装的方法实现是子类方法的一部分 129 | - 就可以使用扩展的方式 130 | 1. 在子类中重写父类的方法 131 | 2. 在需要的位置使用 `super().父类方法` 来调用父类方法的执行 132 | 3. 代码其他的位置针对子类的需求,编写子类特有的代码实现 133 | 134 | **关于 super** 135 | 136 | - 在 `Python` 中 `super` 是一个**特殊的类** 137 | - `super()` 就是使用 `super` 类**创建出来的对象** 138 | - 最常使用的场景就是**在重写父类方法时,调用在父类中封装的方法实现** 139 | 140 | **调用父类方法的另一种方式** 141 | 142 | >在 `Python 2.x` 时,如果需要调用父类的方法,还可以使用以下方式: 143 | 144 | ```python 145 | 父类名.方法(self) 146 | ``` 147 | 148 | - 这种方式,目前在 `Python 3.x` 还支持 149 | - 不推荐使用,因为一旦父类发生变化,方法调用位置的类名同样需要修改 150 | 151 | **提示** 152 | 153 | - 在开发时,`父类名` 和 `super()` 两种方式不要混用 154 | - 如果使用当前子类名调用方式,会形成递归掉调用,出现死循环 155 | 156 | ### 1.3 父类的私有属性和私有方法 157 | 158 | 1. 子类对象不能在自己的方法内部,直接访问父类的私有属性或私有方法 159 | 2. 子类对象可以通过父类的公有方法,间接访问到私有属性或私有方法 160 | 161 | >- 私有属性、方法是对象的隐私,不对外公开,外界以及子类都不能直接访问 162 | >- 私有属性、方法通常用于做一些内部的事情 163 | 164 | ![父类的私有属性和私有方法](img/img32.png) 165 | 166 | - `B` 的对象不能直接访问 `__num2` 属性 167 | - `B` 的对象不能在 `demo` 方法内访问 `__num2` 属性 168 | - `B` 的对象可以在 `demo` 方法内,调用父类的 `test` 方法 169 | - 父类的 `test` 方法内部,能够访问 `__num2` 属性和 `__test` 方法 170 | 171 | ## 02.多继承 172 | 173 | **概念** 174 | 175 | - 子类可以拥有多个父类,并且具有所有父类的属性和方法 176 | - 例如:孩子会继承自己父亲和母亲的特性 177 | 178 | ![多继承](img/img33.png) 179 | 180 | **语法** 181 | 182 | ```python 183 | class 子类名(父类名1,父类名2...): 184 | pass 185 | ``` 186 | 187 | ```python 188 | class A: 189 | 190 | def test(self): 191 | print("test 方法") 192 | 193 | 194 | class B: 195 | 196 | def demo(self): 197 | print("demo 方法") 198 | 199 | 200 | class C(A, B): 201 | """多继承可以让子类对象,同时具有多个父类的属性和方法""" 202 | pass 203 | 204 | # 创建子类对象 205 | c = C() 206 | 207 | c.test() 208 | c.demo() 209 | ``` 210 | 211 | ### 2.1 多继承的使用注意事项 212 | 213 | **问题的提出** 214 | 215 | - 如果不同的类中存在同名的方法,子类对象在调用方法时,会调用哪一个父类中的方法? 216 | 217 | >提示:**开发时,应该尽量避免这种容易产生混淆的情况**!--如果父类之间存在同名的属性或者方法,应该尽量避免使用多继承 218 | 219 | ![多继承](img/img34.png) 220 | 221 | **Python 中的 MRO -- 方法搜搜索顺序** 222 | 223 | - Python 中针对类提供了一个**内置属性** `__mro__` 可以查看方法搜索顺序 224 | - MRO 是 `method resolution order` ,主要用于**在多继承时判断方法、属性的调用路径** 225 | 226 | ```python 227 | print(C.__mro__) 228 | 229 | # 输出结果 230 | (, , , ) 231 | ``` 232 | 233 | - 在搜索方法时 ,是按照 `__mro__` 的输出结果**从左至右的书匈奴查找的** 234 | - 如果在当前类中**找到方法,就直接执行,不再搜索** 235 | - 如果**没有找到,就查下一个类**中是否有对应的方法,如果找到,就直接执行,不再搜索 236 | - 如果找到最后一个类,还没有找到方法,程序报错 237 | 238 | ### 2.2 新式类与旧式(经典)类 239 | 240 | >`object` 是 `Python` 为所有对象提供的基类,提供有一些内置的属性和方法,可以使用 `dir` 函数查看 241 | 242 | ```python 243 | class A: 244 | pass 245 | 246 | a = A() 247 | dir(a) 248 | ``` 249 | 250 | ![object的内置属性/方法](img/img35.png) 251 | 252 | - **新式类**:以 `object` 为基类的类,**推荐使用** 253 | - 经典类:不以 `object` 为基类的类,不推荐使用 254 | - 在 `Python 3.x` 中定义类时,如果没有指定父类,会默认使用 `object` 作为该类的基类 -- `Python 3.x` 中定义的类都是新式类 255 | - 在 `Python 2.x` 中定义的类,如果没有指定父类,则不会以 `object` 作为基类 256 | 257 | >新式类和经典类在多继承时 -- 会影响到方法的搜索顺序 258 | 259 | 为了保证编写的代码能够同时在 `Python 2.x` 和 `Python 3.x` 运行,今后在定义类时,如果没有父类,建议统一继承自 `object` 260 | 261 | ```python 262 | class 类名(object): 263 | pass 264 | ``` -------------------------------------------------------------------------------- /17.多态,类属性和类方法.md: -------------------------------------------------------------------------------- 1 | #python 2022/9/4 2 | 3 | # 多态 4 | 5 | ## 目标 6 | 7 | - 多态 8 | 9 | **面向对象三大特性** 10 | 11 | 1. 封装:根据职责将属性和方法封装到一个抽象的类中 12 | - 定义类的准则 13 | 2. 继承:实现代码的重用,相同的代码不需要重复的编写 14 | - 设计类的技巧 15 | - 子类针对自己特有的需求,编写特定的代码 16 | 3. 多态:不同的子类对象调用相同的父类方法,产生不同的执行结果 17 | - 多态可以增加代码的灵活度 18 | - **以继承和重写父类方法为前提** 19 | - 是调用方法的技巧,不会影响到类的内部设计 20 | 21 | ![多态示意图](img/img36.png) 22 | 23 | ## 多态案例演练 24 | 25 | **需求** 26 | 27 | 1. 在 `Dog` 类中封装方法 `game` 28 | - 普通狗只是简单的玩耍 29 | 2. 定义 `XiaoTianQuan` 继承自 `Dog` ,并且重写 `game` 方法 30 | - 哮天犬需要在天上玩耍 31 | 3. 定义 `Person` 类,并且封装一个和狗玩的方法 32 | - 在方法内部,直接让狗对象调用 `game` 方法 33 | 34 | ![多态演练示意图](img/img37.png) 35 | 36 | ```python 37 | class Dog(object): 38 | 39 | def __init__(self, name) -> None: 40 | self.name = name 41 | 42 | def game(self): 43 | print("%s 蹦蹦跳跳地玩耍..." % self.name) 44 | 45 | 46 | class XiaoTianDog(Dog): 47 | 48 | def game(self): 49 | print("%s 飞到天上玩耍..." % self.name) 50 | 51 | 52 | class Person(object): 53 | 54 | def __init__(self, name) -> None: 55 | self.name = name 56 | 57 | def game_with_dog(self, dog: Dog): 58 | print("%s 和 %s 快乐地玩耍..." % (self.name, dog.name)) 59 | # 让狗玩耍 60 | dog.game() 61 | 62 | 63 | # 1.创建 狗 对象 64 | # wangcai = Dog("旺财") 65 | wangcai = XiaoTianDog("飞天旺财") 66 | 67 | # 2.创建一个 小明 对象 68 | xiaoming = Person("小明") 69 | 70 | # 3.让小明调用和狗玩的方法 71 | xiaoming.game_with_dog(wangcai) 72 | ``` 73 | 74 | **案例小结** 75 | 76 | - `Person` 类中只需要让狗对象调用 `game` 方法,而不关心具体是什么狗 77 | - `game` 方法是在 `Dog` 父类中定义的 78 | - 在程序执行时,传入不同的狗对象实参,就会产生不同的执行效果 79 | 80 | # 类属性 81 | 82 | ## 01.类的结构 83 | 84 | ### 1.1 术语 -- 实例 85 | 86 | 1. 使用面向对象开发,第1步是设计类 87 | 2. 使用 类名() 创建对象,创建对象的动作有两步 88 | 1) 在内存中为对象**分配空间** 89 | 2) 调用初始化方法 `__init__` 为**对象初始化** 90 | 3. 对象创建后,内存中就有了一个对象的实实在在的存在 -- 实例 91 | 92 | ![类的结构示意图](img/img38.png) 93 | 94 | 因此,通常也会把: 95 | 96 | 1. 创建出来的对象叫作**类的实例** 97 | 2. 创建对象的当作叫作**实例化** 98 | 3. 对象的属性叫作**实例属性** 99 | 4. 对象调用的方法叫作**实例方法** 100 | 101 | 在程序执行时: 102 | 103 | 1. 对象各自拥有自己的实例属性 104 | 2. 调用对象方法,可以通过 `self.` 105 | - 访问自己的属性 106 | - 访问自己的方法 107 | 108 | **结论** 109 | 110 | - **每一个对象都有自己独立的内存空间,保存各自不同的属性** 111 | - **多个对象的方法,在内存中只有一份,在调用方法时,需要把对象的引用传递到方法内部** 112 | 113 | ### 1.2 类是一个特殊的对象 114 | 115 | >`Python` 中**一切皆对象**: 116 | > - `class AAA:` 定义的类属于类对象 117 | > - `obj1 = AAA()` 属于实例对象 118 | 119 | - 在程序运行时,类同样会被加载到内存 120 | - 在 `Python` 中,类是一个特殊的对象--类对象 121 | - 在程序运行时,类对象在内存中只有一份,使用一个类可以创建很多个对象实例 122 | - 除了封装实例的属性和方法外,类对象还可以拥有自己的属性和方法 123 | 1. 类属性 124 | 2. 类方法 125 | - 通过 `类名.` 的方式可以访问类的属性或者调用类的方法 126 | 127 | ![类的结构示意图](img/img39.png) 128 | 129 | ## 02.类属性和实例属性 130 | 131 | ### 2.1 概念和使用 132 | 133 | - 类属性就是给类对象中定义的属性 134 | - 通常**用来记录与这个类相关的特征** 135 | - 类属性不会用于记录具体对象的特征 136 | 137 | **示例需求** 138 | 139 | - 定义一个根据类 140 | - 每件工具都有自己的 `name` 141 | - 需求 -- 知道使用这个类,创建了多少个工具对象? 142 | 143 | ![类属性案例](img/img40.png) 144 | 145 | ```python 146 | class Tool(object): 147 | 148 | # 使用赋值语句定义类属性,记录所有工具对象的数量 149 | count = 0 150 | 151 | def __init__(self, name) -> None: 152 | self.name = name 153 | 154 | # 每次创建对象都会调用初始化方法 155 | Tool.count += 1 156 | 157 | 158 | # 1.创建工具对象 159 | tool1 = Tool("斧头") 160 | tool2 = Tool("锤子") 161 | tool3 = Tool("水桶") 162 | 163 | # 2.输出工具对象的数量 164 | print(Tool.count) 165 | ``` 166 | 167 | ### 2.2 属性的获取机制 168 | 169 | - 在 `Python` 中属性的获取存在一个**向上查找机制** 170 | 171 | ![通过对象访问类属性](img/img41.png) 172 | 173 | - 因此,要访问类属性有两种方式“ 174 | 1. 类名.类属性 175 | 2. 对象.类属性(不推荐) 176 | 177 | **注意** 178 | 179 | - 如果使用 `对象.类属性 = 值` 赋值语句,只会给对象添加一个实例属性,而不会影响到类属性的值 180 | 181 | ## 03.类方法和静态方法 182 | 183 | ### 3.1 类方法 184 | 185 | - **类属性**就是针对**类对象**定义的属性 186 | - **使用赋值语句在 `class` 关键字下方可以定义类属性** 187 | - 类属性用于记录与这个类相关的特征 188 | - 类方法就是针对类对象定义的方法 189 | - 在类方法内部可以直接访问类属性或者调用其他的类方法 190 | 191 | **语法如下** 192 | 193 | ```python 194 | @classmethod 195 | def 类方法名(cls): 196 | pass 197 | ``` 198 | 199 | - 类方法需要用修饰器 `@classmethod` 来标识,告诉解释器这是一个类方法 200 | - 类方法的第一个参数应该是 `cls` 201 | - 由哪一个类调用的方法,方法内的 `cls` 就是哪一个类的引用 202 | - 这个参数和实例方法的第一个参数是 `self` 类似 203 | - 提示:使用其他名称也可以,不过习惯使用 `cls` 204 | - 通过`类名.` 调用类方法时,不需要传递 `cls` 参数 205 | - 在方法内部 206 | - 可以通过 `cls.` 访问类的属性 207 | - 也可以通过 `cls.` 调用其他的类方法 208 | 209 | **示例需求** 210 | 211 | - 定义一个工具类 212 | - 每件工具都有自己的 `name` 213 | - 需求 -- 在类封装一个 `show_tool_count` 的类方法,输出使用当前这个类,创建的对象个数 214 | 215 | ![类方法案例](img/img42.png) 216 | 217 | ```python 218 | class Tool(object): 219 | 220 | # 使用赋值语句定义类属性,记录所有工具对象的数量 221 | count = 0 222 | 223 | @classmethod 224 | def show_tool_count(cls): 225 | 226 | print("工具对象的数量 %d" % cls.count) 227 | 228 | def __init__(self, name) -> None: 229 | self.name = name 230 | 231 | # 每次创建对象都会调用初始化方法 232 | Tool.count += 1 233 | 234 | 235 | # 创建工具对象 236 | tool1 = Tool("锤子") 237 | tool2 = Tool("榔头") 238 | 239 | # 调用类方法 240 | Tool.show_tool_count() 241 | ``` 242 | 243 | >在类方法内部,可以直接使用 `cls` **访问类属性或者调用类方法** 244 | 245 | ### 3.2 静态方法 246 | 247 | - 在开发时,如果需要在类中封装一个方法,这个方法: 248 | - 既不需要访问实例属性或者调用实例方法 249 | - 也不需要访问类属性或者调用类方法 250 | - 这个时候,可以把这个方法封装成一个静态方法 251 | 252 | **语法如下** 253 | 254 | ```python 255 | @staticmethod 256 | def 静态方法名(): 257 | pass 258 | ``` 259 | 260 | - **静态方法需要用修饰器 `@staticmethod` 来标识,告诉解释器这是一个静态方法** 261 | - 通过 `类名.` 调用静态方法 262 | 263 | ```python 264 | class Dog: 265 | 266 | @staticmethod 267 | def run(): 268 | # 不访问实例属性/类属性 269 | print("小狗要跑...") 270 | 271 | def __init__(self, name) -> None: 272 | 273 | self.name = name 274 | 275 | # 通过 类名. 调用静态方法 -- 不需要创建对象,就可以调用 276 | Dog.run() 277 | ``` 278 | 279 | ### 3.3 方法综合范例 280 | 281 | 1. 设计一个 `Game` 类 282 | 2. 属性: 283 | - 定义一个类属性 `top_score` 记录游戏的历史最高分 284 | - 定义一个实例属性 `player_name` 记录当前游戏的玩家姓名 285 | 3. 方法: 286 | - **静态方法**: `show_help` 显示游戏帮助信息 287 | - **类方法**: `show_top_score` 显示历史最高分 288 | - **实例方法**: `start_game` 开始当前玩家的游戏 289 | 4. 主程序步骤 290 | 1) 查看帮助信息 291 | 2) 查看历史最高分 292 | 3) 创建游戏对象,开始游戏 293 | 294 | ![[img43.png]] 295 | 296 | ```python 297 | class Game(object): 298 | 299 | # 历史最高分 300 | top_score = 0 301 | 302 | def __init__(self, player_name) -> None: 303 | self.player_name = player_name 304 | 305 | @staticmethod 306 | def show_help(): 307 | print("帮助信息:让僵尸进入大门") 308 | 309 | @classmethod 310 | def show_top_score(cls): 311 | print("历史记录 %d" % cls.top_score) 312 | 313 | def start_game(self): 314 | print("%s 开始游戏" % self.player_name) 315 | 316 | 317 | # 1.查看游戏的帮助信息 318 | Game.show_help() 319 | 320 | # 2.查看历史最高分 321 | Game.show_top_score() 322 | 323 | # 3.创建游戏对象 324 | game = Game("小明") 325 | game.start_game() 326 | ``` 327 | 328 | **案例小结** 329 | 330 | 1. **实例方法** -- 方法内部需要访问实例属性 331 | - 实例方法内部可以使用 `类名.` 访问类属性 332 | 2. **类方法** -- 方法内部**只**需要访问类属性 333 | 3. **静态方法** -- 方法内部,**不需要访问实例属性和类属性** 334 | 335 | **提问** 336 | 337 | 如果方法内部既需要访问实例属性,右需要访问类属性,应该定义成什么方法? 338 | 339 | >答案: 340 | >- 应该定义 **实例方法** 341 | >- 因为,类只有一个,在实例方法内部可以使用 `类名.` 访问类属性 -------------------------------------------------------------------------------- /18.单例.md: -------------------------------------------------------------------------------- 1 | #python 2022/9/4 2 | 3 | # 单例 4 | 5 | ## 目标 6 | 7 | - 单例设计模式 8 | - `__new__` 方法 9 | - Python 中的单例 10 | 11 | ## 01.单例设计模式 12 | 13 | - 设计模式 14 | - **设计模式是前人工作的总结和提炼**,通常被人们广泛流传的设计模式都是针对某一特定问题的成熟的解决方案 15 | - 使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性 16 | - 单例的设计模式 17 | - 目的 -- **让类创建的对象,在系统中只有唯一的一个实例** 18 | - 每一次执行 `类名()` 返回的对象,**内存地址是相同的** 19 | 20 | **单例设计模式的应用场景** 21 | 22 | - 音乐播放对象 23 | - 回收站对象 24 | - 打印机对象 25 | - ... 26 | 27 | ## 02. `__new__` 方法 28 | 29 | - 使用 `类名()` 创建对象时,Python的解释器首先会调用 `__new__` 方法为对象**分配空间** 30 | - `__new__` 是一个由 `object` 基类提供的**内置的静态方法**,主要作用有两个: 31 | 1) **在内存中为对象分配空间** 32 | 2) **返回对象的引用** 33 | - Python 的解释器获得对象的引用后,将引用作为第一个参数,传递给 `__init__` 方法 34 | 35 | >重写 `__new__` 方法的海马非常固定! 36 | 37 | - 重写 `__new__` 方法一定要 `return super().__new__(cls)` 38 | - 否则 Python 的解释器**得不到**分配了空间的对象引用,就不会调用对象的初始化方法 39 | - 注意:`__new__` 是一个静态方法,在调用时需要出动传递 `cls` 参数 40 | 41 | ![对象分配空间和初始化](img/img44.png) 42 | 43 | ```python 44 | class MusicPlayer: 45 | 46 | def __new__(cls, *args, **kwargs): 47 | # 1.创建对象时,new方法会被自动调用 48 | print("创建对象,分配空间") 49 | 50 | # 2.为对象分配空间 51 | instance = super().__new__(cls) 52 | 53 | # 3.返回对象的引用 54 | return instance 55 | 56 | def __init__(self) -> None: 57 | print("播放器初始化") 58 | 59 | 60 | # 创建播放器对象 61 | player = MusicPlayer() 62 | 63 | print(player) 64 | ``` 65 | 66 | ## 03.Python 中的单例 67 | 68 | - **单例 -- 让类创建的对象,在系统中只有唯一一个实例** 69 | 1. 定义一个类属性,初始值为 `None` ,用于记录单例对象的引用 70 | 2. 重写 `__new__` 方法 71 | 3. 如果类属性 `is None` ,调用父类方法分配空间,并在类属性中记录结果 72 | 4. 返回类属性中记录的对象引用 73 | 74 | ![单例流程](img/img45.png) 75 | 76 | ```python 77 | class MusicPlayer(object): 78 | 79 | # 记录第一个被创建对象的引用 80 | instance = None 81 | 82 | def __new__(cls, *args, **kwargs): 83 | # 1.判断类属性是否是空对象 84 | if cls.instance is None: 85 | # 2.调用父类的方法,为第一个对象分配空间 86 | cls.instance = super().__new__(cls) 87 | 88 | # 3.返回类属性保存的对象引用 89 | return cls.instance 90 | ``` 91 | 92 | **只执行一次初始化工作** 93 | 94 | - 在每次使用 `类名()` 创建对象时,Python 的解释器都会自动调用两个方法: 95 | 1) `__new__` 分配空间 96 | 2) `__init__` 对象初始化 97 | - 上个例子中对 `__new__` 方法改造之后,每次得到**第一次被创建对象的引用** 98 | - 但是,**初始化方法还会被再次调用** 99 | 100 | **需求** 101 | 102 | - 让初始化当作只被执行一次 103 | 104 | **解决办法** 105 | 106 | 1. 定义一个类属性 `init_flag` 标记是否执行过初始化动作,初始化为 `False` 107 | 2. 在 `__init__` 方法中,判断 `init_flag` ,如果为 `False` 就执行初始化动作 108 | 3. 然后将 `init_flag` 设置为 `True` 109 | 4. 这样,再次自动调用 `__init__` 方法时,初始化动作就不会被再次执行了 110 | 111 | ```python 112 | class MusicPlayer(object): 113 | 114 | # 记录第一个被创建对象的引用 115 | instance = None 116 | 117 | # 记录是否执行过初始化动作 118 | init_flag = False 119 | 120 | def __new__(cls, *args, **kwargs): 121 | # 1.判断类属性是否是空对象 122 | if cls.instance is None: 123 | # 2.调用父类的方法,为第一个对象分配空间 124 | cls.instance = super().__new__(cls) 125 | 126 | # 3.返回类属性保存的对象引用 127 | return cls.instance 128 | 129 | def __init__(self) -> None: 130 | # 1.判断是否执行过初始化动作 131 | if MusicPlayer.init_flag: 132 | return 133 | 134 | # 2.如果没有执行过,再执行初始化动作 135 | print("初始化播放器") 136 | 137 | # 3.修改类属性标记 138 | MusicPlayer.init_flag = True 139 | 140 | 141 | # 创建多个对象 142 | player1 = MusicPlayer() 143 | print(player1) 144 | 145 | player2 = MusicPlayer() 146 | print(player2) 147 | ``` -------------------------------------------------------------------------------- /19.异常.md: -------------------------------------------------------------------------------- 1 | #python 2022/9/5 2 | 3 | # 异常 4 | 5 | ## 目标 6 | 7 | - 异常的概念 8 | - 捕获异常 9 | - 异常的传递 10 | - 自定义异常 11 | 12 | ## 01.异常的概念 13 | 14 | - 程序在运行时,如果 `Python 解释器` 遇到一个错误,**会停止程序的执行,并且提示一些错误信息**,这就是**异常** 15 | - 程序停止执行并且提示错误信息这个动作,我们通常称之为:**抛出(raise)异常** 16 | 17 | >程序开发时,很难将所有的特殊情况都处理的面面俱到,通过**异常捕获**可以针对突发事件做集中的处理,从而保证程序的稳定性和健壮性 18 | 19 | ## 02.捕获异常 20 | 21 | ### 2.1 简单的捕获异常语法 22 | 23 | - 在程序开发中,如果对某些代码的执行不能确定是否正确,可以增加 `try(尝试)` 来捕获异常 24 | - 捕获异常最简单的语法格式: 25 | 26 | ```python 27 | try: 28 | 尝试执行的代码 29 | except: 30 | 出现错误的处理 31 | ``` 32 | 33 | - `try` 尝试,下方编写要尝试的代码,不确定是否能够正常执行的代码 34 | - `except` 如果不是,下方编写尝试失败的代码 35 | 36 | **简单异常捕获演练 -- 眼球用户输入整数** 37 | 38 | ```python 39 | try: 40 | # 不能确定正确执行的代码 41 | num = int(input("请输入一个整数:")) 42 | except: 43 | # 错误的处理代码 44 | print("请输入正确的整数格式") 45 | 46 | print("-" * 50) 47 | ``` 48 | 49 | ### 2.2 错误类型的捕获 50 | 51 | - 在程序执行时,可能会遇到不同类型的异常,并且需要**针对不同类型的异常,做出不同的响应,这个时候,就需要捕获错误类型** 52 | - 语法如下: 53 | 54 | ```python 55 | try: 56 | # 尝试执行的代码 57 | pass 58 | except 错误类型1: 59 | # 针对错误类型1,对应的代码处理 60 | pass 61 | except (错误类型2, 错误类型3): 62 | # 针对错误类型2 和 3,对应的代码处理 63 | pass 64 | except Exception as result: 65 | print("未知错误 %s " % result) 66 | ``` 67 | 68 | - 当 `Python` **解释器抛出异常时,最后一行错误信息的第一个单词,就是错误类型** 69 | 70 | **需求** 71 | 72 | 1. 提示用户输入一个整数 73 | 2. 使用 `8` 除以用户输入的整数并且输出 74 | 75 | ```python 76 | try: 77 | # 1. 提示用户输入一个整数 78 | num = int(input("输入一个整数:")) 79 | 80 | # 2. 使用 `8` 除以用户输入的整数并且输出 81 | res = 8 / num 82 | 83 | print(res) 84 | except ZeroDivisionError: 85 | print("除0错误") 86 | except ValueError: 87 | print("请输入正确的整数") 88 | ``` 89 | 90 | **捕获未知错误** 91 | 92 | - 在开发时,要预判到所有可能出现的错误,还是有一定难度的 93 | - 如果希望程序无论出现任何错误,都不会因为 `Python` 解释器抛出异常而被终止,可以再增加一个 `except` 94 | - 语法如下: 95 | 96 | ```python 97 | except Exception as result: 98 | print("未知错误 %s" % result) 99 | ``` 100 | 101 | ### 2.3 异常捕获完整语法 102 | 103 | - 在实际开发中,为了能够处理复杂的异常情况,实际的异常语法如下: 104 | 105 | >提示: 106 | >- 有关完整语法的应用场景,在后续学习中,结合实际的案例会更好理解 107 | 108 | ```python 109 | try: 110 | # 尝试执行的代码 111 | pass 112 | except 错误类型1: 113 | # 针对错误类型1,对应的代码处理 114 | pass 115 | except 错误类型2: 116 | # 针对错误类型2,对应的代码处理 117 | pass 118 | except (错误类型3, 错误类型4): 119 | # 针对错误类型3 和 4,对应的d代码处理 120 | pass 121 | except Exception as result: 122 | # 打印错误信息 123 | print(result) 124 | else: 125 | # 没有异常才会执行的代码 126 | pass 127 | finally: 128 | # 无论是否有异常,都会执行的代码 129 | print("无论是否有异常,都会执行的代码") 130 | ``` 131 | 132 | - `else` 只有在没有异常时才会执行的代码 133 | - `finally` 无论是否有异常,都会执行的代码 134 | - 之前一个演练的完整捕获异常代码如下: 135 | 136 | ```python 137 | try: 138 | # 1. 提示用户输入一个整数 139 | num = int(input("输入一个整数:")) 140 | 141 | # 2. 使用 `8` 除以用户输入的整数并且输出 142 | res = 8 / num 143 | 144 | print(res) 145 | except ValueError: 146 | print("请输入正确的整数") 147 | except Exception as result: 148 | print("未知错误 %s" % result) 149 | else: 150 | print("尝试成功") 151 | finally: 152 | print("无论是否出现异常都会执行的代码") 153 | 154 | print("-" * 20) 155 | ``` 156 | 157 | ## 03.异常的传递 158 | 159 | - 异常的传递 -- 当函数/方法执行出现异常,会将异常传递给函数/方法的调用一方 160 | - 如果传递到主程序,仍然没有异常处理,程序才会被终止 161 | - 在开发中,可以在主函数中增加异常捕获 162 | - 而在主函数中国调用的其他函数,只要出现异常,都会传递到主函数的异常捕获中 163 | - 这样就不需要在代码中,增加大量的异常捕获,能够保证代码的整洁 164 | 165 | **需求** 166 | 167 | 1. 定义函数 `demo1()` **提示用户输入一个函数并且返回** 168 | 2. 定义函数 `demo2()` 调用 `demo1()` 169 | 3. 在 主程序中调用 `demo2()` 170 | 171 | ```python 172 | def demo1(): 173 | return int(input("请输入整数:")) 174 | 175 | 176 | def demo2(): 177 | return demo1() 178 | 179 | # 利用异常的传递性,在主程序捕获异常 180 | try: 181 | print(demo2()) 182 | except Exception as result: 183 | print("未知错误 %s" % result) 184 | ``` 185 | 186 | ## 04.抛出 raise 异常 187 | 188 | ### 4.1 应用场景 189 | 190 | - 在开发中,除了代码执行出错 `python` 解释器会抛出异常之外 191 | - 还可以**根据应用程序特有的业务需求主动抛出异常** 192 | 193 | **示例** 194 | 195 | - 提示用户输入密码,如果长度少于8,抛出异常 196 | 197 | ![自定义异常](img/img46.png) 198 | 199 | **注意** 200 | 201 | - 当前函数只负责提示用户输入密码,如果密码长度不正确,需要其他函数进行额外处理 202 | - 因此可以抛出异常,由其他需要处理的函数捕获异常 203 | 204 | ```python 205 | 206 | ``` 207 | 208 | ### 4.2 抛出异常 209 | 210 | - 在 Python 中提供了一个 `Exception` 异常类 211 | - 在开发时,如果满足特定业务需求时,希望抛出异常,可以: 212 | 1. **创建一个 `Exception` 的对象** 213 | 2. **使用 `raise` 关键字抛出异常对象** 214 | 215 | **需求** 216 | 217 | - 定义 `inpyt_password` 函数,提示用户输入密码 218 | - 如果用户输入长度 <8,抛出异常 219 | - 如果用户输入长度 >= 8,返回输入的密码 220 | 221 | ```python 222 | def input_password(): 223 | 224 | # 1.提示用户输入密码 225 | pwd = input("请输入密码:") 226 | # 2.判断密码长度 >= 8,返回用户输入的密码 227 | if len(pwd) >= 8: 228 | return pwd 229 | # 3.如果 < 8,主动抛出异常 230 | print("主动抛出异常") 231 | # 1>创建异常对象 - 可以使用错误信息字符串作为参数 232 | ex = Exception("密码长度不够") 233 | # 2>主动抛出异常 234 | raise ex 235 | 236 | 237 | # 提示用户输入密码 238 | try: 239 | print(input_password()) 240 | except Exception as result: 241 | print(result) 242 | ``` -------------------------------------------------------------------------------- /20.模块.md: -------------------------------------------------------------------------------- 1 | #python 2022/9/5 2 | 3 | # 模块 4 | 5 | ## 目标 6 | 7 | - 模块 8 | - 包 9 | - 模块的制作 10 | 11 | ## 01.模块 12 | 13 | ### 1.1 模块的概念 14 | 15 | >模块是 Python 程序架构一个核心概念 16 | 17 | - 每一个以扩展名 `.py` 结尾的 `Python` 源代码文件都是一个模块 18 | - 模块名同样也是一个标识符,需要符合标识符的命名规则 19 | - 在模块中 定义的全局变量、函数、类都是提供给外界直接使用的工具 20 | - 模块就好比是工具包,要想使用这个工具包中工具,就需要先导入这个模块 21 | 22 | ### 1.2 模块的两种导入方式 23 | 24 | 1) **import 导入** 25 | 26 | ```python 27 | import 模块名1 28 | import 模块名2 29 | ``` 30 | 31 | >提示:在导入模块时,每个导入应该独占一行 32 | 33 | - 导入之后 34 | - 通过 `模块名.` 使用模块提供的工具 -- 全局变量、函数、类 35 | 36 | **使用 as 指定模块的别名** 37 | 38 | >如果模块的名字太长,可以使用 `as` 指定模块的名称,以方便在代码中的使用 39 | 40 | ```python 41 | import 模块1 as 模块别名 42 | ``` 43 | 44 | >注意:模块别名应该符合**大驼峰命名法** 45 | 46 | ```python 47 | # ch_01_测试模块1.py 48 | # 全局变量 49 | title = "模块1" 50 | 51 | # 函数 52 | def say_hello(): 53 | print("我是 %s" % title) 54 | 55 | 56 | # 类 57 | class Dog(object): 58 | pass 59 | 60 | # ch_02_测试模块2.py 61 | # 全局变量 62 | title = "模块2" 63 | 64 | # 函数 65 | def say_hello(): 66 | print("我是 %s" % title) 67 | 68 | 69 | # 类 70 | class Cat(object): 71 | pass 72 | 73 | # import导入模块 74 | import ch_01_测试模块1 as DogModule 75 | import ch_02_测试模块2 as CatModule 76 | 77 | DogModule.say_hello() 78 | CatModule.say_hello() 79 | 80 | dog = DogModule.Dog() 81 | print(dog) 82 | 83 | cat = CatModule.Cat() 84 | print(cat) 85 | ``` 86 | 87 | 2) **from ... import 导入** 88 | 89 | - 如果希望从某一个模块中,导入部分工具,就可以使用 `from ... import` 的方式 90 | - `import 模块名` 是一次性把模块中所有工具全部导入,并且通过 模块名/别名访问 91 | 92 | ```python 93 | # 从模块 导入 某一个工具 94 | from 模块1 import 工具名 95 | ``` 96 | 97 | - 导入之后 98 | - 不需要通过 `模块名.` 99 | - 可以直接使用**模块提供的工具 -- 全局变量、函数、类** 100 | 101 | >注意:如果两个模块,存在同名的函数,那么后导入模块的函数,会覆盖掉先导入的函数 102 | 103 | - 开发时 `import` 代码就应该统一写在代码的顶部,更容易及时发现冲突 104 | - 一旦发现冲突,可以使用 `as` 关键字**给其中一个工具起一个别名** 105 | 106 | - `from ... import *` 107 | 108 | ```python 109 | # 从模块导入所有故居 110 | from 模块名1 import * 111 | ``` 112 | 113 | >这种方式不推荐使用,因为函数重名并没有任何的提示,出现问题不好排查 114 | 115 | ### 1.3 模块的搜索顺序 116 | 117 | `Python` 的解释器在导入模块时,会: 118 | 119 | 1. 搜索当前目录指定模块名的文件,如果有就直接导入 120 | 2. 如果没有,再搜索系统目录 121 | 122 | >在开发时,给文件起名,**不要和系统的模块文件重名** 123 | >`Python` 中每一个模块都有一个内置属性 `__file__` 可以**查看导入模块的完整路径** 124 | 125 | ```python 126 | import random 127 | 128 | # 生成一个 0~10 的数字 129 | rand = random.randint(0, 10) 130 | 131 | print(rand) 132 | ``` 133 | 134 | >注意:如果当前目录下,存在一个 `random.py` 的文件按,程序就无法正常运行 135 | >这个时候,`Python` 的解释器会加载当前目录下的 `random.py` 而不会加载系统的 `random` 模块 136 | 137 | ### 原则 -- 每一个文件都应该是可以被导入的 138 | 139 | - 一个独立的 `Python` 文件就是一个模块 140 | - **在导入文件时,文件中所有没有任何缩进的代码都会被执行一遍**! 141 | 142 | **实际开发场景** 143 | 144 | - 在实际开发中,每一个模块都是独立开发的,大多都有专人负责 145 | - 开发人员通常会**在模块下发增加一些测试代码** 146 | - 仅在模块内部使用,而被导入到其他文件中不需要执行 147 | 148 | **`__main__` 属性** 149 | 150 | >- `__name__` 属性可以做到,测试模块的代码**只在测试情况下被运行,而在被导入时不会被执行**! 151 | 152 | - **`__name__` 是 `Python` 的一个内置属性,记录着一个字符串** 153 | - **如果是被其他文件导入,`__name__` 就是模块名** 154 | - **如果是当前执行的程序,`__name__` 是 `__main__`** 155 | 156 | 在很多 `Python` 文件中都会看到以下格式的代码: 157 | 158 | ```python 159 | # 导入模块 160 | # 定义全局变量 161 | # 定义类 162 | # 定义函数 163 | 164 | # 在代码的最下方 165 | def mian(): 166 | # ... 167 | pass 168 | 169 | # 根据 __name__ 判断是否执行下方代码 170 | if __name__ == "__main__": 171 | main() 172 | ``` 173 | 174 | ## 02.包 (Package) 175 | 176 | **概念** 177 | 178 | - 包是一个**包含多个模块的特殊目录** 179 | - 目录下有一个特殊的文件 `__init__.py` 180 | - 包名的命名方式和变量名一致,小写字母 + `_` 181 | 182 | **好处** 183 | 184 | - 使用 `import 保名` 可以**一次性导入包中所有模块** 185 | 186 | **案例演练** 187 | 188 | 1. 新建一个 `cm_message` 的包 189 | 2. 在目录下,新建两个文件 `send_message` 和 `receive_message` 190 | 3. 在 `send_message` 文件中定义一个 `send` 函数 191 | 4. 在 `receive_message` 文件中定义一个 `receive` 函数 192 | 5. 在外部直接导入 `hm_message` 的包 193 | 194 | **`__init__.py`** 195 | 196 | - 要在外界使用包中的模块,**需要在 `__init__.py` 中指定对外界提供的模块列表** 197 | 198 | ```python 199 | # __init__.py 200 | # 从 当前目录 导入 模块列表 201 | from . import send_message 202 | from . import receive_message 203 | 204 | 205 | # ch_10_导入包.py 206 | import ch_message 207 | 208 | ch_message.send_message.send("hello") 209 | 210 | txt = ch_message.receive_message.receive() 211 | print(txt) 212 | ``` 213 | 214 | ## 03.发布模块 215 | 216 | - 如果希望自己开发的模块,分享给其他人,可以按照以下步骤操作 217 | 218 | ### 3.1 制作发布压缩包步骤 219 | 220 | 1) 创建 `setup.py` 221 | 222 | ```python 223 | from distutils.core import setup 224 | 225 | setup(name="ch_message", # 包名 226 | version="1.0", # 版本 227 | description="Charlie's 发送和接收消息模块", # 描述信息 228 | long_description="完整的发送和接收消息模块", # 完整的描述信息 229 | author="CharlieHon", # 作者 230 | author_email="CharlieHon@charlie.com", 231 | url="https://github.com/CharlieHon/Python", # 主页 232 | py_modules=["ch_message.send_message", 233 | "ch_message.receive_message"] # 以列表形式指定压缩包中包含的模块的名称 234 | ) 235 | ``` 236 | 237 | [有关字典参数的详细信息,可以参考官方网站](https://docs.python.org/2/distutils/apiref.html) 238 | 239 | 2) **构建模块** 240 | 241 | ```python 242 | $ python3 setup.py build 243 | ``` 244 | 245 | 3) **生成发布压缩包** 246 | 247 | ```python 248 | $ python3 setup.py sdist 249 | ``` 250 | 251 | >在Windows终端中执行命令相同,这是只需要到对应目录下执行即可 252 | 253 | ### 3.2 安装模块(到系统路径) 254 | 255 | ```python 256 | $ tar -zxf ch_message-1.0.tar.gz 257 | 258 | $ sudo python3 setup.py install 259 | ``` 260 | 261 | **卸载模块** 262 | 263 | 直接从安装目录下,把安装模块的目录删除即可,如下例: 264 | 265 | ```python 266 | $ cd /usr/local/lib/python3.5/dist-package/ 267 | $ sudo rm -r ch_message 268 | ``` -------------------------------------------------------------------------------- /21.文件.md: -------------------------------------------------------------------------------- 1 | #python 2022/9/6 2 | 3 | ## 目标 4 | 5 | - 文件的概念 6 | - 文件的基本操作 7 | - 文件/文件夹的常用操作 8 | - 文本文件的编码方式 9 | 10 | ## 01.文件的概念 11 | 12 | ### 1.1 文件的概念和作用 13 | 14 | - 计算机的文件,就是存储在某种长期存储设备上的一段数据 15 | - 长期存储设备包括:硬盘、U盘、移动硬盘、光盘... 16 | 17 | **文件的作用** 18 | 19 | 将数据长期保存下来,在需要的时候使用 20 | 21 | | CPU | 内存 | 硬盘 | 22 | | --- | ---- | ---- | 23 | | ![](img/img47.jpg) | ![](img/img48.png) |![](img/img49.jpg) | 24 | 25 | ### 1.2 文件的存储方式 26 | 27 | - 在计算机中,文件是以**二进制**的方式保存在磁盘上的 28 | 29 | 文本文件和二进制文件 30 | 31 | - 文本文件 32 | - **可以使用文本编辑软件查看** 33 | - 本质上开始二进制文件 34 | - 例如:python 的源程序 35 | - 二进制文件 36 | - 保存的内容不是给他人直接阅读的,而是**提供给其他软件使用的** 37 | - 例如:图片文件、音频文件、视频文件等等 38 | - 二进制文件不能使用文本编辑软件查看 39 | 40 | ## 02.文件的基本操作 41 | 42 | ### 2.1 操作文件的套路 43 | 44 | 在计算机中要操作的文件的套路非常固定,一共包含三个步骤: 45 | 46 | 1. 打开文件 47 | 2. 读、写文件 48 | - **读** 将文件内容读入内存 49 | - **写** 将内存内容写入文件 50 | 3. 关闭文件 51 | 52 | ### 2.2 操作文件的函数/方法 53 | 54 | - 在 Python 中要操作文件需要记住 **1个函数 和 3个方法** 55 | 56 | | 序号 | 函数/方法 | 说明 | 57 | | ---- | --------- | ------------------------------ | 58 | | 01 | `open` | 打开文件,并且返回文件操作对象 | 59 | | 02 | `read` | 将文件内容读取到内存 | 60 | | 03 | `write` | 将指定内容写入文件 | 61 | | 04 | `close` | 关闭文件 | 62 | 63 | - `open` 函数负责打开文件,并且返回文件对象 64 | - `read/write/close` 三个方法都需要通过**文件对象**来调用 65 | 66 | ### 2.3 read 方法 -- 读取文件 67 | 68 | - `open` 函数的第一个参数是要打开的文件名 (文件名区分大小写) 69 | - **如果文件存在,返回文件从操作对象** 70 | - **如果文件不存在,会抛出异常** 71 | - `read` 方法可以一次性**读入并返回文件的所有内容** 72 | - `close` 方法负责**关闭文件** 73 | - 如果**忘记关闭文件,会造成系统资源消耗,而且会影响到后续对文件的访问** 74 | - 注意:**方法执行后,会把文件指针移动到文件的末尾** 75 | 76 | ```python 77 | # 1.打开文件 78 | file = open("README") 79 | 80 | # 2.读取文件内容 81 | text = file.read() 82 | print(text) 83 | 84 | # 3.关闭文件 85 | file.close() 86 | ``` 87 | 88 | **提示** 89 | 90 | - 在开发中,通常会先编写打开和关闭的代码,再编写中间针对文件的读/写操作! 91 | 92 | **文件指针** 93 | 94 | - **文件指针标记从哪个位置开始读取数据** 95 | - **第一次打开文件**时,通常**文件指针会指向文件的开始位置** 96 | - 当执行了 `read` 方法后,**文件指针会移动到读取内容的末尾** 97 | - 默认情况下移动到文件末尾 98 | 99 | **思考** 100 | 101 | - 如果执行了一次 `read` 方法,读取了所有内容,那么再次调用 `read` 方法,还能够获得到内容吗? 102 | - 不能 103 | - 第一次读取之后,文件指针移动到了文件末尾,再次调用不会读取到任何的内容 104 | 105 | ### 2.4 打开文件的方式 106 | 107 | - `open` 函数默认以**只读模式**打开文件,并且返回文件对象 108 | 109 | 语法如下: 110 | 111 | ```python 112 | f = open("文件名", "访问方式") 113 | ``` 114 | 115 | | 访问方式 | 说明 | 116 | | -------- | -------------------------------------------------------------------------------------------------------- | 117 | | `r` | 以**只读**方式打开文件。文件的指针将会放在文件的开头,这是**默认模式**。如果文件不存在,抛出异常 | 118 | | `w` | 以**只写**方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件 | 119 | | `a` | 以**追加**方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入 | 120 | | `r+` | 以**读写**方式打开文件。文件的指针将会放在文件的开头。如果文件不存在,抛出异常 | 121 | | `w+` | 以**读写**方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件 | 122 | | `a+` | 以**读写**方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入 | 123 | 124 | **提示** 125 | 126 | - 频繁的移动文件指针,会影响文件的读写效率,开发中更多的时候会以**只读、只写**的方式来操作文件 127 | 128 | ### 2.5 按行读取文件的内容 129 | 130 | - `read` 方法默认会把文件的**所有内容一次性读取到内存** 131 | - 如果文件太大,对内存的占用会非常严重 132 | 133 | **readline 方法** 134 | 135 | - `readline` 方法可以一次读取一行内容 136 | - 方法执行后,**会把文件指针移动到下一行**,准备再次读取 137 | 138 | **读取大文件的正确姿势** 139 | 140 | ```python 141 | # 1.打开文件 142 | file = open("README") 143 | 144 | # 2.读取文件 145 | while True: 146 | # 每次读取一行 147 | text = file.readline() 148 | 149 | # 判断是否读取到内容 150 | if not text: 151 | break 152 | print(text, end="") 153 | 154 | # 关闭文件 155 | file.close() 156 | ``` 157 | 158 | ### 2.6 文件读写案例 -- 复制文件 159 | 160 | **目标** 161 | 162 | 用代码的方式,来实现文件复制过程 163 | 164 | ![复制文件](img/img50.png) 165 | 166 | **小文件复制** 167 | 168 | - 打开一个已有文件,读取完整内容,并写入到另一个文件 169 | 170 | ```python 171 | # 1.打开文件 172 | file_read = open("README") 173 | file_Write = open("README[复件]", "w") 174 | 175 | # 2.读、写文件 176 | text = file_read.read() 177 | file_Write.write(text) 178 | 179 | # 3.关闭文件 180 | file_read.close() 181 | file_Write.close() 182 | ``` 183 | 184 | **大文件复制** 185 | 186 | - 打开一个已有文件,逐行读取内容,并顺序写入到另一个文件 187 | 188 | ```python 189 | # 1.打开文件 190 | file_read = open("README") 191 | file_Write = open("README[复件]", "w") 192 | 193 | # 2.读、写文件 194 | while True: 195 | # 读取一行内容 196 | text = file_read.readline() 197 | 198 | # 判断是否读取到内容 199 | if not text: 200 | break 201 | file_Write.write(text) 202 | 203 | # 3.关闭文件 204 | file_read.close() 205 | file_Write.close() 206 | ``` 207 | 208 | ## 03.文件/目录的常用管理操作 209 | 210 | - 在**终端/文件浏览器**中可以执行常规的**文件/目录**管理操作,例如: 211 | - 创建、重命名、删除、改变路径】查看目录内容、... 212 | - 在 Python 中,如果希望通过程序实现上述功能,**需要导入 `os` 模块** 213 | 214 | **文件操作** 215 | 216 | | 序号 | 方法名 | 说明 | 示例 | 217 | | ---- | -------- | ---------- | --------------------------------- | 218 | | 01 | `rename` | 重命名文件 | `os.rename(源文件名, 目标文件名)` | 219 | | 02 | `remove` | 删除文件 | `os.remove(文件名)` | 220 | 221 | **目录操作** 222 | 223 | | 序号 | 方法名 | 说明 | 示例 | 224 | | ---- | ------------ | -------------- | ------------------ | 225 | | 01 | `listdir` | 目录列表 | `os.listdir(目录名)` | 226 | | 02 | `mkdir` | 创建目录 | `os.mkdir(目录名)` | 227 | | 03 | `rmdir` | 删除目录 | `os.rmdir(目录名)` | 228 | | 04 | `getcwd` | 获取当前目录 | `os.getcwd()` | 229 | | 05 | `chdir` | 修改工作目录 | `os.chdir(目标目录)` | 230 | | 06 | `path.isdir` | 判断是否是目录 | `os.path.isdir(文件路径)` | 231 | 232 | >提示:文件或者目录操作都支持**相对路径和绝对路径** 233 | 234 | ## 04.文本文件的编码格式 235 | 236 | - 文本文件存储的内容是基于**字符编码**的文件,常见的编码有 `ASCII` 编码,`UNICODE` 编码等 237 | 238 | >Python 2.x 默认使用 `ASCII` 编码 239 | >Python 3.x 默认使用 `UTF-8` 编码 240 | 241 | ### 4.1 ASCII 编码 和 UNICODE 编码 242 | 243 | **ASCII 编码** 244 | 245 | - 计算机中只有 `256` 个 `ASCII` 字符 246 | - 一个 `ASCII` 在内存中占用 **1个字节** 的空间 247 | - `8` 个 `0/1` 的排列组合方式一共有 `256` 种,也就是 `2^8` 248 | 249 | ![ASCII编码](img/img51.png) 250 | 251 | **UTF-8 编码格式** 252 | 253 | - 计算机中使用 **1-6个字节** 来标识一个 `UTF-8` 字符,**涵盖了地球上几乎所有地区的文字** 254 | - 大多数汉字会使用**3个字节**表示 255 | - `UTF-8` 是 `UNICODE` 编码的一种编码格式 256 | 257 | ### 4.2 Python 2.x 中如何使用中文 258 | 259 | >Python 2.x 默认使用 `ASCII` 编码格式 260 | >Python 3.x 默认使用 `UTF-8` 编码格式 261 | 262 | - 在 Python 2.x 文件的第一行增加以下代码,解释器会以 `utf-8` 编码来处理 Python 文件 263 | 264 | ```python 265 | # *-* cooding:utf8 *-* 266 | ``` 267 | 268 | - 也可以使用 269 | 270 | ```python 271 | # coding=utf8 272 | ``` 273 | 274 | **unicode 字符串** 275 | 276 | - 在 `Python 2.x` 中,即使指定了文件使用 `UTF-8` 的编码格式,但是在遍历字符串时,仍然会 **以字节为单位遍历** 字符串 277 | - 要能够**正确地遍历字符串**,在定义字符串时,需要**在字符串地引号前,增加一个小写字母 `u`** ,告诉解释器这是一个 `unicode` 字符串(使用 `UTF-8` 编码格式的字符串) -------------------------------------------------------------------------------- /22.eval函数.md: -------------------------------------------------------------------------------- 1 | #python 2022/9/6 2 | 3 | ## eval 函数 4 | 5 | `eval()` 函数十分强大--**将字符串当成有效的表达式来求值并返回计算结果** 6 | 7 | ```python 8 | # 基本的数学计算 9 | In[1]: eval("1 + 1") 10 | Out[1]: 2 11 | 12 | # 字符串重复 13 | In[2]: eval("'*' * 10") 14 | Out[2]: '**********' 15 | 16 | # 将字符串转换成列表 17 | In[3]: type(eval("[1, 2, 3, 4, 5]")) 18 | Out[3]: list 19 | 20 | # 将字符串转换成字典 21 | In[4]: type(eval("{'name':'xiaoming', 'age':18}")) 22 | Out[4]: dict 23 | 24 | ``` 25 | 26 | ## 案例-计算器 27 | 28 | **需求** 29 | 30 | 1. 提示用户输入一个加减乘除混合运算 31 | 2. 返回计算结果 32 | 33 | ```python 34 | input_str = input("请输入算术题:") 35 | print(eval(input_str)) 36 | ``` 37 | 38 | ## 不要滥用 eval 39 | 40 | >在开发时千万不要使用 `eval` 直接转换 `input` 的结果 41 | 42 | ```python 43 | # 可以执行任何终端命令,不安全! 44 | __import__('os').system('ls') 45 | ``` 46 | 47 | - 等价代码 48 | 49 | ```python 50 | import os 51 | 52 | os.system("终端命令") 53 | ``` 54 | 55 | - 执行成功,返回 0 56 | - 执行失败,返回错误信息 -------------------------------------------------------------------------------- /24.项目实战2 - 游戏框架搭建.md: -------------------------------------------------------------------------------- 1 | #python 2022/9/8 2 | 3 | # 游戏框架搭建 4 | 5 | 目标 -- 使用面向对象设计飞机大战游戏类 6 | 7 | ## 目标 8 | 9 | - 明确主程序职责 10 | - 实现主程序类 11 | - 准备游戏精灵类 12 | 13 | ## 01.明确主程序职责 14 | 15 | - 回顾快速入门案例,一个游戏主程序的职责可以分为两个部分: 16 | - 游戏初始化 17 | - 游戏训话 18 | - 根据明确的职责,设计 `PlaneGame` 类如下: 19 | 20 | ![游戏主程序](img/img60.png) 21 | 22 | >提示根据职责封装私有方法,可以避免某一个方法的代码写得太过冗长,如果某一个方法编写的太长,既不好阅读,也不好维护! 23 | 24 | - **游戏初始化** -- `__init__()` 会调用以下方法 25 | 26 | | 方法 | 职责 | 27 | | ------------------------ | -------------------------------------- | 28 | | `__event_handler(self)` | 事件监听 | 29 | | `__checkcollide(self)` | 碰撞检测 -- 子弹销毁敌机、敌机撞毁英雄 | 30 | | `__update_sprites(self)` | 精灵组更新和绘制 | 31 | | `__game_over()` | 游戏结束 | 32 | 33 | ## 03.实现飞机大战主游戏类 34 | 35 | ### 2.1 明确文件职责 36 | 37 | ![程序文件职责](img/img61.png) 38 | 39 | - `plane_main` 40 | 1. 封装 主游戏类 41 | 2. 创建 游戏对象 42 | 3. 启动游戏 43 | - `plane_sprites` 44 | 1. 封装游戏中所有需要使用的精灵子类 45 | 2. 提供游戏的相关根据 46 | 47 | **代码实现** 48 | 49 | - 新建 `plane_main.py` 文件,并且设置为可执行 50 | - 编写基础代码 51 | 52 | ```python 53 | import pygame 54 | from plane_sprites import * 55 | 56 | 57 | class PlaneGame(object): 58 | """飞机大战主游戏类""" 59 | 60 | def __init__(self) -> None: 61 | print("游戏初始化") 62 | 63 | # 1.创建游戏的窗口 64 | self.screen = pygame.display.set_mode((480, 700)) 65 | # 2.创建游戏的时钟 66 | self.clock = pygame.time.Clock() 67 | # 3.调用私有方法,精灵和精灵组的创建 68 | self.__create_sprites() 69 | 70 | def __create_sprites(self): 71 | pass 72 | 73 | def start_game(self): 74 | print("游戏开始...") 75 | 76 | 77 | 78 | if __name__ == "__main__": 79 | 80 | # 创建游戏对象 81 | game = PlaneGame() 82 | 83 | # 启动游戏 84 | game.start_game() 85 | ``` 86 | 87 | **使用常量代替固定的数值** 88 | 89 | >- 常量 -- 不变化的量 90 | >- 变量 -- 可以变化的量 91 | 92 | **应用场景** 93 | 94 | - 在开发时,可能会需要使用固定的数值,例如 屏幕的高度是 `700` 95 | - 这个时候,建议不要直接使用固定数值,而应该使用**常量** 96 | - 在开发时,为了保证代码的可维护性,尽量不要使用 **魔法数字** 97 | 98 | **常量的定义** 99 | 100 | - 定义常量和定义变量的语法完全一样,都是使用赋值语句 101 | - **常量的命名**应该**所有字母都使用大写,单词与单词之间使用下划线连接** 102 | 103 | >提示:Python 中并没有真正意义的常量,只是通过命名的约定 -- 所有字母都是大写的就是常量,开发时不要轻易修改! 104 | 105 | **代码调整** 106 | 107 | - 在 `plane_sprites.py` 中增加常量定义 108 | 109 | ```python 110 | # 屏幕大小的常量 111 | SCREEN_RECT = pygame.Rect(0, 0, 480, 700) 112 | # 屏幕刷新率 113 | FRAME_PER_SEC = 60 114 | ``` 115 | 116 | ```python 117 | # coding=utf8 118 | from logging import PlaceHolder 119 | import pygame 120 | from plane_sprites import * 121 | 122 | 123 | class PlaneGame(object): 124 | """飞机大战主游戏类""" 125 | 126 | def __init__(self) -> None: 127 | print("游戏初始化") 128 | 129 | # 1.创建游戏的窗口 130 | self.screen = pygame.display.set_mode(SCREEN_RECT.size) 131 | # 2.创建游戏的时钟 132 | self.clock = pygame.time.Clock() 133 | # 3.调用私有方法,精灵和精灵组的创建 134 | self.__create_sprites() 135 | 136 | def __create_sprites(self): 137 | pass 138 | 139 | def start_game(self): 140 | print("游戏开始...") 141 | 142 | while True: 143 | # 1.设置刷新帧率 144 | self.clock.tick(FRAME_PER_SEC) 145 | # 2.事件监听 146 | self.__event_handler() 147 | # 3.碰撞检测 148 | self.__check_collider() 149 | # 4.更新/绘制精灵组 150 | self.__update_sprites() 151 | # 5.更新显示 152 | pygame.display.update() 153 | 154 | def __event_handler(self): 155 | for event in pygame.event.get(): 156 | # 判断是否退出游戏 157 | if event.type == pygame.QUIT: 158 | PlaneGame.__game_over() 159 | 160 | def __check_collider(self): 161 | pass 162 | 163 | def __update_sprites(self): 164 | pass 165 | 166 | @staticmethod 167 | def __game_over(): 168 | print("游戏结束...") 169 | pygame.quit() 170 | exit() 171 | 172 | 173 | if __name__ == "__main__": 174 | 175 | # 创建游戏对象 176 | game = PlaneGame() 177 | 178 | # 启动游戏 179 | game.start_game() 180 | ``` -------------------------------------------------------------------------------- /img/img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img1.png -------------------------------------------------------------------------------- /img/img10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img10.png -------------------------------------------------------------------------------- /img/img11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img11.png -------------------------------------------------------------------------------- /img/img12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img12.png -------------------------------------------------------------------------------- /img/img13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img13.png -------------------------------------------------------------------------------- /img/img14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img14.png -------------------------------------------------------------------------------- /img/img15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img15.png -------------------------------------------------------------------------------- /img/img16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img16.png -------------------------------------------------------------------------------- /img/img17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img17.png -------------------------------------------------------------------------------- /img/img18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img18.png -------------------------------------------------------------------------------- /img/img19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img19.png -------------------------------------------------------------------------------- /img/img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img2.png -------------------------------------------------------------------------------- /img/img20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img20.png -------------------------------------------------------------------------------- /img/img21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img21.png -------------------------------------------------------------------------------- /img/img22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img22.png -------------------------------------------------------------------------------- /img/img23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img23.png -------------------------------------------------------------------------------- /img/img24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img24.png -------------------------------------------------------------------------------- /img/img25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img25.png -------------------------------------------------------------------------------- /img/img26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img26.png -------------------------------------------------------------------------------- /img/img27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img27.png -------------------------------------------------------------------------------- /img/img28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img28.png -------------------------------------------------------------------------------- /img/img29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img29.png -------------------------------------------------------------------------------- /img/img3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img3.png -------------------------------------------------------------------------------- /img/img30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img30.png -------------------------------------------------------------------------------- /img/img31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img31.png -------------------------------------------------------------------------------- /img/img32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img32.png -------------------------------------------------------------------------------- /img/img33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img33.png -------------------------------------------------------------------------------- /img/img34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img34.png -------------------------------------------------------------------------------- /img/img35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img35.png -------------------------------------------------------------------------------- /img/img36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img36.png -------------------------------------------------------------------------------- /img/img37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img37.png -------------------------------------------------------------------------------- /img/img38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img38.png -------------------------------------------------------------------------------- /img/img39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img39.png -------------------------------------------------------------------------------- /img/img4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img4.png -------------------------------------------------------------------------------- /img/img40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img40.png -------------------------------------------------------------------------------- /img/img41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img41.png -------------------------------------------------------------------------------- /img/img42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img42.png -------------------------------------------------------------------------------- /img/img43.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img43.png -------------------------------------------------------------------------------- /img/img44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img44.png -------------------------------------------------------------------------------- /img/img45.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img45.png -------------------------------------------------------------------------------- /img/img46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img46.png -------------------------------------------------------------------------------- /img/img47.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img47.jpg -------------------------------------------------------------------------------- /img/img48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img48.png -------------------------------------------------------------------------------- /img/img49.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img49.jpg -------------------------------------------------------------------------------- /img/img5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img5.jpg -------------------------------------------------------------------------------- /img/img50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img50.png -------------------------------------------------------------------------------- /img/img51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img51.png -------------------------------------------------------------------------------- /img/img52.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img52.png -------------------------------------------------------------------------------- /img/img53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img53.png -------------------------------------------------------------------------------- /img/img54.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img54.png -------------------------------------------------------------------------------- /img/img55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img55.png -------------------------------------------------------------------------------- /img/img56.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img56.gif -------------------------------------------------------------------------------- /img/img57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img57.png -------------------------------------------------------------------------------- /img/img58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img58.png -------------------------------------------------------------------------------- /img/img59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img59.png -------------------------------------------------------------------------------- /img/img6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img6.jpg -------------------------------------------------------------------------------- /img/img60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img60.png -------------------------------------------------------------------------------- /img/img61.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img61.png -------------------------------------------------------------------------------- /img/img62.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img62.png -------------------------------------------------------------------------------- /img/img63.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img63.png -------------------------------------------------------------------------------- /img/img64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img64.png -------------------------------------------------------------------------------- /img/img65.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img65.png -------------------------------------------------------------------------------- /img/img66.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img66.png -------------------------------------------------------------------------------- /img/img67.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img67.png -------------------------------------------------------------------------------- /img/img68.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img68.png -------------------------------------------------------------------------------- /img/img69.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img69.png -------------------------------------------------------------------------------- /img/img7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img7.png -------------------------------------------------------------------------------- /img/img70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img70.png -------------------------------------------------------------------------------- /img/img71.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img71.png -------------------------------------------------------------------------------- /img/img72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img72.png -------------------------------------------------------------------------------- /img/img73.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img73.png -------------------------------------------------------------------------------- /img/img75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img75.png -------------------------------------------------------------------------------- /img/img76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img76.png -------------------------------------------------------------------------------- /img/img8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img8.png -------------------------------------------------------------------------------- /img/img9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/img/img9.png -------------------------------------------------------------------------------- /飞机大战/__pycache__/plane_sprites.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/__pycache__/plane_sprites.cpython-38.pyc -------------------------------------------------------------------------------- /飞机大战/ch_01_pygame入门.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | pygame.init() 4 | 5 | # 编写游戏的代码 6 | 7 | print("游戏的代码...") 8 | 9 | pygame.quit() -------------------------------------------------------------------------------- /飞机大战/ch_02_使用Rect描述英雄.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | hero_rect = pygame.Rect(100, 500, 120, 125) 4 | 5 | print("英雄的原点 %d %d" % (hero_rect.x, hero_rect.y)) # 100 500 6 | print("英雄的尺寸 %d %d" % (hero_rect.width, hero_rect.height)) # 120 125 7 | print("英雄的尺寸 %d %d" % hero_rect.size) # 120 125 8 | -------------------------------------------------------------------------------- /飞机大战/ch_03_创建游戏主屏幕.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | pygame.init() 4 | 5 | # 创建游戏主屏幕 6 | screen = pygame.display.set_mode((480, 700)) 7 | while True: 8 | pass 9 | 10 | pygame.quit() -------------------------------------------------------------------------------- /飞机大战/ch_04_绘制图像.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | pygame.init() 4 | 5 | # 创建游戏窗口 480 * 700 6 | screen = pygame.display.set_mode((480, 700)) 7 | 8 | # 绘制背景图像 9 | # 1>加载图像数据 10 | bg = pygame.image.load("./飞机大战/images/background.png") 11 | # 2>blit 绘制图像 12 | screen.blit(bg, (0,0)) 13 | # 3>update 更新屏幕显示 14 | pygame.display.update() 15 | 16 | # while True: 17 | # pass 18 | 19 | pygame.quit() -------------------------------------------------------------------------------- /飞机大战/ch_05_绘制英雄图像.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | pygame.init() 4 | 5 | # 创建游戏窗口 480 * 700 6 | screen = pygame.display.set_mode((480, 700)) 7 | 8 | # 绘制背景图像 9 | # 1>加载图像数据 10 | bg = pygame.image.load("./飞机大战/images/background.png") 11 | # 2>blit 绘制图像 12 | screen.blit(bg, (0,0)) 13 | # 3>update 更新屏幕显示 14 | pygame.display.update() 15 | 16 | # 绘制英雄的飞机 17 | hero = pygame.image.load("./飞机大战/images/me1.png") 18 | screen.blit(hero, (200, 500)) 19 | pygame.display.update() 20 | 21 | while True: 22 | pass 23 | 24 | 25 | pygame.quit() -------------------------------------------------------------------------------- /飞机大战/ch_06_update方法.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | pygame.init() 4 | 5 | # 创建游戏窗口 480 * 700 6 | screen = pygame.display.set_mode((480, 700)) 7 | 8 | # 绘制背景图像 9 | bg = pygame.image.load("./飞机大战/images/background.png") 10 | screen.blit(bg, (0,0)) 11 | 12 | # 绘制英雄飞机 13 | hero = pygame.image.load("./飞机大战/images/me1.png") 14 | screen.blit(hero, (200, 500)) 15 | 16 | # 更新屏幕显示,可以在所有绘制工作完成之后,统一调用 update 方法 17 | pygame.display.update() 18 | 19 | 20 | while True: 21 | pass 22 | 23 | pygame.quit() -------------------------------------------------------------------------------- /飞机大战/ch_07_认识游戏循环.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | # 游戏的初始化 4 | pygame.init() 5 | 6 | # 创建游戏窗口 480 * 700 7 | screen = pygame.display.set_mode((480, 700)) 8 | 9 | # 绘制背景图像 10 | bg = pygame.image.load("./飞机大战/images/background.png") 11 | screen.blit(bg, (0,0)) 12 | 13 | # 绘制英雄飞机 14 | hero = pygame.image.load("./飞机大战/images/me1.png") 15 | screen.blit(hero, (200, 500)) 16 | 17 | # 更新屏幕显示,可以在所有绘制工作完成之后,统一调用 update 方法 18 | pygame.display.update() 19 | 20 | # 创建时钟对象 21 | clock = pygame.time.Clock() 22 | 23 | # 游戏循环 -> 意味着游戏的正式开始 24 | i = 0 25 | while True: 26 | # tick()的参数指定循环体内部的代码执行的频率 27 | clock.tick(60) 28 | print(i) 29 | i += 1 30 | 31 | pygame.quit() -------------------------------------------------------------------------------- /飞机大战/ch_08_更新英雄的位置.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | # 游戏的初始化 4 | pygame.init() 5 | 6 | # 创建游戏窗口 480 * 700 7 | screen = pygame.display.set_mode((480, 700)) 8 | 9 | # 绘制背景图像 10 | bg = pygame.image.load("./飞机大战/images/background.png") 11 | screen.blit(bg, (0,0)) 12 | 13 | # 绘制英雄飞机 14 | hero = pygame.image.load("./飞机大战/images/me1.png") 15 | screen.blit(hero, (200, 500)) 16 | 17 | # 更新屏幕显示,可以在所有绘制工作完成之后,统一调用 update 方法 18 | pygame.display.update() 19 | 20 | # 创建时钟对象 21 | clock = pygame.time.Clock() 22 | 23 | # 1.定义 rect记录飞机的初始位置 24 | hero_rect = pygame.Rect(200, 500, 102, 126) 25 | 26 | # 游戏循环 -> 意味着游戏的正式开始 27 | while True: 28 | # tick()的参数指定循环体内部的代码执行的频率 29 | clock.tick(60) 30 | 31 | # 2.修改飞机的位置 32 | hero_rect.y -= 1 33 | # 当飞机底部超出屏幕时,飞机从主屏幕进入 34 | if hero_rect.bottom <= 0: 35 | hero_rect.y = 700 36 | # 3.调用 blit 方法绘制图像 37 | screen.blit(bg, (0,0)) 38 | screen.blit(hero, hero_rect) 39 | # 4.调用 update 方法更新显示 40 | pygame.display.update() 41 | 42 | pygame.quit() -------------------------------------------------------------------------------- /飞机大战/ch_09_事件监听.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | # 游戏的初始化 4 | pygame.init() 5 | 6 | # 创建游戏窗口 480 * 700 7 | screen = pygame.display.set_mode((480, 700)) 8 | 9 | # 绘制背景图像 10 | bg = pygame.image.load("./飞机大战/images/background.png") 11 | screen.blit(bg, (0,0)) 12 | 13 | # 绘制英雄飞机 14 | hero = pygame.image.load("./飞机大战/images/me1.png") 15 | screen.blit(hero, (200, 500)) 16 | 17 | # 更新屏幕显示,可以在所有绘制工作完成之后,统一调用 update 方法 18 | pygame.display.update() 19 | 20 | # 创建时钟对象 21 | clock = pygame.time.Clock() 22 | 23 | # 1.定义 rect记录飞机的初始位置 24 | hero_rect = pygame.Rect(200, 500, 102, 126) 25 | 26 | # 游戏循环 -> 意味着游戏的正式开始 27 | while True: 28 | # tick()的参数指定循环体内部的代码执行的频率 29 | clock.tick(60) 30 | 31 | # 监听事件 32 | for event in pygame.event.get(): 33 | # 判断事件类型是否是退出事件 34 | if event.type == pygame.QUIT: 35 | print("游戏退出...") 36 | 37 | # quit 卸载所有的模块 38 | pygame.quit() 39 | 40 | # exit() 直接终止当前正在执行的程序 41 | exit() 42 | 43 | # 2.修改飞机的位置 44 | hero_rect.y -= 1 45 | # 当飞机底部超出屏幕时,飞机从主屏幕进入 46 | if hero_rect.bottom <= 0: 47 | hero_rect.y = 700 48 | # 3.调用 blit 方法绘制图像 49 | screen.blit(bg, (0,0)) 50 | screen.blit(hero, hero_rect) 51 | # 4.调用 update 方法更新显示 52 | pygame.display.update() 53 | 54 | pygame.quit() -------------------------------------------------------------------------------- /飞机大战/ch_10_演练精灵.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from plane_sprites import * 3 | 4 | # 游戏的初始化 5 | pygame.init() 6 | 7 | # 创建游戏窗口 480 * 700 8 | screen = pygame.display.set_mode((480, 700)) 9 | 10 | # 绘制背景图像 11 | bg = pygame.image.load("./飞机大战/images/background.png") 12 | screen.blit(bg, (0,0)) 13 | 14 | # 绘制英雄飞机 15 | hero = pygame.image.load("./飞机大战/images/me1.png") 16 | screen.blit(hero, (200, 500)) 17 | 18 | # 更新屏幕显示,可以在所有绘制工作完成之后,统一调用 update 方法 19 | pygame.display.update() 20 | 21 | # 创建时钟对象 22 | clock = pygame.time.Clock() 23 | 24 | # 1.定义 rect记录飞机的初始位置 25 | hero_rect = pygame.Rect(200, 500, 102, 126) 26 | 27 | # 创建敌机的精灵 28 | enemy = GameSprite("./飞机大战/images/enemy1.png") 29 | enemy1 = GameSprite("./飞机大战/images/enemy1.png", 2) 30 | # 创建敌机的精灵组 31 | enenmy_group = pygame.sprite.Group(enemy, enemy1) 32 | 33 | 34 | # 游戏循环 -> 意味着游戏的正式开始 35 | while True: 36 | # tick()的参数指定循环体内部的代码执行的频率 37 | clock.tick(60) 38 | 39 | # 监听事件 40 | for event in pygame.event.get(): 41 | # 判断事件类型是否是退出事件 42 | if event.type == pygame.QUIT: 43 | print("游戏退出...") 44 | 45 | # quit 卸载所有的模块 46 | pygame.quit() 47 | 48 | # exit() 直接终止当前正在执行的程序 49 | exit() 50 | 51 | # 2.修改飞机的位置 52 | hero_rect.y -= 1 53 | # 当飞机底部超出屏幕时,飞机从主屏幕进入 54 | if hero_rect.bottom <= 0: 55 | hero_rect.y = 700 56 | # 3.调用 blit 方法绘制图像 57 | screen.blit(bg, (0,0)) 58 | screen.blit(hero, hero_rect) 59 | 60 | # 让精灵组调用两个方法 61 | # update - 让组中的所有精灵更新位置 62 | enenmy_group.update() 63 | # draw - 在 screen 上绘制所有的精灵 64 | enenmy_group.draw(screen) 65 | 66 | # 4.调用 update 方法更新显示 67 | pygame.display.update() 68 | 69 | pygame.quit() -------------------------------------------------------------------------------- /飞机大战/images/again.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/again.png -------------------------------------------------------------------------------- /飞机大战/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/background.png -------------------------------------------------------------------------------- /飞机大战/images/bomb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/bomb.png -------------------------------------------------------------------------------- /飞机大战/images/bomb_supply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/bomb_supply.png -------------------------------------------------------------------------------- /飞机大战/images/bullet1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/bullet1.png -------------------------------------------------------------------------------- /飞机大战/images/bullet2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/bullet2.png -------------------------------------------------------------------------------- /飞机大战/images/bullet_supply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/bullet_supply.png -------------------------------------------------------------------------------- /飞机大战/images/enemy1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy1.png -------------------------------------------------------------------------------- /飞机大战/images/enemy1_down1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy1_down1.png -------------------------------------------------------------------------------- /飞机大战/images/enemy1_down2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy1_down2.png -------------------------------------------------------------------------------- /飞机大战/images/enemy1_down3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy1_down3.png -------------------------------------------------------------------------------- /飞机大战/images/enemy1_down4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy1_down4.png -------------------------------------------------------------------------------- /飞机大战/images/enemy2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy2.png -------------------------------------------------------------------------------- /飞机大战/images/enemy2_down1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy2_down1.png -------------------------------------------------------------------------------- /飞机大战/images/enemy2_down2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy2_down2.png -------------------------------------------------------------------------------- /飞机大战/images/enemy2_down3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy2_down3.png -------------------------------------------------------------------------------- /飞机大战/images/enemy2_down4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy2_down4.png -------------------------------------------------------------------------------- /飞机大战/images/enemy2_hit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy2_hit.png -------------------------------------------------------------------------------- /飞机大战/images/enemy3_down1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy3_down1.png -------------------------------------------------------------------------------- /飞机大战/images/enemy3_down2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy3_down2.png -------------------------------------------------------------------------------- /飞机大战/images/enemy3_down3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy3_down3.png -------------------------------------------------------------------------------- /飞机大战/images/enemy3_down4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy3_down4.png -------------------------------------------------------------------------------- /飞机大战/images/enemy3_down5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy3_down5.png -------------------------------------------------------------------------------- /飞机大战/images/enemy3_down6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy3_down6.png -------------------------------------------------------------------------------- /飞机大战/images/enemy3_hit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy3_hit.png -------------------------------------------------------------------------------- /飞机大战/images/enemy3_n1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy3_n1.png -------------------------------------------------------------------------------- /飞机大战/images/enemy3_n2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/enemy3_n2.png -------------------------------------------------------------------------------- /飞机大战/images/gameover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/gameover.png -------------------------------------------------------------------------------- /飞机大战/images/life.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/life.png -------------------------------------------------------------------------------- /飞机大战/images/me1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/me1.png -------------------------------------------------------------------------------- /飞机大战/images/me2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/me2.png -------------------------------------------------------------------------------- /飞机大战/images/me_destroy_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/me_destroy_1.png -------------------------------------------------------------------------------- /飞机大战/images/me_destroy_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/me_destroy_2.png -------------------------------------------------------------------------------- /飞机大战/images/me_destroy_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/me_destroy_3.png -------------------------------------------------------------------------------- /飞机大战/images/me_destroy_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/me_destroy_4.png -------------------------------------------------------------------------------- /飞机大战/images/pause_nor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/pause_nor.png -------------------------------------------------------------------------------- /飞机大战/images/pause_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/pause_pressed.png -------------------------------------------------------------------------------- /飞机大战/images/resume_nor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/resume_nor.png -------------------------------------------------------------------------------- /飞机大战/images/resume_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CharlieHon/Python/4537f6649e0287de155efd6caaf62b0f7c949407/飞机大战/images/resume_pressed.png -------------------------------------------------------------------------------- /飞机大战/plane_main.py: -------------------------------------------------------------------------------- 1 | # coding=utf8 2 | import pygame 3 | from plane_sprites import * 4 | 5 | 6 | class PlaneGame(object): 7 | """飞机大战主游戏类""" 8 | 9 | def __init__(self) -> None: 10 | print("游戏初始化") 11 | 12 | # 1.创建游戏的窗口 13 | self.screen = pygame.display.set_mode(SCREEN_RECT.size) 14 | # 2.创建游戏的时钟 15 | self.clock = pygame.time.Clock() 16 | # 3.调用私有方法,精灵和精灵组的创建 17 | self.__create_sprites() 18 | # 4.设计定时器事件 - 创建敌机 1s 19 | pygame.time.set_timer(CREATE_ENEMY_EVENT, 1000) 20 | pygame.time.set_timer(HERO_FIRE_EVENT, 500) 21 | 22 | def __create_sprites(self): 23 | 24 | # 创建背景精灵和精灵组 25 | bg1 = Background() 26 | bg2 = Background(True) 27 | 28 | self.back_group = pygame.sprite.Group(bg1, bg2) 29 | 30 | # 创建敌机的精灵组 31 | self.enemy_group = pygame.sprite.Group() 32 | 33 | # 创建英雄的精灵和精灵组 34 | self.hero = Hero() 35 | self.hero_group = pygame.sprite.Group(self.hero) 36 | 37 | def start_game(self): 38 | print("游戏开始...") 39 | 40 | while True: 41 | # 1.设置刷新帧率 42 | self.clock.tick(FRAME_PER_SEC) 43 | # 2.事件监听 44 | self.__event_handler() 45 | # 3.碰撞检测 46 | self.__check_collide() 47 | # 4.更新/绘制精灵组 48 | self.__update_sprites() 49 | # 5.更新显示 50 | pygame.display.update() 51 | 52 | def __event_handler(self): 53 | for event in pygame.event.get(): 54 | # 判断是否退出游戏 55 | if event.type == pygame.QUIT: 56 | PlaneGame.__game_over() 57 | elif event.type == CREATE_ENEMY_EVENT: 58 | # print("敌机出场...") 59 | # 创建敌机精灵 60 | enemy = Enemy() 61 | # 将敌机精灵添加到敌机精灵组 62 | self.enemy_group.add(enemy) 63 | # elif event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT: 64 | # print("向右移动") 65 | elif event.type == HERO_FIRE_EVENT: 66 | self.hero.fire() 67 | 68 | # 使用键盘提供的方法获取键盘按键 - 按键元组 69 | keys_pressed = pygame.key.get_pressed() 70 | # 判断元组中对应的按键索引值 1 71 | if keys_pressed[pygame.K_RIGHT]: 72 | self.hero.speed = 2 73 | elif keys_pressed[pygame.K_LEFT]: 74 | self.hero.speed = -2 75 | else: 76 | self.hero.speed = 0 77 | 78 | 79 | def __check_collide(self): 80 | # 1.子弹摧毁敌机 81 | pygame.sprite.groupcollide(self.hero.bullets, self.enemy_group, True, True) 82 | 83 | # 2.敌机撞毁英雄 84 | enemies = pygame.sprite.spritecollide(self.hero, self.enemy_group, True) 85 | 86 | # 3.判断列表是否有内容 87 | if len(enemies) > 0: 88 | # 让英雄牺牲 89 | self.hero.kill() 90 | # 结束游戏 91 | PlaneGame.__game_over() 92 | 93 | def __update_sprites(self): 94 | 95 | self.back_group.update() 96 | self.back_group.draw(self.screen) 97 | 98 | self.enemy_group.update() 99 | self.enemy_group.draw(self.screen) 100 | 101 | self.hero_group.update() 102 | self.hero_group.draw(self.screen) 103 | 104 | self.hero.bullets.update() 105 | self.hero.bullets.draw(self.screen) 106 | 107 | @staticmethod 108 | def __game_over(): 109 | print("游戏结束...") 110 | pygame.quit() 111 | exit() 112 | 113 | 114 | if __name__ == "__main__": 115 | 116 | # 创建游戏对象 117 | game = PlaneGame() 118 | 119 | # 启动游戏 120 | game.start_game() 121 | 122 | -------------------------------------------------------------------------------- /飞机大战/plane_sprites.py: -------------------------------------------------------------------------------- 1 | # *-* coding:utf8 *-* 2 | import random 3 | import pygame 4 | 5 | # 屏幕大小的常量 6 | SCREEN_RECT = pygame.Rect(0, 0, 480, 700) 7 | # 屏幕刷新率 8 | FRAME_PER_SEC = 60 9 | # 创建敌机的定时器常量 10 | CREATE_ENEMY_EVENT = pygame.USEREVENT 11 | # 英雄发射子弹事件 12 | HERO_FIRE_EVENT = pygame.USEREVENT + 1 13 | 14 | class GameSprite(pygame.sprite.Sprite): 15 | """飞机大战游戏精灵""" 16 | 17 | def __init__(self, image_name, speed=1) -> None: 18 | 19 | # 调用父类的初始化方法 20 | super().__init__() 21 | 22 | # 定义对象的属性 23 | self.image = pygame.image.load(image_name) 24 | self.rect = self.image.get_rect() 25 | self.speed = speed 26 | 27 | def update(self): 28 | 29 | # 在屏幕的垂直方向移动 30 | self.rect.y += self.speed 31 | 32 | class Background(GameSprite): 33 | """游戏背景精灵""" 34 | 35 | def __init__(self, is_alt=False) -> None: 36 | 37 | # 1.调用父类方法实现精灵创建(images/rect/speed) 38 | super().__init__("./飞机大战/images/background.png") 39 | # 2.判断是否是交替图像,如果是,需要设置初始设置 40 | if is_alt: 41 | self.rect.y = -self.rect.height 42 | 43 | def update(self): 44 | # 1.调用父类的方法实现 45 | super().update() 46 | # 2.判断是否移出屏幕,如果移出普,将图像设置到屏幕的正上方 47 | if self.rect.y >= SCREEN_RECT.height: 48 | self.rect.y = -self.rect.height 49 | 50 | 51 | class Enemy(GameSprite): 52 | """敌机精灵""" 53 | 54 | def __init__(self) -> None: 55 | 56 | # 1.调用父类方法,创建敌机精灵,同时指定敌机图片 57 | super().__init__("./飞机大战/images/enemy1.png") 58 | 59 | # 2指定敌机的初始随机速度 60 | self.speed = random.randint(1, 3) 61 | # 3.指定敌机的初始随机位置 62 | self.rect.bottom = 0 63 | # 水平随机位置 64 | max_x = SCREEN_RECT.width - self.rect.width 65 | self.rect.x = random.randint(0, max_x) 66 | 67 | def update(self): 68 | 69 | # 1.调用父类方法,保持垂直方向的飞行 70 | super().update() 71 | # 2.判断是否飞出屏幕,如果是,需要从精灵组删除敌机 72 | if self.rect.y >= SCREEN_RECT.height: 73 | # print("飞出屏幕,从精灵组删除...") 74 | # kill方法可以将精灵从所有精灵组中移出,精灵就会被自动销毁 75 | self.kill() 76 | 77 | def __del__(self): 78 | # print("敌机挂了 %s" % self.rect) 79 | pass 80 | 81 | 82 | class Hero(GameSprite): 83 | """英雄精灵""" 84 | 85 | def __init__(self) -> None: 86 | 87 | # 1.调用父类方法,设置 image, speed 88 | super().__init__("./飞机大战/images/me1.png", 0) 89 | # 2.设置英雄的初始位置 90 | self.rect.centerx = SCREEN_RECT.centerx 91 | self.rect.bottom = SCREEN_RECT.bottom - 120 92 | 93 | # 3.创建子弹的精灵组 94 | self.bullets = pygame.sprite.Group() 95 | 96 | 97 | def update(self): 98 | 99 | # 英雄在水平方向移动 100 | self.rect.x += self.speed 101 | 102 | # 判断英雄是否在水平位置上超出屏幕 103 | if self.rect.x < 0: 104 | self.rect.x = 0 105 | elif self.rect.right >= SCREEN_RECT.right: 106 | self.rect.right = SCREEN_RECT.right 107 | 108 | def fire(self): 109 | # print("发射子弹...") 110 | 111 | for i in (0, 1, 2): 112 | # 1.创建子弹精灵 113 | bullet = Bullet() 114 | 115 | # 2.设置精灵的位置 116 | bullet.rect.bottom = self.rect.y - i * 20 117 | bullet.rect.centerx = self.rect.centerx 118 | 119 | # 3.将精灵添加到精灵组 120 | self.bullets.add(bullet) 121 | 122 | class Bullet(GameSprite): 123 | """定义子弹类""" 124 | 125 | def __init__(self): 126 | 127 | # 调用父类方法,设置子弹图片,设置初始速度 128 | super().__init__("./飞机大战/images/bullet1.png", -2) 129 | 130 | def update(self): 131 | 132 | # 调用父类方法,让子弹沿垂直方向飞行 133 | super().update() 134 | 135 | # 判断子弹是否飞出屏幕 136 | if self.rect.bottom < 0: 137 | self.kill() --------------------------------------------------------------------------------