init commit
17
.bookignore
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# 辅助处理的python脚本文件
|
||||||
|
delete_extra_md.py
|
||||||
|
color_print.py
|
||||||
|
auto_catalog.py
|
||||||
|
|
||||||
|
# jetbrain目录,python编译文件
|
||||||
|
.idea/
|
||||||
|
__pycache__/
|
||||||
|
|
||||||
|
# 自己
|
||||||
|
.bookignore
|
||||||
|
|
||||||
|
# 一键生成书籍的脚本
|
||||||
|
build_book.bat
|
||||||
|
|
||||||
|
# gitignore
|
||||||
|
.gitignore
|
||||||
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# jetbrain目录,python编译文件
|
||||||
|
.idea/
|
||||||
|
__pycache__/
|
||||||
|
.vscode/
|
||||||
85
CATALOG_FOR_GITBOOK.md
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
# Summary
|
||||||
|
|
||||||
|
* [Python3小白课 介绍](./README.md)
|
||||||
|
* [课程目录](./Catalog.md)
|
||||||
|
|
||||||
|
* [一、Python初识](./chapter1/README.md)
|
||||||
|
* [1-1 python3小白课:python语言简介](./chapter1/1-1 python3小白课:python语言简介.md)
|
||||||
|
* [1-2 python3小白课:python下载](./chapter1/1-2 python3小白课:python下载.md)
|
||||||
|
* [1-3 python3小白课:python安装](./chapter1/1-3 python3小白课:python安装.md)
|
||||||
|
* [1-4 python3小白课:我的第一个python脚本](./chapter1/1-4 python3小白课:我的第一个python脚本.md)
|
||||||
|
* [1-5 python3小白课:如何运行py文件](./chapter1/1-5 python3小白课:如何运行py文件.md)
|
||||||
|
* [1-6 python3小白课:使用python IDLE](./chapter1/1-6 python3小白课:使用python IDLE.md)
|
||||||
|
* [1-7 python3小白课:使用python shell](./chapter1/1-7 python3小白课:使用python shell.md)
|
||||||
|
* [二、变量、简单类型和运算符](./chapter2/README.md)
|
||||||
|
* [2-1 python3小白课:啥是变量](./chapter2/2-1 python3小白课:啥是变量.md)
|
||||||
|
* [2-2 python3小白课:定义常量](./chapter2/2-2 python3小白课:定义常量.md)
|
||||||
|
* [2-3 python3小白课:注释让你事半功倍](./chapter2/2-3 python3小白课:注释让你事半功倍.md)
|
||||||
|
* [2-4 python3小白课:数值类型之整型](./chapter2/2-4 python3小白课:数值类型之整型.md)
|
||||||
|
* [2-5 python3小白课:数值类型之浮点型](./chapter2/2-5 python3小白课:数值类型之浮点型.md)
|
||||||
|
* [2-6 python3小白课:数值类型之复数](./chapter2/2-6 python3小白课:数值类型之复数.md)
|
||||||
|
* [2-7 python3小白课:字符串入门](./chapter2/2-7 python3小白课:字符串入门.md)
|
||||||
|
* [2-8 python3小白课:字节串](./chapter2/2-8 python3小白课:字节串.md)
|
||||||
|
* [2-9 python3小白课:字符串进阶](./chapter2/2-9 python3小白课:字符串进阶.md)
|
||||||
|
* [2-10 python3小白课:赋值运算符](./chapter2/2-10 python3小白课:赋值运算符.md)
|
||||||
|
* [2-11 python3小白课:算术运算符](./chapter2/2-11 python3小白课:算术运算符.md)
|
||||||
|
* [2-12 python3小白课:索引运算符](./chapter2/2-12 python3小白课:索引运算符.md)
|
||||||
|
* [2-13 python3小白课:比较运算符](./chapter2/2-13 python3小白课:比较运算符.md)
|
||||||
|
* [2-14 python3小白课:身份运算符](./chapter2/2-14 python3小白课:身份运算符.md)
|
||||||
|
* [2-15 python3小白课:逻辑运算符](./chapter2/2-15 python3小白课:逻辑运算符.md)
|
||||||
|
* [2-16 python3小白课:位运算符](./chapter2/2-16 python3小白课:位运算符.md)
|
||||||
|
* [2-17 python3小白课:赋值运算符扩展](./chapter2/2-17 python3小白课:赋值运算符扩展.md)
|
||||||
|
* [2-18 python3小白课:三目运算符](./chapter2/2-18 python3小白课:三目运算符.md)
|
||||||
|
* [2-19 python3小白课:成员运算符](./chapter2/2-19 python3小白课:成员运算符.md)
|
||||||
|
* [2-20 python3小白课:运算符优先级](./chapter2/2-20 python3小白课:运算符优先级.md)
|
||||||
|
* [三、列表、元组和字典](./chapter3/README.md)
|
||||||
|
* [3-1 python3小白课:列表和元组的区别](./chapter3/3-1 python3小白课:列表和元组的区别.md)
|
||||||
|
* [3-2 python3小白课:列表元组入门](./chapter3/3-2 python3小白课:列表元组入门.md)
|
||||||
|
* [3-3 python3小白课:深入列表](./chapter3/3-3 python3小白课:深入列表.md)
|
||||||
|
* [3-4 python3小白课:字典初识](./chapter3/3-4 python3小白课:字典初识.md)
|
||||||
|
* [3-5 python3小白课:字典操作基础](./chapter3/3-5 python3小白课:字典操作基础.md)
|
||||||
|
* [3-6 python3小白课:字典的常用方法](./chapter3/3-6 python3小白课:字典的常用方法.md)
|
||||||
|
* [四、流程控制](./chapter4/README.md)
|
||||||
|
* [4-1 python3小白课:if分支结构](./chapter4/4-1 python3小白课:if分支结构.md)
|
||||||
|
* [4-2 python3小白课:while循环结构](./chapter4/4-2 python3小白课:while循环结构.md)
|
||||||
|
* [4-3 python3小白课:for-in循环结构](./chapter4/4-3 python3小白课:for-in循环结构.md)
|
||||||
|
* [4-4 python3小白课:for表达式](./chapter4/4-4 python3小白课:for表达式.md)
|
||||||
|
* [五、自定义函数](./chapter5/README.md)
|
||||||
|
* [5-1 python3小白课:函数是什么](./chapter5/5-1 python3小白课:函数是什么.md)
|
||||||
|
* [5-2 python3小白课:函数入门](./chapter5/5-2 python3小白课:函数入门.md)
|
||||||
|
* [5-3 python3小白课:递归函数](./chapter5/5-3 python3小白课:递归函数.md)
|
||||||
|
* [5-4 python3小白课:关键字参数](./chapter5/5-4 python3小白课:关键字参数.md)
|
||||||
|
* [5-5 python3小白课:参数默认值](./chapter5/5-5 python3小白课:参数默认值.md)
|
||||||
|
* [5-6 python3小白课:参数收集](./chapter5/5-6 python3小白课:参数收集.md)
|
||||||
|
* [5-7 python3小白课:变量作用域](./chapter5/5-7 python3小白课:变量作用域.md)
|
||||||
|
* [5-8 python3小白课:局部函数](./chapter5/5-8 python3小白课:局部函数.md)
|
||||||
|
* [六、模块和包](./chapter6/README.md)
|
||||||
|
* [6-1 python3小白课:模块的导入](./chapter6/6-1 python3小白课:模块的导入.md)
|
||||||
|
* [6-2 python3小白课:自己写模块](./chapter6/6-2 python3小白课:自己写模块.md)
|
||||||
|
* [6-3 python3小白课:导入模块详解](./chapter6/6-3 python3小白课:导入模块详解.md)
|
||||||
|
* [6-4 python3小白课:包是什么](./chapter6/6-4 python3小白课:包是什么.md)
|
||||||
|
* [6-5 python3小白课:定义包](./chapter6/6-5 python3小白课:定义包.md)
|
||||||
|
* [6-6 python3小白课:包成员导入](./chapter6/6-6 python3小白课:包成员导入.md)
|
||||||
|
* [6-7 python3小白课:模块内容查看](./chapter6/6-7 python3小白课:模块内容查看.md)
|
||||||
|
* [6-8 python3小白课:解锁你心仪的三方包](./chapter6/6-8 python3小白课:解锁你心仪的三方包.md)
|
||||||
|
* [6-9 python3小白课:虚拟环境介绍和安装](./chapter6/6-9 python3小白课:虚拟环境介绍和安装.md)
|
||||||
|
* [6-10 python3小白课:虚拟环境使用](./chapter6/6-10 python3小白课:虚拟环境使用.md)
|
||||||
|
* [七、类和对象](./chapter7/README.md)
|
||||||
|
* [7-1 python3小白课:一节课搞懂面向对象](./chapter7/7-1 python3小白课:一节课搞懂面向对象.md)
|
||||||
|
* [7-2 python3小白课:定义类和实例化对象](./chapter7/7-2 python3小白课:定义类和实例化对象.md)
|
||||||
|
* [7-3 python3小白课:了解实例方法](./chapter7/7-3 python3小白课:了解实例方法.md)
|
||||||
|
* [7-4 python3小白课:用property函数定义属性](./chapter7/7-4 python3小白课:用property函数定义属性.md)
|
||||||
|
* [7-5 python3小白课:封装和隐藏](./chapter7/7-5 python3小白课:封装和隐藏.md)
|
||||||
|
* [7-6 python3小白课:类的继承和多继承](./chapter7/7-6 python3小白课:类的继承和多继承.md)
|
||||||
|
* [7-7 python3小白课:重写父类方法和使用super函数](./chapter7/7-7 python3小白课:重写父类方法和使用super函数.md)
|
||||||
|
* [7-8 python3小白课:类的多态性](./chapter7/7-8 python3小白课:类的多态性.md)
|
||||||
|
* [7-9 python3小白课:可以被枚举的类](./chapter7/7-9 python3小白课:可以被枚举的类.md)
|
||||||
|
* [八、异常处理机制](./chapter8/README.md)
|
||||||
|
* [8-1 python3小白课:最基本的异常处理](./chapter8/8-1 python3小白课:最基本的异常处理.md)
|
||||||
|
* [8-2 python3小白课:多异常捕获](./chapter8/8-2 python3小白课:多异常捕获.md)
|
||||||
|
* [8-3 python3小白课:查看详细异常信息](./chapter8/8-3 python3小白课:查看详细异常信息.md)
|
||||||
|
* [8-4 python3小白课:异常机制中的else块](./chapter8/8-4 python3小白课:异常机制中的else块.md)
|
||||||
|
* [8-5 python3小白课:finally块回收资源](./chapter8/8-5 python3小白课:finally块回收资源.md)
|
||||||
|
* [8-6 python3小白课:自己引发异常](./chapter8/8-6 python3小白课:自己引发异常.md)
|
||||||
|
|
||||||
|
* [课程总结](./Summary.md)
|
||||||
80
Catalog.md
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# 课程目录
|
||||||
|
|
||||||
|
* ### [一、Python初识](./chapter1)
|
||||||
|
* [1-1 python3小白课:python语言简介](./chapter1/1-1 python3小白课:python语言简介.html)
|
||||||
|
* [1-2 python3小白课:python下载](./chapter1/1-2 python3小白课:python下载.html)
|
||||||
|
* [1-3 python3小白课:python安装](./chapter1/1-3 python3小白课:python安装.html)
|
||||||
|
* [1-4 python3小白课:我的第一个python脚本](./chapter1/1-4 python3小白课:我的第一个python脚本.html)
|
||||||
|
* [1-5 python3小白课:如何运行py文件](./chapter1/1-5 python3小白课:如何运行py文件.html)
|
||||||
|
* [1-6 python3小白课:使用python IDLE](./chapter1/1-6 python3小白课:使用python IDLE.html)
|
||||||
|
* [1-7 python3小白课:使用python shell](./chapter1/1-7 python3小白课:使用python shell.html)
|
||||||
|
* ### [二、变量、简单类型和运算符](./chapter2)
|
||||||
|
* [2-1 python3小白课:啥是变量](./chapter2/2-1 python3小白课:啥是变量.html)
|
||||||
|
* [2-2 python3小白课:定义常量](./chapter2/2-2 python3小白课:定义常量.html)
|
||||||
|
* [2-3 python3小白课:注释让你事半功倍](./chapter2/2-3 python3小白课:注释让你事半功倍.html)
|
||||||
|
* [2-4 python3小白课:数值类型之整型](./chapter2/2-4 python3小白课:数值类型之整型.html)
|
||||||
|
* [2-5 python3小白课:数值类型之浮点型](./chapter2/2-5 python3小白课:数值类型之浮点型.html)
|
||||||
|
* [2-6 python3小白课:数值类型之复数](./chapter2/2-6 python3小白课:数值类型之复数.html)
|
||||||
|
* [2-7 python3小白课:字符串入门](./chapter2/2-7 python3小白课:字符串入门.html)
|
||||||
|
* [2-8 python3小白课:字节串](./chapter2/2-8 python3小白课:字节串.html)
|
||||||
|
* [2-9 python3小白课:字符串进阶](./chapter2/2-9 python3小白课:字符串进阶.html)
|
||||||
|
* [2-10 python3小白课:赋值运算符](./chapter2/2-10 python3小白课:赋值运算符.html)
|
||||||
|
* [2-11 python3小白课:算术运算符](./chapter2/2-11 python3小白课:算术运算符.html)
|
||||||
|
* [2-12 python3小白课:索引运算符](./chapter2/2-12 python3小白课:索引运算符.html)
|
||||||
|
* [2-13 python3小白课:比较运算符](./chapter2/2-13 python3小白课:比较运算符.html)
|
||||||
|
* [2-14 python3小白课:身份运算符](./chapter2/2-14 python3小白课:身份运算符.html)
|
||||||
|
* [2-15 python3小白课:逻辑运算符](./chapter2/2-15 python3小白课:逻辑运算符.html)
|
||||||
|
* [2-16 python3小白课:位运算符](./chapter2/2-16 python3小白课:位运算符.html)
|
||||||
|
* [2-17 python3小白课:赋值运算符扩展](./chapter2/2-17 python3小白课:赋值运算符扩展.html)
|
||||||
|
* [2-18 python3小白课:三目运算符](./chapter2/2-18 python3小白课:三目运算符.html)
|
||||||
|
* [2-19 python3小白课:成员运算符](./chapter2/2-19 python3小白课:成员运算符.html)
|
||||||
|
* [2-20 python3小白课:运算符优先级](./chapter2/2-20 python3小白课:运算符优先级.html)
|
||||||
|
* ### [三、列表、元组和字典](./chapter3)
|
||||||
|
* [3-1 python3小白课:列表和元组的区别](./chapter3/3-1 python3小白课:列表和元组的区别.html)
|
||||||
|
* [3-2 python3小白课:列表元组入门](./chapter3/3-2 python3小白课:列表元组入门.html)
|
||||||
|
* [3-3 python3小白课:深入列表](./chapter3/3-3 python3小白课:深入列表.html)
|
||||||
|
* [3-4 python3小白课:字典初识](./chapter3/3-4 python3小白课:字典初识.html)
|
||||||
|
* [3-5 python3小白课:字典操作基础](./chapter3/3-5 python3小白课:字典操作基础.html)
|
||||||
|
* [3-6 python3小白课:字典的常用方法](./chapter3/3-6 python3小白课:字典的常用方法.html)
|
||||||
|
* ### [四、流程控制](./chapter4)
|
||||||
|
* [4-1 python3小白课:if分支结构](./chapter4/4-1 python3小白课:if分支结构.html)
|
||||||
|
* [4-2 python3小白课:while循环结构](./chapter4/4-2 python3小白课:while循环结构.html)
|
||||||
|
* [4-3 python3小白课:for-in循环结构](./chapter4/4-3 python3小白课:for-in循环结构.html)
|
||||||
|
* [4-4 python3小白课:for表达式](./chapter4/4-4 python3小白课:for表达式.html)
|
||||||
|
* ### [五、自定义函数](./chapter5)
|
||||||
|
* [5-1 python3小白课:函数是什么](./chapter5/5-1 python3小白课:函数是什么.html)
|
||||||
|
* [5-2 python3小白课:函数入门](./chapter5/5-2 python3小白课:函数入门.html)
|
||||||
|
* [5-3 python3小白课:递归函数](./chapter5/5-3 python3小白课:递归函数.html)
|
||||||
|
* [5-4 python3小白课:关键字参数](./chapter5/5-4 python3小白课:关键字参数.html)
|
||||||
|
* [5-5 python3小白课:参数默认值](./chapter5/5-5 python3小白课:参数默认值.html)
|
||||||
|
* [5-6 python3小白课:参数收集](./chapter5/5-6 python3小白课:参数收集.html)
|
||||||
|
* [5-7 python3小白课:变量作用域](./chapter5/5-7 python3小白课:变量作用域.html)
|
||||||
|
* [5-8 python3小白课:局部函数](./chapter5/5-8 python3小白课:局部函数.html)
|
||||||
|
* ### [六、模块和包](./chapter6)
|
||||||
|
* [6-1 python3小白课:模块的导入](./chapter6/6-1 python3小白课:模块的导入.html)
|
||||||
|
* [6-2 python3小白课:自己写模块](./chapter6/6-2 python3小白课:自己写模块.html)
|
||||||
|
* [6-3 python3小白课:导入模块详解](./chapter6/6-3 python3小白课:导入模块详解.html)
|
||||||
|
* [6-4 python3小白课:包是什么](./chapter6/6-4 python3小白课:包是什么.html)
|
||||||
|
* [6-5 python3小白课:定义包](./chapter6/6-5 python3小白课:定义包.html)
|
||||||
|
* [6-6 python3小白课:包成员导入](./chapter6/6-6 python3小白课:包成员导入.html)
|
||||||
|
* [6-7 python3小白课:模块内容查看](./chapter6/6-7 python3小白课:模块内容查看.html)
|
||||||
|
* [6-8 python3小白课:解锁你心仪的三方包](./chapter6/6-8 python3小白课:解锁你心仪的三方包.html)
|
||||||
|
* [6-9 python3小白课:虚拟环境介绍和安装](./chapter6/6-9 python3小白课:虚拟环境介绍和安装.html)
|
||||||
|
* [6-10 python3小白课:虚拟环境使用](./chapter6/6-10 python3小白课:虚拟环境使用.html)
|
||||||
|
* ### [七、类和对象](./chapter7)
|
||||||
|
* [7-1 python3小白课:一节课搞懂面向对象](./chapter7/7-1 python3小白课:一节课搞懂面向对象.html)
|
||||||
|
* [7-2 python3小白课:定义类和实例化对象](./chapter7/7-2 python3小白课:定义类和实例化对象.html)
|
||||||
|
* [7-3 python3小白课:了解实例方法](./chapter7/7-3 python3小白课:了解实例方法.html)
|
||||||
|
* [7-4 python3小白课:用property函数定义属性](./chapter7/7-4 python3小白课:用property函数定义属性.html)
|
||||||
|
* [7-5 python3小白课:封装和隐藏](./chapter7/7-5 python3小白课:封装和隐藏.html)
|
||||||
|
* [7-6 python3小白课:类的继承和多继承](./chapter7/7-6 python3小白课:类的继承和多继承.html)
|
||||||
|
* [7-7 python3小白课:重写父类方法和使用super函数](./chapter7/7-7 python3小白课:重写父类方法和使用super函数.html)
|
||||||
|
* [7-8 python3小白课:类的多态性](./chapter7/7-8 python3小白课:类的多态性.html)
|
||||||
|
* [7-9 python3小白课:可以被枚举的类](./chapter7/7-9 python3小白课:可以被枚举的类.html)
|
||||||
|
* ### [八、异常处理机制](./chapter8)
|
||||||
|
* [8-1 python3小白课:最基本的异常处理](./chapter8/8-1 python3小白课:最基本的异常处理.html)
|
||||||
|
* [8-2 python3小白课:多异常捕获](./chapter8/8-2 python3小白课:多异常捕获.html)
|
||||||
|
* [8-3 python3小白课:查看详细异常信息](./chapter8/8-3 python3小白课:查看详细异常信息.html)
|
||||||
|
* [8-4 python3小白课:异常机制中的else块](./chapter8/8-4 python3小白课:异常机制中的else块.html)
|
||||||
|
* [8-5 python3小白课:finally块回收资源](./chapter8/8-5 python3小白课:finally块回收资源.html)
|
||||||
|
* [8-6 python3小白课:自己引发异常](./chapter8/8-6 python3小白课:自己引发异常.html)
|
||||||
504
LICENSE
Normal file
@ -0,0 +1,504 @@
|
|||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
[This is the first released version of the Lesser GPL. It also counts
|
||||||
|
as the successor of the GNU Library Public License, version 2, hence
|
||||||
|
the version number 2.1.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Lesser General Public License, applies to some
|
||||||
|
specially designated software packages--typically libraries--of the
|
||||||
|
Free Software Foundation and other authors who decide to use it. You
|
||||||
|
can use it too, but we suggest you first think carefully about whether
|
||||||
|
this license or the ordinary General Public License is the better
|
||||||
|
strategy to use in any particular case, based on the explanations below.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom of use,
|
||||||
|
not price. Our General Public Licenses are designed to make sure that
|
||||||
|
you have the freedom to distribute copies of free software (and charge
|
||||||
|
for this service if you wish); that you receive source code or can get
|
||||||
|
it if you want it; that you can change the software and use pieces of
|
||||||
|
it in new free programs; and that you are informed that you can do
|
||||||
|
these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
distributors to deny you these rights or to ask you to surrender these
|
||||||
|
rights. These restrictions translate to certain responsibilities for
|
||||||
|
you if you distribute copies of the library or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link other code with the library, you must provide
|
||||||
|
complete object files to the recipients, so that they can relink them
|
||||||
|
with the library after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with a two-step method: (1) we copyright the
|
||||||
|
library, and (2) we offer you this license, which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
To protect each distributor, we want to make it very clear that
|
||||||
|
there is no warranty for the free library. Also, if the library is
|
||||||
|
modified by someone else and passed on, the recipients should know
|
||||||
|
that what they have is not the original version, so that the original
|
||||||
|
author's reputation will not be affected by problems that might be
|
||||||
|
introduced by others.
|
||||||
|
|
||||||
|
Finally, software patents pose a constant threat to the existence of
|
||||||
|
any free program. We wish to make sure that a company cannot
|
||||||
|
effectively restrict the users of a free program by obtaining a
|
||||||
|
restrictive license from a patent holder. Therefore, we insist that
|
||||||
|
any patent license obtained for a version of the library must be
|
||||||
|
consistent with the full freedom of use specified in this license.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the
|
||||||
|
ordinary GNU General Public License. This license, the GNU Lesser
|
||||||
|
General Public License, applies to certain designated libraries, and
|
||||||
|
is quite different from the ordinary General Public License. We use
|
||||||
|
this license for certain libraries in order to permit linking those
|
||||||
|
libraries into non-free programs.
|
||||||
|
|
||||||
|
When a program is linked with a library, whether statically or using
|
||||||
|
a shared library, the combination of the two is legally speaking a
|
||||||
|
combined work, a derivative of the original library. The ordinary
|
||||||
|
General Public License therefore permits such linking only if the
|
||||||
|
entire combination fits its criteria of freedom. The Lesser General
|
||||||
|
Public License permits more lax criteria for linking other code with
|
||||||
|
the library.
|
||||||
|
|
||||||
|
We call this license the "Lesser" General Public License because it
|
||||||
|
does Less to protect the user's freedom than the ordinary General
|
||||||
|
Public License. It also provides other free software developers Less
|
||||||
|
of an advantage over competing non-free programs. These disadvantages
|
||||||
|
are the reason we use the ordinary General Public License for many
|
||||||
|
libraries. However, the Lesser license provides advantages in certain
|
||||||
|
special circumstances.
|
||||||
|
|
||||||
|
For example, on rare occasions, there may be a special need to
|
||||||
|
encourage the widest possible use of a certain library, so that it becomes
|
||||||
|
a de-facto standard. To achieve this, non-free programs must be
|
||||||
|
allowed to use the library. A more frequent case is that a free
|
||||||
|
library does the same job as widely used non-free libraries. In this
|
||||||
|
case, there is little to gain by limiting the free library to free
|
||||||
|
software only, so we use the Lesser General Public License.
|
||||||
|
|
||||||
|
In other cases, permission to use a particular library in non-free
|
||||||
|
programs enables a greater number of people to use a large body of
|
||||||
|
free software. For example, permission to use the GNU C Library in
|
||||||
|
non-free programs enables many more people to use the whole GNU
|
||||||
|
operating system, as well as its variant, the GNU/Linux operating
|
||||||
|
system.
|
||||||
|
|
||||||
|
Although the Lesser General Public License is Less protective of the
|
||||||
|
users' freedom, it does ensure that the user of a program that is
|
||||||
|
linked with the Library has the freedom and the wherewithal to run
|
||||||
|
that program using a modified version of the Library.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, whereas the latter must
|
||||||
|
be combined with the library in order to run.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library or other
|
||||||
|
program which contains a notice placed by the copyright holder or
|
||||||
|
other authorized party saying it may be distributed under the terms of
|
||||||
|
this Lesser General Public License (also called "this License").
|
||||||
|
Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, complete source code means
|
||||||
|
all the source code for all modules it contains, plus any associated
|
||||||
|
interface definition files, plus the scripts used to control compilation
|
||||||
|
and installation of the library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete source code as you receive it, in any medium, provided that
|
||||||
|
you conspicuously and appropriately publish on each copy an
|
||||||
|
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||||
|
all the notices that refer to this License and to the absence of any
|
||||||
|
warranty; and distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy,
|
||||||
|
and you may at your option offer warranty protection in exchange for a
|
||||||
|
fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Library, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you accompany
|
||||||
|
it with the complete corresponding machine-readable source code, which
|
||||||
|
must be distributed under the terms of Sections 1 and 2 above on a
|
||||||
|
medium customarily used for software interchange.
|
||||||
|
|
||||||
|
If distribution of object code is made by offering access to copy
|
||||||
|
from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also combine or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (1) uses at run time a
|
||||||
|
copy of the library already present on the user's computer system,
|
||||||
|
rather than copying library functions into the executable, and (2)
|
||||||
|
will operate properly with a modified version of the library, if
|
||||||
|
the user installs one, as long as the modified version is
|
||||||
|
interface-compatible with the version that the work was made with.
|
||||||
|
|
||||||
|
c) Accompany the work with a written offer, valid for at
|
||||||
|
least three years, to give the same user the materials
|
||||||
|
specified in Subsection 6a, above, for a charge no more
|
||||||
|
than the cost of performing this distribution.
|
||||||
|
|
||||||
|
d) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
e) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the materials to be distributed need not include anything that is
|
||||||
|
normally distributed (in either source or binary form) with the major
|
||||||
|
components (compiler, kernel, and so on) of the operating system on
|
||||||
|
which the executable runs, unless that component itself accompanies
|
||||||
|
the executable.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library is void, and will automatically terminate your
|
||||||
|
rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses
|
||||||
|
terminated so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
9. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
subject to these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties with
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Library.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under any
|
||||||
|
particular circumstance, the balance of the section is intended to apply,
|
||||||
|
and the section as a whole is intended to apply in other circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library under this License may add
|
||||||
|
an explicit geographical distribution limitation excluding those countries,
|
||||||
|
so that distribution is permitted only in or among countries not thus
|
||||||
|
excluded. In such case, this License incorporates the limitation as if
|
||||||
|
written in the body of this License.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Lesser General Public License from time to time.
|
||||||
|
Such new versions will be similar in spirit to the present version,
|
||||||
|
but may differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Library
|
||||||
|
specifies a version number of this License which applies to it and
|
||||||
|
"any later version", you have the option of following the terms and
|
||||||
|
conditions either of that version or of any later version published by
|
||||||
|
the Free Software Foundation. If the Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
write to the author to ask for permission. For software which is
|
||||||
|
copyrighted by the Free Software Foundation, write to the Free
|
||||||
|
Software Foundation; we sometimes make exceptions for this. Our
|
||||||
|
decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing
|
||||||
|
and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||||
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||||
|
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||||
|
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||||
|
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||||
|
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||||
|
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||||
|
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||||
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Libraries
|
||||||
|
|
||||||
|
If you develop a new library, and you want it to be of the greatest
|
||||||
|
possible use to the public, we recommend making it free software that
|
||||||
|
everyone can redistribute and change. You can do so by permitting
|
||||||
|
redistribution under these terms (or, alternatively, under the terms of the
|
||||||
|
ordinary General Public License).
|
||||||
|
|
||||||
|
To apply these terms, attach the following notices to the library. It is
|
||||||
|
safest to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least the
|
||||||
|
"copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the library's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
USA
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||||
|
library `Frob' (a library for tweaking knobs) written by James Random
|
||||||
|
Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1990
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
That's all there is to it!
|
||||||
55
README.md
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# **python3小白课**笔记
|
||||||
|
|
||||||
|
**作者:雪山凌狐**
|
||||||
|
|
||||||
|
**网址:[雪山凌狐教程http://fox-9.com](http://fox-9.com)**
|
||||||
|
|
||||||
|
你是否也有这样的困扰?
|
||||||
|
|
||||||
|
* 知识浓缩度太高,跟不上老师的节奏?
|
||||||
|
* 知识讲解太枯燥,认真学习几课就放弃?
|
||||||
|
* 专业术语太多,要记忆的太多,抓不住重点,学了就忘?
|
||||||
|
|
||||||
|
学得最快的是这部分基础课,但是最容易遗忘的也恰恰是这些基础课。
|
||||||
|
|
||||||
|
快来学习这套**python3小白课**吧,采用跟以往都不同的全新教学模式,历时3-5个月倾力打造的python零基础课程,特别适合python或编程零基础的学员学习,包你学完之后能够真正入门python!
|
||||||
|
|
||||||
|
(说明:本套课程针对小白,对于python有一定基础,渴望掌握进阶知识的学员帮助可能不会特别大,如需要作为知识巩固的材料那也是可以的。如需要学习进阶知识,敬请关注今后会推出的进阶课程。)
|
||||||
|
|
||||||
|
## 学习目标
|
||||||
|
|
||||||
|
针对python零基础或编程零基础的学员,学习python3,学习编程,不再害怕并快速入门它们。
|
||||||
|
|
||||||
|
万丈高楼平地起,任何python后续的进阶学习都基于本套教程的基础,需要所有学员务必重视本套基础教程的简单学习,掌握一个基础概念,方便后续进阶拓展。
|
||||||
|
|
||||||
|
因为是系统学习,可能你在学了十来课之后常常会问到自己,我学这些个到底有什么用?能做出个什么东西来?这时候一方面心态不要着急,打好基础,之后写复杂的代码逻辑就能得心应手,想用什么就能下意识地用出来;另一方面,你可以考虑适量的进行项目驱动学习,写一点最简单的小脚本实现一个小功能,这时候会发现,提高比较快,而且基础打好会深刻的感觉到它的重要。
|
||||||
|
|
||||||
|
如果你觉得难,或者语言难,英语感到不会,怕,并没有关系,当初我在学习时,像这样的基础课程,都在跨越几年的时间里,反复学习了三四遍,因此,如果你一遍学不会,请再看一遍,直到你看懂为止即可。
|
||||||
|
|
||||||
|
## 课程特色
|
||||||
|
|
||||||
|
👍 针对小白同学必知必会的一些python基础知识点进行扫盲,学习完成之后,将不再惧怕编程,惧怕深入学习python其他的代码。
|
||||||
|
|
||||||
|
👍 课程注意内容的精练、简洁,不冗长拖沓,以尽可能风趣幽默但又通俗易懂的方式完成我们的学习。
|
||||||
|
|
||||||
|
👍 尽可能的在每一课将该课涉及到的一些英语单词内容教会大家。
|
||||||
|
|
||||||
|
## 运行环境
|
||||||
|
|
||||||
|
* python3.8.2 x64(python是免费开源的)
|
||||||
|
|
||||||
|
下载:**雪山凌狐教程** 微信公众号 暗号:python3.8.2
|
||||||
|
|
||||||
|
* IDE或编辑器选择:vscode 或 sublime 或 pycharm
|
||||||
|
|
||||||
|
均可以免费使用,任选其一即可:(课程计划使用vscode)
|
||||||
|
|
||||||
|
**vscode**:[https://code.visualstudio.com/](https://code.visualstudio.com/) 微软出品,完全免费,插件丰富。下载后安装chinese扩展可以汉化,然后安装python扩展支持python。可以在程序内部调试python程序,或调起终端执行。中量级,约两百多M。
|
||||||
|
|
||||||
|
简单教学:[Microsoft VS Code安装和汉化指南](http://fox-9.com/735.html)
|
||||||
|
|
||||||
|
**sublime**:[http://www.sublimetext.com/](http://www.sublimetext.com/) 增强型笔记本软件,插件丰富,免费使用全部功能,但在你使用约20分钟,你保存的时候会弹出让你买正版的提示,关闭即可。正版应该是99美元左右。Ctrl + B可以在软件内部编译程序调试。轻量级,约三十多M。
|
||||||
|
|
||||||
|
简单教学:[Sublime刚安装怎么用?做好这几步,大刀阔斧用起来!](http://fox-9.com/620.html)
|
||||||
|
|
||||||
|
**pycharm**:[https://www.jetbrains.com/pycharm/download/](https://www.jetbrains.com/pycharm/download/) JetBrains大厂出品,专职用于python项目,下载免费的Community社区版学习足够。Professional专业版比较适合你写web站点的python程序使用,初级学习不需要。做大型项目更友好,重量级,约1G。
|
||||||
11
Summary.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# 课程总结
|
||||||
|
|
||||||
|
经过了十几节课的洗礼,恭喜大家走到这一步,如今,正式python入门啦!
|
||||||
|
|
||||||
|
这套python3小白课,我使用了最通俗易懂的语言和最简洁的例子,将大家python入门需要掌握的一些知识悉心传授给了大家,希望大家在日后的python学习中,都能以本套教程为基础,徜徉于编程的海洋,不断拓展自己的能力,因此而终身受益。
|
||||||
|
|
||||||
|
本套课程也支持大家在未来遗忘某块知识的时候反复回看,用于巩固基础,这都是很好的。
|
||||||
|
|
||||||
|
将所学学以致用,那才是最好的,我真心希望大家学习完成后能够自我进行代码练习,巩固所学到的知识,一段时间后,能够脱离教程而编写出自己的东西,那,才是真正的毕业,也是我所希望的。我不希望大家脱离教程之后就丢失了应有的编程思维,这是应该逐步培养的,我希望大家可以自觉做到不看教程这一课的内容能够自己复述出来或者代码演示能够写出来了,那,才是真正的毕业了。
|
||||||
|
|
||||||
|
祝愿大家学有所成,前程似锦,咱们后会有期!
|
||||||
BIN
assets/alipay-code.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
assets/favicon.ico
Normal file
|
After Width: | Height: | Size: 361 KiB |
BIN
assets/wechatpay-code.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
105
auto_catalog.py
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
# coding:utf-8
|
||||||
|
|
||||||
|
import os
|
||||||
|
from color_print import printDarkYellow
|
||||||
|
"""
|
||||||
|
作者:雪山凌狐
|
||||||
|
网址:http://fox-9.com
|
||||||
|
修订时间:2022-09-14
|
||||||
|
|
||||||
|
写书好伴侣,自动目录生成器
|
||||||
|
目录需满足条件:
|
||||||
|
1.各个章节使用`chapter+章节`数字的方式来写,且每个文件夹里面都有一个README.md文件,文件第一行是一级标题的章节名
|
||||||
|
2.各课时md文件存放到各自的章节目录里面,课时的文件名跟需要生成的课时名一致,且文件名开头为章节数字-数字序号(如第一章第一节为 1-1),序号结束后空格后再写其他内容
|
||||||
|
3.章节的目录中除了assets文件夹以外不要有其他文件夹了
|
||||||
|
|
||||||
|
运行后会自动生成目录树和目录两个文件供使用
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 生成gitbook目录树的文件
|
||||||
|
summarytree_filename = "CATALOG_FOR_GITBOOK.md"
|
||||||
|
# 一个课程目录文件
|
||||||
|
catalog_filename = "Catalog.md"
|
||||||
|
# 课程总结文件名
|
||||||
|
summary_filename = "Summary.md"
|
||||||
|
# 首页的README.md文件在生成的网站中的标题
|
||||||
|
readme_name = "Python3小白课 介绍"
|
||||||
|
|
||||||
|
|
||||||
|
def get_catalog(folder):
|
||||||
|
"""自动生成目录"""
|
||||||
|
# 获取有哪几个章节列表
|
||||||
|
dirs = os.listdir(folder)
|
||||||
|
chapter_dir = []
|
||||||
|
for path in dirs:
|
||||||
|
whole_path = os.path.join(folder, path)
|
||||||
|
if os.path.isdir(whole_path):
|
||||||
|
if path.startswith("chapter"):
|
||||||
|
chapter_dir.append(whole_path)
|
||||||
|
chapter_dir.sort()
|
||||||
|
|
||||||
|
# 初始化summarytree文件
|
||||||
|
if os.path.exists(summarytree_filename):
|
||||||
|
os.remove(summarytree_filename)
|
||||||
|
with open(summarytree_filename, "a", encoding="utf-8") as f:
|
||||||
|
f.write("# Summary\n\n")
|
||||||
|
f.write("* [%s](./README.md)\n" % readme_name)
|
||||||
|
f.write("* [课程目录](./Catalog.md)\n\n")
|
||||||
|
|
||||||
|
# 初始化catalog文件
|
||||||
|
if os.path.exists(catalog_filename):
|
||||||
|
os.remove(catalog_filename)
|
||||||
|
with open(catalog_filename, "a", encoding="utf-8") as f:
|
||||||
|
f.write("# 课程目录\n\n")
|
||||||
|
|
||||||
|
# 写具体章节内容
|
||||||
|
for chapter in chapter_dir:
|
||||||
|
readme_path = os.path.join(chapter, "README.md")
|
||||||
|
with open(readme_path, "r", encoding="utf-8") as f:
|
||||||
|
chapter_name = f.readline().strip().replace("# ", "")
|
||||||
|
filelist = os.listdir(chapter)
|
||||||
|
try:
|
||||||
|
filelist.remove("README.md")
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
filelist.remove("assets")
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
filelist.sort(key=return_index, reverse=False)
|
||||||
|
# print(filelist)
|
||||||
|
|
||||||
|
# 写summarytree文件内容
|
||||||
|
with open(summarytree_filename, "a", encoding="utf-8") as f:
|
||||||
|
f.write("* [{name}]({path})\n".format(name=chapter_name,
|
||||||
|
path=chapter + "/README.md"))
|
||||||
|
for cur_file in filelist:
|
||||||
|
f.write("\t* [{name}]({path})\n".format(
|
||||||
|
name=os.path.splitext(cur_file)[0],
|
||||||
|
path=chapter + "/" + cur_file))
|
||||||
|
|
||||||
|
# 写catalog文件内容
|
||||||
|
with open(catalog_filename, "a", encoding="utf-8") as f:
|
||||||
|
f.write("* ### [{name}]({path})\n".format(name=chapter_name,
|
||||||
|
path=chapter))
|
||||||
|
for cur_file in filelist:
|
||||||
|
cur_file_name = os.path.splitext(cur_file)[0]
|
||||||
|
f.write("\t* [{name}]({path})\n".format(
|
||||||
|
name=cur_file_name,
|
||||||
|
path=chapter + "/" + cur_file_name + ".html"))
|
||||||
|
|
||||||
|
# 写课程总结summary链接
|
||||||
|
with open(summarytree_filename, "a", encoding="utf-8") as f:
|
||||||
|
f.write("\n* [课程总结](./%s)\n" % summary_filename)
|
||||||
|
|
||||||
|
|
||||||
|
def return_index(filename):
|
||||||
|
"""返回文件名的序号"""
|
||||||
|
index1 = filename.find("-")
|
||||||
|
index2 = filename.find(" ")
|
||||||
|
return int(filename[index1 + 1:index2])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
get_catalog("./")
|
||||||
|
printDarkYellow("生成目录完成!\n\n")
|
||||||
158
book.json
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
{
|
||||||
|
"title": "python3小白课笔记",
|
||||||
|
"author": "雪山凌狐",
|
||||||
|
"description": "python3小白课,让你不再惧怕python的入门学习",
|
||||||
|
"language": "zh-hans",
|
||||||
|
"gitbook": "3.2.3",
|
||||||
|
"styles": {
|
||||||
|
"website": "/css/website.css"
|
||||||
|
},
|
||||||
|
"structure": {
|
||||||
|
"readme": "README.md",
|
||||||
|
"summary": "CATALOG_FOR_GITBOOK.md"
|
||||||
|
},
|
||||||
|
"links": {
|
||||||
|
"sidebar": {
|
||||||
|
"雪山凌狐教程": "http://fox-9.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"favicon",
|
||||||
|
"-search",
|
||||||
|
"-lunr",
|
||||||
|
"-sharing",
|
||||||
|
"-livereload",
|
||||||
|
"-highlight",
|
||||||
|
"prism",
|
||||||
|
"prism-themes",
|
||||||
|
"fontsettings",
|
||||||
|
"back-to-top-button",
|
||||||
|
"expandable-chapters-small",
|
||||||
|
"code",
|
||||||
|
"search-pro",
|
||||||
|
"splitter",
|
||||||
|
"donate",
|
||||||
|
"tbfed-pagefooter",
|
||||||
|
"pageview-count",
|
||||||
|
"auto-scroll-table",
|
||||||
|
"lightbox",
|
||||||
|
"anchor-navigation-ex",
|
||||||
|
"sitemap-general",
|
||||||
|
"ad",
|
||||||
|
"image-captions",
|
||||||
|
"autotheme",
|
||||||
|
"advanced-emoji",
|
||||||
|
"flexible-alerts",
|
||||||
|
"statistics",
|
||||||
|
"push-bd"
|
||||||
|
],
|
||||||
|
"pluginsConfig": {
|
||||||
|
"favicon": {
|
||||||
|
"shortcut": "/assets/favicon.ico",
|
||||||
|
"bookmark": "/assets/favicon.ico"
|
||||||
|
},
|
||||||
|
"donate": {
|
||||||
|
"wechat": "/python3xiaobaike/assets/wechatpay-code.jpg",
|
||||||
|
"alipay": "/python3xiaobaike/assets/alipay-code.jpg",
|
||||||
|
"title": "",
|
||||||
|
"button": "赏",
|
||||||
|
"alipayText": "支付宝打赏",
|
||||||
|
"wechatText": "微信打赏"
|
||||||
|
},
|
||||||
|
"tbfed-pagefooter": {
|
||||||
|
"copyright": "Copyright © <a href='http://fox-9.com'>雪山凌狐教程</a>",
|
||||||
|
"modify_label": "该文件修订时间:",
|
||||||
|
"modify_format": "YYYY-MM-DD HH:mm:ss"
|
||||||
|
},
|
||||||
|
"prism": {
|
||||||
|
"css": [
|
||||||
|
"prism-themes/themes/prism-material-light.css"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"anchor-navigation-ex": {
|
||||||
|
"showLevel": false,
|
||||||
|
"showGoTop": false,
|
||||||
|
"float": {
|
||||||
|
"showLevelIcon": true,
|
||||||
|
"level1Icon": "fa fa-hand-o-right",
|
||||||
|
"level2Icon": "fa fa-hand-o-right",
|
||||||
|
"level3Icon": "fa fa-hand-o-right"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sitemap-general": {
|
||||||
|
"prefix": "http://doc.fox-9.com/python3xiaobaike/"
|
||||||
|
},
|
||||||
|
"autotheme": {
|
||||||
|
"white": [
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25
|
||||||
|
],
|
||||||
|
"sepia": [
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25,
|
||||||
|
25
|
||||||
|
],
|
||||||
|
"night": [
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"image-captions": {
|
||||||
|
"caption": "_CAPTION_"
|
||||||
|
},
|
||||||
|
"flexible-alerts": {
|
||||||
|
"style": "flat",
|
||||||
|
"note": {
|
||||||
|
"label": "说明"
|
||||||
|
},
|
||||||
|
"tip": {
|
||||||
|
"label": "提示"
|
||||||
|
},
|
||||||
|
"warning": {
|
||||||
|
"label": "警告"
|
||||||
|
},
|
||||||
|
"danger": {
|
||||||
|
"label": "注意"
|
||||||
|
},
|
||||||
|
"question": {
|
||||||
|
"label": "问题",
|
||||||
|
"icon": "fa fa-question-circle",
|
||||||
|
"className": "question"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"statistics": {
|
||||||
|
"bd_token": "605d1993c133629d69ab2701f78d9690"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
build_book.bat
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
@echo off
|
||||||
|
rem 作者:雪山凌狐
|
||||||
|
rem 网址:http://fox-9.com
|
||||||
|
rem 修订时间:2022-09-14
|
||||||
|
rem 写书好伴侣,一键生成编译好的gitbook
|
||||||
|
|
||||||
|
rem 启动utf-8编码页,输出中文不乱码
|
||||||
|
chcp 65001
|
||||||
|
|
||||||
|
echo 删除旧的编译目录...
|
||||||
|
rd/s/q python3xiaobaike
|
||||||
|
echo ====================
|
||||||
|
|
||||||
|
echo 自动生成目录中...
|
||||||
|
python auto_catalog.py
|
||||||
|
echo ====================
|
||||||
|
|
||||||
|
echo 编译生成book中...
|
||||||
|
call gitbook build
|
||||||
|
echo ====================
|
||||||
|
|
||||||
|
echo 删除多余的markdown文件中...
|
||||||
|
python delete_extra_md.py
|
||||||
|
echo ====================
|
||||||
|
|
||||||
|
echo 修改book目录名中...
|
||||||
|
ren _book python3xiaobaike
|
||||||
|
echo ====================
|
||||||
|
|
||||||
|
echo 运行完成!感谢您的使用!
|
||||||
|
|
||||||
|
|
||||||
|
pause
|
||||||
73
chapter1/1-1 python3小白课:python语言简介.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# python3小白课:python语言简介
|
||||||
|
|
||||||
|
### python的起源
|
||||||
|
|
||||||
|
python起源于1989年,由龟叔`Guido van Rossum`发明,是一种解释型、跨平台的语言,使用它是`免费`的。相比其他语言而言,代码简洁简单,应用范围广,在当下十分流行,是一门十分容易入门的编程语言。不管你是什么工作岗位,如果需要学习一门大家比较认可的编程语言的话,python首当其冲受到推荐。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### python版本之谜
|
||||||
|
|
||||||
|
目前最新版本是python3以上的版本。目前使用python的用户分为使用python2.7的和使用python3的。为什么会这样呢?
|
||||||
|
|
||||||
|
因为在08年的12月,龟叔发布了python3.0的版本,决定不向下兼容python2(因为python首发版本的时间较早,比如早于unicode编码标准的发布时间),在这个抛开过去包袱的层面上对该语言做了一定的改进,对我来说,最大能感受到的变化有两点,一个是print打印输出内容到控制台的一个功能,新的写法跟旧的写法是不一样的,另一个就是编码问题,这对于许多写python代码又涉及中文的朋友感受可能更多一些。在python2中,默认的代码编码是ASCII编码,这样在输出一些中文字符串的时候常常遇到乱码的问题,需要各种解码、编码、转换编码等复杂操作才能不乱码,非常烦人。而python3代码的默认编码为`utf-8`编码,默认就支持了中文,所以在编码这块用python3会省心许多。
|
||||||
|
|
||||||
|
还有一些其他的差异,但差异并不算很多,如果你过去学习过python2,那么python3也是很容易上手的。
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> python2.7是python2.x系列的最后一个会维护的版本,但官方宣布在2020年停止维护,目前看来,可能是真的要跟我们说再见了。
|
||||||
|
>
|
||||||
|
> python2.7.18版本是目前python官方说的最后一个python2的版本,发布日期为2020年4月20日。
|
||||||
|
|
||||||
|
python2停止更新参考链接:[https://pythoninsider.blogspot.com/2020/04/python-2718-last-release-of-python-2.html](https://pythoninsider.blogspot.com/2020/04/python-2718-last-release-of-python-2.html)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 学习python2还是python3?
|
||||||
|
|
||||||
|
其实在发布python3的时候,已经有非常多优秀的代码、三方库等都是用python2写的了,这时候大家的选择很多,而且很多大型公司内部都在用python2来编写一些代码做一些运维工作之类的或者其他(包括现在依然也是)。
|
||||||
|
|
||||||
|
我个人也在这个问题上纠结过无数次,那么本套教程的想法是,鉴于目前看到python2已经停止了进一步更新维护,python3才是我们应该考虑的未来。本套教程只着重讲解python3的基础内容,不对python2进行教学,如果你担心你写的代码跟公司的python2项目等不兼容的话,没有关系,我们后面讲解`虚拟环境`的搭建和使用,在不影响现有所有python2项目的基础上,顺利跑起来你写的python3的代码,也不是难事。
|
||||||
|
|
||||||
|
因此,我们的课程的所有内容均基于`python3`以上的版本学习,最好是python3.6+的版本。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### python的用途
|
||||||
|
|
||||||
|
没有接触过python或者没有接触过编程的同学,一定会问出这个问题,python能做啥?能如何帮到我的工作和生活?
|
||||||
|
|
||||||
|
我们可以简单罗列一些:
|
||||||
|
|
||||||
|
- web开发:也就是写网站,很多知名网站用python来做为主要开发语言,咱们列举几个:豆瓣、知乎、果壳网、Google、NASA、YouTube、Facebook等等。
|
||||||
|
|
||||||
|
- 网络爬虫:简单来说就是数据采集,从公开的互联网的数据中抓取所需要的信息下来,可以做后续分析啊什么的。如果你学习过易语言,可以跟易语言post技术相类比,而且在某些方面比易语言要优秀。
|
||||||
|
|
||||||
|
- 数据分析:将大数据或普通数据进行分析等,也可以对网络爬虫爬到的数据进行分析,成熟的模块,让有些用其他语言比如matlab、R等的开发者都开始用起了python。
|
||||||
|
|
||||||
|
- 人工智能:目前很热门流行的一个词汇,简单来说就是通过一系列数据建立模型对计算机进行训练,让计算机在某个领域达到人一样的智能,甚至超越人类,比如模型预测、图像识别等等一些,属于目前比较前沿的科学领域了。
|
||||||
|
|
||||||
|
- 自动化运维:这个在一般的公司的IT部门相当常见,只需要简单的几句代码,就可以实现一些自动化运维的任务,大大节省了人工成本,同时开发难度也并不高。对于个人,一些批量性的任务,也可以自己开发个小程序来实现,从此,妈妈再也不用担心我下班晚啦。
|
||||||
|
|
||||||
|
- 其他:常见的比如用户界面编程(这块的话用python写界面的人不算特别多,感兴趣可以深入了解,目前个人觉得易语言写用户界面比较方便)、数据库编程(有大量数据涉及跟数据库交互的,python可以轻松解决)、游戏编程(真的,python还能写个游戏出来),还有其他的一些,咱们就不一一列举了。
|
||||||
|
|
||||||
|
总之,python能实现的东西很多,它的社区很活跃,同时,世界各地有许许多多的贡献者,还会编写自己的一些三方库(即一些已经编写好的解决方案命令,你直接调用就可以实现一些功能,不需要你自己会写)上传到python社区当中,而这些,都是`免费下载和使用`的。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------- | ------------------------------------------------------------ |
|
||||||
|
| unicode | 为每种语言中的每个字符设定了统一并且唯一的二进制编码,统一码、万国码、单一码 |
|
||||||
|
| print | 打印,在python中是一个像控制台输出调试内容的命令,可以理解为`调试输出` |
|
||||||
|
| ASCII | 美国信息交换标准代码,共定义了128个字符,当然,没包含汉字 |
|
||||||
|
| utf-8 | 8位元,是针对Unicode的一种可变长度字符编码。目前应用广泛,python3脚本的默认编码,支持中文 |
|
||||||
|
| last | 最后的 |
|
||||||
|
| release | 发行版,发布 |
|
||||||
|
|
||||||
22
chapter1/1-2 python3小白课:python下载.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# python3小白课:python下载
|
||||||
|
|
||||||
|
官网:[https://www.python.org/](https://www.python.org/)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
可以经过一顿操作之后找到我们需要的下载地址:(我们的课程基于win系统,下载win系统对应的版本,如果你是其他系统对应下载其他系统版本即可)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
python3.8.2 x64:[https://www.python.org/ftp/python/3.8.2/python-3.8.2-amd64.exe](https://www.python.org/ftp/python/3.8.2/python-3.8.2-amd64.exe)
|
||||||
|
|
||||||
|
我会提供已经下载好的安装包,你可以跟着我用同一个版本学习,也可以使用自己喜欢的版本,但建议选择`python3.6+`的版本。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| -------------------- | --------------------------------- |
|
||||||
|
| executable installer | 可执行安装包,你可以理解为exe文件 |
|
||||||
|
| download | 下载 |
|
||||||
26
chapter1/1-3 python3小白课:python安装.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# python3小白课:python安装
|
||||||
|
|
||||||
|
安装时需要注意几个点:
|
||||||
|
|
||||||
|
(1)选择好安装路径,路径中`不要出现中文`,尽量不要出现空格,方便后续寻址。
|
||||||
|
|
||||||
|
(2)勾选添加到`环境变量`,会自动添加,也可以到环境变量中自己添加一下。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ---------------------- | ---------- |
|
||||||
|
| PATH | 路径 |
|
||||||
|
| Customize installation | 自定义安装 |
|
||||||
|
| shortcuts | 快捷方式 |
|
||||||
|
| environment variables | 环境变量 |
|
||||||
|
| location | 位置,定位 |
|
||||||
|
| Install | 安装 |
|
||||||
41
chapter1/1-4 python3小白课:我的第一个python脚本.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# python3小白课:我的第一个python脚本
|
||||||
|
|
||||||
|
python脚本文件是一系列python命令的集合,一般一行一条命令,它的编写很简单,普通的文本编辑器就能完成。
|
||||||
|
|
||||||
|
这里我们使用vscode软件来进行编写。
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> 这里并不推荐使用记事本来编写python脚本,因为可能会有编码的问题,python3脚本默认的编码为utf-8。
|
||||||
|
|
||||||
|
这是一款十分好用轻便的代码编辑器,拥有丰富的插件和精美的代码配色,让你在编程的道路上事半功倍。
|
||||||
|
|
||||||
|
该软件是免费开源软件,大家直接下载安装使用即可。
|
||||||
|
|
||||||
|
软件的下载和使用配置请参考本笔记的首页的底部。扩展方面,安装一个`python`扩展即可,出品方为Microsoft,微软官方。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
安装和配置完成后,我们新建一个文件,即可开始编写我们的第一个python脚本程序。
|
||||||
|
|
||||||
|
编写内容:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
print("你好,小白同学,我是萌萌哒python~")
|
||||||
|
```
|
||||||
|
|
||||||
|
保存为`hello.py`。
|
||||||
|
|
||||||
|
这里请注意,python脚本文件的后缀名为`.py`。
|
||||||
|
|
||||||
|
这样我们的第一个python脚本文件就写好啦,下节课我们来运行一下看吧!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------ | ------------------------- |
|
||||||
|
| coding | 代码,原型是code,ing形式 |
|
||||||
|
| hello | 你好 |
|
||||||
53
chapter1/1-5 python3小白课:如何运行py文件.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# python3小白课:如何运行py文件
|
||||||
|
|
||||||
|
打开cmd命令提示符,输入命令:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python --version
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 如果报错说找不到python这个命令,那么八成是python的目录没有加入到环境变量或者环境变量没生效造成的。
|
||||||
|
>
|
||||||
|
> 如果确认没有加入,加入后重试即可。
|
||||||
|
>
|
||||||
|
> 如果是已经加入了,但还是报找不到,两个方案,一个是重启一下电脑再尝试,另一个是无需重启,使用管理员模式运行cmd窗口即可。
|
||||||
|
>
|
||||||
|
> 如果能够正确打印出版本号,则可以进入后面的操作。
|
||||||
|
|
||||||
|
找到你保存python脚本的路径,举例子,比如完整路径是`D:\scripts\hello.py`
|
||||||
|
|
||||||
|
打开cmd窗口时通常不在这个路径下。
|
||||||
|
|
||||||
|
你需要使用cd命令切换到该路径下,比如默认打开cmd的时候一般是在c盘的某个路径下,接下来你需要输入如下两个命令(输入完命令记得回车哦):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cd D:\scripts
|
||||||
|
d:
|
||||||
|
```
|
||||||
|
|
||||||
|
这样就可以切换到d盘的该路径下了。
|
||||||
|
|
||||||
|
cd命令还可以退到上一级的目录,写法为:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cd..
|
||||||
|
```
|
||||||
|
|
||||||
|
进入该路径后,输入命令执行python脚本:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python hello.py
|
||||||
|
```
|
||||||
|
|
||||||
|
一个非常简单的运行py文件的实例就完成啦!快来试试吧!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------- | -------------- |
|
||||||
|
| scripts | 脚本,复数形式 |
|
||||||
|
| version | 版本 |
|
||||||
26
chapter1/1-6 python3小白课:使用python IDLE.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# python3小白课:使用python IDLE
|
||||||
|
|
||||||
|
如果电脑上没有安装什么文本编辑器(常见于公司服务器的场景,不太允许安装太多的三方工具软件),那么python安装后是会自带一款编辑器供你使用的,虽然我个人感觉没有其他程序写得爽,但还是得介绍让大家知道一下的,那就是`python IDLE`。
|
||||||
|
|
||||||
|
通过系统的搜索或者在开始菜单找到python的目录,就可以找到IDLE了,打开IDLE,可以看到默认的界面就是`python shell`。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
python shell是一个python的行解释器,通过输入python命令,可以单行立即执行代码。有关python shell的相关内容,我们在下一节课还会做进一步讲解。
|
||||||
|
|
||||||
|
在该界面按下`Ctrl+N`快捷键可以新建一个python脚本文件,可以在里面编写我们的py脚本代码。编写完成并保存该文件后,可以按`F5`快捷键直接在该界面运行该代码。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
你还可以做一些IDLE的选项和配置等的设置。
|
||||||
|
|
||||||
|
关于IDLE的知识,大家大致了解一下即可,如果你能自由安装其他软件,安装其他的编辑器或IDE都比这个强,所以大家只需要知道有这么个东西即可。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ----- | -------------------------------------------- |
|
||||||
|
| IDLE | 集成开发和学习环境 |
|
||||||
|
| shell | 壳,一般是命令解析器,为使用者提供命令行操作 |
|
||||||
53
chapter1/1-7 python3小白课:使用python shell.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# python3小白课:使用python shell
|
||||||
|
|
||||||
|
上节课我们介绍过,python shell是一个python的命令行解释器,py文件可以一次性执行许多的代码,而行解释器,是输入一行代码,回车后就立即执行这一行代码,然后你可以再输入下一行。
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 小白同学问:这样的话咱们执行python代码的效率岂不是很慢吗?得一行一行地执行。
|
||||||
|
|
||||||
|
其实啊,我们平常使用python shell最多的场景是临时测试某几行代码的运行效果,因为它不需要将python代码保存成文件,你可以执行任意的代码,在关闭运行窗口或退出python shell之后,它就立即丢失,不会对你造成任何的负担。你可以在里面测试任意的单条代码。
|
||||||
|
|
||||||
|
比如有时候我还拿它来当计算器使用,效果可能比系统自带的还优秀。
|
||||||
|
|
||||||
|
下面我们来介绍一下。
|
||||||
|
|
||||||
|
最常用的运行python shell的环境目前我认为是使用cmd窗口。打开cmd,输入命令`python`并回车,即可进入python shell,如图所示:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
你可以一行行输入命令并回车,可以立即查看结果。
|
||||||
|
|
||||||
|
我还常常用它来查看某些命令自带的帮助文档(这些后续你写自己的命令的时候帮助文档也可以自己定义的),比如我想查看`print`命令的帮助,输入(记住命令后面不需要跟参数或者括号哦):
|
||||||
|
|
||||||
|
```python
|
||||||
|
help(print)
|
||||||
|
```
|
||||||
|
|
||||||
|
如果帮助文档太长显示不完,它还会在最底下显示`More`,继续回车即可查看剩余的帮助内容。
|
||||||
|
|
||||||
|
如果你想退出python shell,可以直接关闭cmd窗口,或者输入命令:
|
||||||
|
|
||||||
|
```python
|
||||||
|
exit()
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 记住括号不要漏掉。
|
||||||
|
|
||||||
|
上述所提到的代码如下图所示:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
上述就是python shell的一些基本使用,很简单,大家随便玩玩即可。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ----- | ---------- |
|
||||||
|
| help | 帮助 |
|
||||||
|
| print | 打印 |
|
||||||
|
| exit | 离开,退出 |
|
||||||
5
chapter1/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# 一、Python初识
|
||||||
|
|
||||||
|
本章节让我们一起走进Python的世界,一起领略这门语言的魅力吧!
|
||||||
|
|
||||||
|
学习完本章节后,相信你对于python已经有一个大概的了解了。
|
||||||
BIN
chapter1/assets/1-1-1.jpg
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
chapter1/assets/1-1-2.jpg
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
chapter1/assets/1-2-1.jpg
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
chapter1/assets/1-2-2.jpg
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
chapter1/assets/1-3-1.jpg
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
chapter1/assets/1-3-2.jpg
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
chapter1/assets/1-3-3.jpg
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
chapter1/assets/1-6-1.jpg
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
chapter1/assets/1-6-2.jpg
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
chapter1/assets/1-7-1.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
chapter1/assets/1-7-2.jpg
Normal file
|
After Width: | Height: | Size: 45 KiB |
70
chapter2/2-1 python3小白课:啥是变量.md
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# python3小白课:啥是变量
|
||||||
|
|
||||||
|
假如你是一个卖花的人,你手里有很多很多的花盆,里面带有土壤。你可以给花盆1种植玫瑰花,给花盆2种植水仙花,给花盆3种植百合花。那么比如`花盆1`就是**变量的名**,你说拿起`花盆1`你也就拿起了里面的玫瑰花,而`玫瑰花`就是变量的值。在python中,变量的值可以是各种各样的限定类型,比如可以是一个数字(数值型),也可以是一串文本内容(字符串型)。变量的名更像是一个容器,就像我们刚才比喻的花盆一样,通过名字可以跟对应的值做连接。
|
||||||
|
|
||||||
|
那么为啥我们需要用到值的时候需要含他的名字呢?一方面是因为名字更好记,另一方面也是因为它的值很多时候在代码中是可以变化的,所以叫做变量嘛。通过含名字来指代这个可能会变化的值,那么后面的代码可能就可以写得更加通用一些。
|
||||||
|
|
||||||
|
关于这一点,我们来看个小例子。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding: utf-8
|
||||||
|
a = 11111
|
||||||
|
b = 22222
|
||||||
|
print(a + b)
|
||||||
|
```
|
||||||
|
|
||||||
|
如果我们仅使用值,而不使用变量,那么我们在计算求和的时候写的是`print(11111 + 22222)`。这时候,如果我们需要修改11111为33333,那么我们需要改2个地方,而使用变量,则只需要在定义它的那一行修改即可。这并不是一个极端的例子,实际的代码可能有成百上千行这样的引用,使用变量,你无需记忆一长串的值的内容,而只需要记住它的名字是a和b即可,十分方便。
|
||||||
|
|
||||||
|
在python中,我们可以使用`=`号来做赋值运算符,它在一行代码中,可以将等于号右边的值赋值给左边。很好理解吧?
|
||||||
|
|
||||||
|
而我们需要求和呢?使用`+`号运算符即可。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 我们可以用print命令将变量或表达式计算的结果打印输出在控制台上。
|
||||||
|
|
||||||
|
还有一个我们使用变量的理由,就是我们有时候无需了解中间的值是多少,只需要关心业务逻辑而已。
|
||||||
|
|
||||||
|
举个例子,比如我们需要打开一个文本文件,文件里面的全部内容我是不关心的,我要做的是想判断能否在该文件中找到某些我需要的内容罢了。
|
||||||
|
|
||||||
|
这时候我们把文件的全部内容读入了,存入变量名为aaa的变量中,此时我们无需看aaa对应的值是什么,直接对aaa变量进行寻找操作并输出查找结果即可实现我的目的。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### python是一种弱类型语言
|
||||||
|
|
||||||
|
python是一种弱类型语言,体现在以下两点:
|
||||||
|
|
||||||
|
(1)变量无需事先声明即可使用,比如上述例子中的变量a(没错,我们通常是这么叫的,变量a),没有声明它是什么类型,直接就可以给它赋值一个数值。
|
||||||
|
|
||||||
|
(2)变量的数据类型可以改变。比如上述例子中的变量a,现在我们的变量a是一个数值型数据,你可以在它的下面再写一行代码`a = "我是小白"`,这样就可以将变量a的类型变为字符串类型了。在python中,我们使用英文的双引号或者单引号引起一段内容,表示字符串,它在你后面的学习中,还会经常碰到,后面我们还会做更加详细的讲解。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 变量命名规范
|
||||||
|
|
||||||
|
在变量名起名时,我们是有一些规范的,有些变量名不支持或不合法,python的解释器就不能正常的把它当做一个变量名来来看待。
|
||||||
|
|
||||||
|
总体来说,python的变量名必须以字母、下划线`_`开头,后面可以跟任意数目的字母、数字和下划线`_`。在python中,变量起名一般不含什么中文汉字等(在python3中虽然支持中文变量名,比如`语文 = 100`,但不推荐,也十分罕见,因为你在敲代码的时候可能就得切换输入法了),通常都是字母、下划线的组合居多,偶尔掺杂数字。注意哦,变量名不能包含**空格**。
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> python对大小写敏感,因此变量a和变量A是两回事。
|
||||||
|
|
||||||
|
原则上,使用简单的单词来表示这个变量的作用,或者用你能理解的写法也行,比如你也可以用拼音、或者拼音的首字母组合来作为变量名,都是可以的。
|
||||||
|
|
||||||
|
还有,一些python的保留关键字或者内置函数也不建议作为变量名使用。如果使用保留关键字做变量名,解释器会报错,如果使用内置函数名作为变量名,解释器不报错,但会把内置函数给覆盖掉,就不能使用内置函数了。
|
||||||
|
|
||||||
|
目前,python的保留关键字有如下这些:
|
||||||
|
|
||||||
|
```python
|
||||||
|
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
|
||||||
|
```
|
||||||
|
|
||||||
|
内置函数大概有这些:
|
||||||
|
|
||||||
|
```python
|
||||||
|
['abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
|
||||||
|
```
|
||||||
|
|
||||||
|
这些英文啥意思,咱就暂且不翻译了,用到再仔细跟大家解释。
|
||||||
64
chapter2/2-10 python3小白课:赋值运算符.md
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
# python3小白课:赋值运算符
|
||||||
|
|
||||||
|
从这节课开始我们来学习一下python中的各种运算符,说到运算符,如果你没有学习过编程的话,可能首先会想到我们数学计算中的`+, -, ×, ÷`几个符号吧。其实在编程语言中还有许多其他的运算符,在python中,我们大致可以分成如下几种:
|
||||||
|
|
||||||
|
* 赋值运算符
|
||||||
|
* 算术运算符
|
||||||
|
* 索引运算符
|
||||||
|
* 比较运算符
|
||||||
|
* 身份运算符
|
||||||
|
* 逻辑运算符
|
||||||
|
* 位运算符
|
||||||
|
* 三目运算符
|
||||||
|
* 成员运算符
|
||||||
|
|
||||||
|
本节课我们先来学习一下赋值运算符。
|
||||||
|
|
||||||
|
这个运算符,相信大家在前面的课程中已经耳熟能详了,就是一个`=`号。
|
||||||
|
|
||||||
|
通过它,可以将等式右边的值赋值给左边,左边可以是一个变量名来接收。
|
||||||
|
|
||||||
|
我们来直接看点例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 最常见的赋值方式,右边赋值给左边
|
||||||
|
a = 1
|
||||||
|
print(a)
|
||||||
|
# 变量可以赋值给变量
|
||||||
|
b = a
|
||||||
|
print(b)
|
||||||
|
# 表达式结果可以赋值给左边
|
||||||
|
c = b + 10
|
||||||
|
print(c)
|
||||||
|
# python还能支持连续赋值,如下,d,e,f的值都被赋值为8
|
||||||
|
d = e = f = 8
|
||||||
|
"""
|
||||||
|
这里有个附加知识点:
|
||||||
|
大家看我这里写的print函数传入了众多的参数。
|
||||||
|
首先是前面几个,在python3中,print函数是支持同时打印出许多个变量的,他们可以有不同的类型
|
||||||
|
然后是后面的一些参数:
|
||||||
|
sep,表示同时打印出多个变量之间的分隔符,默认是一个空格,我这里指定一个|符号分隔
|
||||||
|
end,表示打印完所有变量后的结束符,默认为\n也就是一个换行符,我这里可以指定一些别的内容
|
||||||
|
这俩参数在某些场景下可能会用到,但不常用,大家需要时会用即可
|
||||||
|
"""
|
||||||
|
print(d, e, f, sep="|", end=" 这是结束标识符")
|
||||||
|
# python还支持便捷的变量值交换
|
||||||
|
a = 1
|
||||||
|
b = 2
|
||||||
|
# 这里将变量b的值赋值给a,将变量a的值赋值给b,实现变量交换
|
||||||
|
a, b = b, a
|
||||||
|
print(a)
|
||||||
|
print(b)
|
||||||
|
```
|
||||||
|
|
||||||
|
赋值运算符,很简单。大家必须熟练掌握。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ---- | ------------------------------------ |
|
||||||
|
| sep | 应为seperate分隔,分开这个单词的简写 |
|
||||||
|
| end | 结束,表示结束符 |
|
||||||
39
chapter2/2-11 python3小白课:算术运算符.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# python3小白课:算术运算符
|
||||||
|
|
||||||
|
话不多说,直接看一下咱们的代码:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# +号用来算术相加,或者字符串拼接等
|
||||||
|
a = 1 + 1
|
||||||
|
b = "little " + "bai"
|
||||||
|
print(a, b)
|
||||||
|
# -号一般表示算术相减,或者负数等
|
||||||
|
a = 2 - 1
|
||||||
|
b = -4
|
||||||
|
print(a, b)
|
||||||
|
# *号表示乘法,也可以用来重复输出字符串一定的次数
|
||||||
|
a = 8 * 3
|
||||||
|
b = "=" * 40
|
||||||
|
print(a, b, sep="\n")
|
||||||
|
# /号表示除法,如果除不尽会出现小数,但不允许除数为0哦(除数不允许为0这个以前咱们也学过)
|
||||||
|
a = 24 / 8
|
||||||
|
b = 24 / 9
|
||||||
|
print(a, b, sep="\n")
|
||||||
|
# //号,表示整除,只取结果中的整数部分,小数部分不会四舍五入,而是全部舍去
|
||||||
|
a = 5 // 2
|
||||||
|
print(a)
|
||||||
|
# %号表示求余运算符,需要区别我们格式化字符串的时候用%,这里是运算符,求余数
|
||||||
|
# 求余数跟整除结合,常常用来做秒跟分、小时、天等单位的换算,很有用
|
||||||
|
a = 10 % 8
|
||||||
|
print(a)
|
||||||
|
# **为乘方运算符,用来求幂的,比如2的3次方就是8
|
||||||
|
a = 2 ** 3
|
||||||
|
print(a)
|
||||||
|
# 当然乘方运算符还能做开方哦,比如开3次方其实就是1/3次方。经过测试我们发现返回一个float浮点数结果
|
||||||
|
a = 8 ** (1/3)
|
||||||
|
print(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
算术运算符很简单,大家请好好掌握哦。
|
||||||
|
|
||||||
11
chapter2/2-12 python3小白课:索引运算符.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# python3小白课:索引运算符
|
||||||
|
|
||||||
|
索引运算符之前我们已经遇到过了就是中括号`[]`,通过它可以来表示索引值、索引范围等,这些我们在之前的课程中已经学习过了,所以我们就不再赘述,除了之前我们学习过的内容,索引运算符还能够指定步长,我们来看一下如下的例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = "my name is little bai"
|
||||||
|
# 取出索引1到索引10(不包含10)的内容,步长为2,也是用冒号即可
|
||||||
|
print(a[1:10:2])
|
||||||
|
```
|
||||||
|
|
||||||
22
chapter2/2-13 python3小白课:比较运算符.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# python3小白课:比较运算符
|
||||||
|
|
||||||
|
比较运算符是用来做比较的,很好理解,我们来直接看看例子再讲解:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 比较运算符运算表达式的比较结果会返回布尔型True或者False(注意大小写),满足返回真,否则返回假
|
||||||
|
a = 10
|
||||||
|
b = 5
|
||||||
|
# 大于
|
||||||
|
print(a > 3)
|
||||||
|
# 大于等于
|
||||||
|
print(a >= 10)
|
||||||
|
# 小于
|
||||||
|
print(b < a)
|
||||||
|
# 小于等于
|
||||||
|
print(1 <= b)
|
||||||
|
# 判断表达式是否值相等,注意用的两个等号,一个等号是赋值,注意区分和记忆
|
||||||
|
print(a == 10)
|
||||||
|
# 不等于,在python2中<>、!=都表示不等于,python3中不允许,所以大家统一写!=即可
|
||||||
|
print(a != 10)
|
||||||
|
```
|
||||||
34
chapter2/2-14 python3小白课:身份运算符.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# python3小白课:身份运算符
|
||||||
|
|
||||||
|
身份运算符是用来表示身份的,在python中用来比较对象是否相等。返回的结果也是True或者False。
|
||||||
|
|
||||||
|
来看例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = 10
|
||||||
|
b = 5
|
||||||
|
# 判断对象是否相等,常用场景是判断类型,用is关键字
|
||||||
|
print(type(a) is int)
|
||||||
|
# 判断对象是否不相等,常用场景也是判断类型,判断是否是None的比较多,用is not关键字
|
||||||
|
"""
|
||||||
|
None表示空值,它是一个特殊 Python 对象, None的类型是NoneType
|
||||||
|
None不支持任何运算也没有任何内建方法
|
||||||
|
可以给变量赋值为None,念的时候一般称作空值或空,其他语言也有类似概念
|
||||||
|
做一些编程判断的很有用的一种类型,比如没返回任何结果可以返回None等
|
||||||
|
***必须必须要知道它~***
|
||||||
|
"""
|
||||||
|
print(type(a) is not None)
|
||||||
|
c = None
|
||||||
|
print(c is None)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------ | ------------------------------------------------------------ |
|
||||||
|
| None | python中的空值类型,类型名为NoneType,使用type(None)可以看到 |
|
||||||
|
| is | 是 |
|
||||||
|
| is not | is的否定形式,表示不是 |
|
||||||
32
chapter2/2-15 python3小白课:逻辑运算符.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# python3小白课:逻辑运算符
|
||||||
|
|
||||||
|
逻辑运算主要用于操作布尔类型(bool)的变量、常量或表达式,逻辑运算符的返回值还是布尔类型。许多编程语言都有相类似或相同的概念,掌握一次,学习其他编程语言时即可很快上手。
|
||||||
|
|
||||||
|
python中就三个逻辑运算符,我们来直接看下代码例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# and,与,前后的表达式都为真时,逻辑返回结果才为真True,否则返回假False
|
||||||
|
a = 10
|
||||||
|
b = 5
|
||||||
|
print(a <= 10 and b == 5)
|
||||||
|
# or,或,前后的表达式任意一个为真时,逻辑返回结果即为真True,都为假才返回假False
|
||||||
|
print(a >= 100 or b == 5)
|
||||||
|
# not,非,只需要一个表达式,表达式结果为True,则返回False,结果为False,则返回True,即反义
|
||||||
|
print(not(a == 10))
|
||||||
|
# 多个逻辑运算符还能嵌套运行,虽然有运算符优先级,但还是建议使用小括号把需要先算的括起来
|
||||||
|
# 这样可以保证代码的可读性,因为,一般人都记不住很多运算符的优先级的
|
||||||
|
print(a <= 10 and (a > b or b == 5))
|
||||||
|
```
|
||||||
|
|
||||||
|
关于逻辑运算符是大家必须掌握的东西,今后在做一些逻辑判断的时候很重要。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ---- | ---------------------- |
|
||||||
|
| and | 与 |
|
||||||
|
| or | 或 |
|
||||||
|
| not | 非,你也可以理解为不是 |
|
||||||
42
chapter2/2-16 python3小白课:位运算符.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# python3小白课:位运算符
|
||||||
|
|
||||||
|
位运算符是用来直接处理数字的原始bit位,是把数字看作二进制来进行计算的。常用在图形、图像处理,文本加解密等领域。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 但在日常常见的编程中,实话说比较罕见,而且掌握起来也有一定的难度,掌握后如果不经常使用也容易忘。因此如果你没有对它的日常需要,可以不进行它的掌握,直接跳过本节即可。感兴趣的同学可以自行查阅网上的资料深入学习。
|
||||||
|
|
||||||
|
我们来看点简单的例子:
|
||||||
|
|
||||||
|
假如 a 为 60,b 为 13。则二进制格式为:
|
||||||
|
|
||||||
|
`a = 0011 1100`
|
||||||
|
|
||||||
|
`b = 0000 1101`
|
||||||
|
|
||||||
|
我们有如下的运算符可供选择:
|
||||||
|
|
||||||
|
| 运算符 | 描述 | 实例 |
|
||||||
|
| :----- | :----------------------------------------------------------- | :-------------------------------------------- |
|
||||||
|
| & | 按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0 | (a & b) 输出结果 12 ,二进制解释: 0000 1100 |
|
||||||
|
| | | 按位或运算符:只要对应的两个二进位有一个为1时,结果位就为1。 | (a | b) 输出结果 61 ,二进制解释: 0011 1101 |
|
||||||
|
| ^ | 按位异或运算符:当两对应的二进位相异时,结果为1 | (a ^ b) 输出结果 49 ,二进制解释: 0011 0001 |
|
||||||
|
| ~ | 按位取反运算符:对数据的每个二进制位取反,即把1变为0,把0变为1 。**~x** 类似于 **-x-1** | (~a ) 输出结果 -61 ,二进制解释: 1100 0011 |
|
||||||
|
| << | 左移动运算符:运算数的各二进位全部左移若干位,由 **<<** 右边的数字指定了移动的位数,高位丢弃,低位补0。 | a << 2 输出结果 240 ,二进制解释: 1111 0000 |
|
||||||
|
| >> | 右移动运算符:把**>>**左边的运算数的各二进位全部右移若干位,**>>** 右边的数字指定了移动的位数 | a >> 2 输出结果 15 ,二进制解释: 0000 1111 |
|
||||||
|
|
||||||
|
我们来看一下验证的代码:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = 0b00111100 # 即a = 60
|
||||||
|
b = 0b00001101 # 即b = 13
|
||||||
|
print(a, b)
|
||||||
|
print(a & b)
|
||||||
|
print(a | b)
|
||||||
|
print(a ^ b)
|
||||||
|
print(~a)
|
||||||
|
print(a << 2)
|
||||||
|
print(a >> 2)
|
||||||
|
```
|
||||||
|
|
||||||
33
chapter2/2-17 python3小白课:赋值运算符扩展.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# python3小白课:赋值运算符扩展
|
||||||
|
|
||||||
|
通过前面的运算符学习,我们可以将赋值运算符进行一定的扩展。
|
||||||
|
|
||||||
|
比如当我们给变量自增的时候,我们可以这么写代码:
|
||||||
|
|
||||||
|
`a = a + 1`
|
||||||
|
|
||||||
|
这么写是允许的,这样会将变量a原有的值加上1,然后再赋值回去给a。在这里,希望小白同学不要用学校里看方程一样的看法来看这个等式,问:这个怎么能相等呢?其实我们这里不是一个等式而是一种赋值形式。在编程中有很多这样的类似写法,大家需要转变一下观念。
|
||||||
|
|
||||||
|
上面的写法还有一种更优化的写法:
|
||||||
|
|
||||||
|
`a += 1`
|
||||||
|
|
||||||
|
也能达到前面一模一样的效果,但我们敲内容已经少了很多。上述两种写法均可,这个选用哪种可以看你个人的需要,其实,哪种好理解,自己好记忆就用哪种就好了。同样的道理,大家可以举一反三,下面的代码看一下:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = 10
|
||||||
|
print(a += 1)
|
||||||
|
print(a -= 1)
|
||||||
|
print(a *= 1)
|
||||||
|
print(a /= 1)
|
||||||
|
print(a //= 3)
|
||||||
|
print(a %= 8)
|
||||||
|
print(a **= 2)
|
||||||
|
print(a &= 1)
|
||||||
|
print(a |= 1)
|
||||||
|
print(a ^= 1)
|
||||||
|
print(a <<= 1)
|
||||||
|
print(a >>= 1)
|
||||||
|
```
|
||||||
|
|
||||||
28
chapter2/2-18 python3小白课:三目运算符.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# python3小白课:三目运算符
|
||||||
|
|
||||||
|
三目运算符是非此即彼的,它可以通过一行的if...else...语句来实现,if表示如果,else表示否则,如果某个表达式的值为True(相信大家看多布尔值之后也熟悉了,今后我们就尽量不在文字中说真了,尽量讲True,False同理),则返回某个结果或运行某个表达式求值,如果为False,则返回另一个结果求值。
|
||||||
|
|
||||||
|
我们来看一个简单的例子帮助大家理解:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = "西瓜甜"
|
||||||
|
print("小白吃西瓜") if a == "西瓜甜" else print("把西瓜给小黑吃")
|
||||||
|
```
|
||||||
|
|
||||||
|
其中,`print("小白吃西瓜")`为`a == "西瓜甜"`这个表达式为True时运行的,如果它为False,则运行`print("把西瓜给小黑吃") `后面这部分,是不是很简单呢?
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> 三目运算符是一种简易的流程控制方式,这是我们第一次接触这样的概念,流程控制让我们的程序不再单调的只有一种可能性,而是根据实际的情况智能的返回结果。
|
||||||
|
>
|
||||||
|
> 关于流程控制的知识我们在后面的课程中还会有更加详细的讲解。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ---- | ---- |
|
||||||
|
| if | 如果 |
|
||||||
|
| else | 否则 |
|
||||||
26
chapter2/2-19 python3小白课:成员运算符.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# python3小白课:成员运算符
|
||||||
|
|
||||||
|
成员运算符可以测试某个成员在不在字符串、列表、元组里面,其中列表、元组我们后面会详细讲解,本节课我们可以先接触一下。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 用in运算符探测成员在不在被测试者里面,前面我们也提到过不知道大家还记得不?返回布尔值结果
|
||||||
|
a = "he"
|
||||||
|
print(a in "hello")
|
||||||
|
# 用not in表示不在里面,不在才返回True
|
||||||
|
print(a not in "little bai")
|
||||||
|
# 也可以判断在不在列表元素中,列表用[]表示
|
||||||
|
print(1 in [1, 3, 5])
|
||||||
|
# 判断在不在元组元素中,元组用()表示
|
||||||
|
print("bai" in ("blue", 1, 'yellow'))
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------ | ---- |
|
||||||
|
| blue | 蓝色 |
|
||||||
|
| yellow | 黄色 |
|
||||||
|
|
||||||
51
chapter2/2-2 python3小白课:定义常量.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# python3小白课:定义常量
|
||||||
|
|
||||||
|
有了变量,让我们来讲一讲常量。
|
||||||
|
|
||||||
|
常量怎么理解?我们可以类比变量来理解,变量是可以变的量,在定义了之后,还能再次给这个变量的值重新赋值,那是变量。而常量就是在运行过程中不可变的。比如圆周率π保留两位小数是3.14,是约定俗成的不会变的东西,那我们就可以称之为常量,常量也分常量名和常量值。一般来说定义了就不会变,也不允许重新赋值。
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> 在很多其他的编程语言中都有常量的概念,但是在python中呢?默认是没有的。
|
||||||
|
|
||||||
|
对,你没听错,目前,python默认就不支持定义一个常量。那怎么办呢?在python的规则中,我们一般约定,当一个变量名全部大写的时候,我们就说它是一个常量(虽然这个“常量”实际上依然还可以重新被赋值)。
|
||||||
|
|
||||||
|
当然,后面改不改它,是你代码说了算的,一般我们按照约定来,不修改这种全部为大写字母的变量就可以了(数字、下划线等也可以作为“常量”的变量名的一部分)。所以,我们在定义一个变量的时候一般是要包含小写字母的。
|
||||||
|
|
||||||
|
来我们看个例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding: utf-8
|
||||||
|
NAME = "little bai"
|
||||||
|
AGE = 18
|
||||||
|
```
|
||||||
|
|
||||||
|
这样我们就轻松定义了两个“常量”。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 延伸阅读
|
||||||
|
|
||||||
|
如果你真的想通过python定义那种不能修改的常量可以怎么做?(其实掌握课程内教学的内容已足够使用)
|
||||||
|
|
||||||
|
请看这篇文章:
|
||||||
|
|
||||||
|
[python中如何定义常量](http://www.xueshanlinghu.com/excellent-articles/2664.html)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### python自带的常量
|
||||||
|
|
||||||
|
在python中,自带也有一小部分常量值,是不可变的,没有什么常量名常量值的说法,就是一个常量,比如布尔值,**真**`True`,**假**`False`等,它们可以直接被使用。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------ | ---- |
|
||||||
|
| name | 姓名 |
|
||||||
|
| little | 小 |
|
||||||
|
| age | 年龄 |
|
||||||
|
| True | 真 |
|
||||||
|
| False | 假 |
|
||||||
145
chapter2/2-20 python3小白课:运算符优先级.md
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
# python3小白课:运算符优先级
|
||||||
|
|
||||||
|
我们在前面的课程中学习了许许多多的运算符,我们在学习时为了简化,都是最简单的写法来表述它们,有时候一个表达式里面仅出现一个运算符,方便大家理解。而它们如果同时出现在一起,python解释器在解释的时候是有优先级顺序的,我们来看看下面的表格:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<caption>
|
||||||
|
Python 运算符优先级和结合性一览表
|
||||||
|
</caption>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th> 运算符说明</th>
|
||||||
|
<th> Python运算符</th>
|
||||||
|
<th> 优先级</th>
|
||||||
|
<th> 结合性</th>
|
||||||
|
<th> 优先级顺序</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 小括号</td>
|
||||||
|
<td> ( )</td>
|
||||||
|
<td> 19</td>
|
||||||
|
<td> 无</td>
|
||||||
|
<td colspan="1" rowspan="19"> 高<br /> ︿<br /> |<br /> |<br /> |<br /> |<br /> |<br /> |<br /> |<br /> |<br /> |<br /> |<br /> |<br /> |<br /> |<br /> |<br /> |<br /> |<br /> |<br /> |<br /> |<br /> | <br /> |<br /> |<br /> 低</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 索引运算符</td>
|
||||||
|
<td> x[i] 或 x[i1: i2 [:i3]]</td>
|
||||||
|
<td> 18</td>
|
||||||
|
<td> 左</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 属性访问</td>
|
||||||
|
<td> x.attribute</td>
|
||||||
|
<td> 17</td>
|
||||||
|
<td> 左</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 乘方</td>
|
||||||
|
<td> **</td>
|
||||||
|
<td> 16</td>
|
||||||
|
<td> 左</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 按位取反</td>
|
||||||
|
<td> ~</td>
|
||||||
|
<td> 15</td>
|
||||||
|
<td> 右</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 符号运算符</td>
|
||||||
|
<td> +(正号)、-(负号)</td>
|
||||||
|
<td> 14</td>
|
||||||
|
<td> 右</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 乘除</td>
|
||||||
|
<td> *、/、//、%</td>
|
||||||
|
<td> 13</td>
|
||||||
|
<td> 左</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 加减</td>
|
||||||
|
<td> +、-</td>
|
||||||
|
<td> 12</td>
|
||||||
|
<td> 左</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 位移</td>
|
||||||
|
<td> >>、<<</td>
|
||||||
|
<td> 11</td>
|
||||||
|
<td> 左</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 按位与</td>
|
||||||
|
<td> &</td>
|
||||||
|
<td> 10</td>
|
||||||
|
<td> 右</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 按位异或</td>
|
||||||
|
<td> ^</td>
|
||||||
|
<td> 9</td>
|
||||||
|
<td> 左</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 按位或</td>
|
||||||
|
<td> |</td>
|
||||||
|
<td> 8</td>
|
||||||
|
<td> 左</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 比较运算符</td>
|
||||||
|
<td> ==、!=、>、>=、<、<= </td>
|
||||||
|
<td> 7</td>
|
||||||
|
<td> 左</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> is 运算符</td>
|
||||||
|
<td> is、is not</td>
|
||||||
|
<td> 6</td>
|
||||||
|
<td> 左</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> in 运算符</td>
|
||||||
|
<td> in、not in</td>
|
||||||
|
<td> 5</td>
|
||||||
|
<td> 左</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 逻辑非</td>
|
||||||
|
<td> not</td>
|
||||||
|
<td> 4</td>
|
||||||
|
<td> 右</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 逻辑与</td>
|
||||||
|
<td> and</td>
|
||||||
|
<td> 3</td>
|
||||||
|
<td> 左</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 逻辑或</td>
|
||||||
|
<td> or</td>
|
||||||
|
<td> 2</td>
|
||||||
|
<td> 左</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 逗号运算符</td>
|
||||||
|
<td> exp1, exp2</td>
|
||||||
|
<td> 1</td>
|
||||||
|
<td> 左</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
上面这东西,大家看一看就好,在实际编写代码的过程中,我们需要注意代码的可读性,所以我们一般不需要写那么复杂的多个运算符糅杂在一起的语句,如果有,你可以拆成多行来写,这样阅读起来更加清晰。
|
||||||
|
|
||||||
|
同时我们可以注意到优先级最高的应该是`()`小括号,因此我们可以完全记不住这张表,使用小括号来将表达式计算顺序来表达清楚,这样更有助于代码的可读性。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| --------- | ---------------------------------- |
|
||||||
|
| atrribute | 属性 |
|
||||||
|
| exp | expression表达式这个单词的简写形式 |
|
||||||
73
chapter2/2-3 python3小白课:注释让你事半功倍.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# python3小白课:注释让你事半功倍
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 注释是啥?
|
||||||
|
|
||||||
|
大家想想,当我们在学校的时候,拿着课本,老师讲到哪里,我们是不是就在哪里做一下笔记啊?(em...要是你不做笔记,那当我没说)
|
||||||
|
|
||||||
|
这个笔记就是一种**注释**。
|
||||||
|
|
||||||
|
在各种编程语言中,注释是一个没什么用但又很有用的东西。它对于实际的代码用处不大,在编译或者解释代码的时候,注释内容会被自动忽略掉,实际执行时不生效。但对于我们开发者来说,堪比代码的说明文档。
|
||||||
|
|
||||||
|
因为注释内容在实际运行时会被忽略,因此你就可以理解为可以尽情恣意的在代码中编写自己喜欢的注释。
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 注释写点啥呢?
|
||||||
|
|
||||||
|
嗯,原则是,你想写啥写啥,你还可以写一首诗上去呢哈哈哈。实际上,我们一般会在某几行关键代码的上方、下方、右方等位置编写注释,内容一般写的是这代码是干啥的,有什么注意事项,有什么要点,未来如何维护或者二次开发等等。
|
||||||
|
|
||||||
|
你写的越详细,对你就越有好处。
|
||||||
|
|
||||||
|
有的同学说,不用啊,不就那几行简单的代码吗?我记得住,我也都知道它干啥的,费那劲呢写注释。
|
||||||
|
|
||||||
|
实则不然。对于你自己来说,你今天记得代码是干啥的,明天记得,你能保证三四年之后你再回来看你当时写的代码是什么意思吗?当你的代码量达到成千上万行的时候,你还能清晰的知道你过去写这么多代码的逻辑结构是什么吗?有了注释,这一切就迎刃而解了。对于别人来说,当你的代码需要开源给别人看,或者进行代码团队协作,或者公司里你离职了,新同事需要维护接管你之前写的代码,没有注释,他是不是要直接去看你的代码来理解逻辑呢?因为不同的人实现同一个功能代码结构可能是有差异的,因此没有注释的代码也极其让别人痛苦,无法很好的做二次开发优化。
|
||||||
|
|
||||||
|
综上所述,注释很重要,能写的部分一定要写,首先是要满足自己知道这是干啥的,其次才是让看你代码的人也能一目了然,而且越详细的注释越有助于别人理解你的代码和你自己记忆起你的代码逻辑。有人说,合理的代码注释应该占源代码的1/3左右,这个你根据自己情况,适量就好。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 除了添加内容注释让人明白代码是做什么的,使用注释还有一个功效,就是调试程序,比如一大段代码中,我有几行代码暂时不需要了,但是以后可能需要呀,这时候可以把这几行代码给注释掉,这样解释器在运行py脚本的时候就会忽略了,当我们再需要的时候,取消注释,就可以了。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
相信大家在听完前面的内容之后都知道了注释的重要性,那么在python中,注释要怎么写呢?
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding: utf-8
|
||||||
|
|
||||||
|
"""
|
||||||
|
我是多行注释1,可以用三个双引号括起来
|
||||||
|
多行注释这是第二行
|
||||||
|
"""
|
||||||
|
|
||||||
|
'''
|
||||||
|
我是多行注释2,可以用三个单引号括起来
|
||||||
|
多行注释这是第二行
|
||||||
|
'''
|
||||||
|
|
||||||
|
# 我是单行注释,这一行的所有内容都被视为注释。
|
||||||
|
a = 1
|
||||||
|
b = 2 # 我是单行注释,#号左边是代码,右边一直到行末都是注释内容,随便写。
|
||||||
|
print(a + b) # 比如可以这样写:打印输出a与b的和
|
||||||
|
|
||||||
|
# 多行注释也可以在每一行的开头加上#号,也算多行注释的一种
|
||||||
|
# 许多文本编辑器都有自带的快捷键支持单行或多行注释或取消注释,百度或者看下编辑器的菜单栏即可
|
||||||
|
```
|
||||||
|
|
||||||
|
我们来看一下如上的例子,我们先来说一下后面常规的注释吧。
|
||||||
|
|
||||||
|
注释的标识符为`#`号,出现它,那么这一行的右侧的内容就会全部被解释器视为注释内容,在执行时会忽略不进行执行。这是一般单行注释的用法。
|
||||||
|
|
||||||
|
多行注释时,一种办法是可以通过文本编辑器的快捷键,先选中需要注释掉的多行,然后按一下快捷键,批量在前面加上`#`号,如果需要恢复也可以按下快捷键批量变回代码。另一种办法是使用上述代码中介绍到的多行注释的方法,使用单引号或双引号均可,效果一致,可以看你喜欢。当我们定义多行文本字符串的时候,也是用的这种方法。
|
||||||
|
|
||||||
|
咱们再来看一下开头的第一行代码,前面也有一个`#`号,那它是注释吗?其实也是注释的,为啥我们都需要写它呢?它的作用其实是给解释器标注脚本的编码格式,在python2中,如果不标注它,则默认代码是ascii编码的,所以需要写一下它是utf-8编码,否则解释器会报错,也不能正常处理中文。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 在python3中,默认的脚本编码格式就是utf-8编码,因此理论上在python3中,不写它也不会报错,也能正常处理中文。但为了代码的可移植性,还是建议习惯性都写上会比较好。编码格式的定义一般写在py文件的第一或第二行。其实你就跟着我写就可以了。
|
||||||
|
|
||||||
|
关于文件编码声明的更多详细标准内容,可以查阅官方文档做延伸阅读:
|
||||||
|
|
||||||
|
[https://www.python.org/dev/peps/pep-0263/](https://www.python.org/dev/peps/pep-0263/)
|
||||||
51
chapter2/2-4 python3小白课:数值类型之整型.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# python3小白课:数值类型之整型
|
||||||
|
|
||||||
|
从这节课开始我们来介绍几种普通又常见的数据类型。
|
||||||
|
|
||||||
|
首先是数值类型,数值类型很好理解,就是用来做数学运算用的。比如我们之前课程中涉及到的人的年龄,就是一种数值。
|
||||||
|
|
||||||
|
数值类型有几种,本节课我们来讲一下——整型(int)。
|
||||||
|
|
||||||
|
整型你也可以理解为整数型,在python3中,能自动处理很大很小的整型数据,类型为int。
|
||||||
|
|
||||||
|
通常我们最常碰到的应该是十进制的数字,比如写个12,那么就是12不是别的东西。在整型中可能还能定义二进制、八进制、十六进制的表示法,但它们不常用,你也可以忽略理解它们。
|
||||||
|
|
||||||
|
来看下我们的例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding: utf-8
|
||||||
|
# 定义一个整型数据
|
||||||
|
a = 1
|
||||||
|
print(a)
|
||||||
|
# type命令可以查看一个值或者变量的类型,将要查看的东东括起来就可以啦~
|
||||||
|
# 命令可以嵌套,print可以把类型结果打印出来
|
||||||
|
print(type(a))
|
||||||
|
# 用0b或0B开头表示二进制整型,日常不常见
|
||||||
|
b = 0b111
|
||||||
|
print(b)
|
||||||
|
# 用0o或0O开头表示八进制整型,日常不常见
|
||||||
|
c = 0o54
|
||||||
|
print(c)
|
||||||
|
# 用0x或0X开头表示十六进制整型,日常不常见
|
||||||
|
d = 0x13
|
||||||
|
print(d)
|
||||||
|
# python3后可以用下划线来作为整型分隔符,方便阅读,类似与会计上的,号
|
||||||
|
# 例子中其实e就是1,000,000一百万
|
||||||
|
e = 1_000_000
|
||||||
|
print(e)
|
||||||
|
```
|
||||||
|
|
||||||
|
从例子中我们学到了一个新的命令`type()`。今后如果需要查看类型的时候就可以使用它。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 一般来讲就是用十进制就好了,其他的花里胡哨的知道下就好。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ---- | ----------------------------------------------- |
|
||||||
|
| int | integer整数这个单词的简短形式,很多地方都能看到 |
|
||||||
|
| type | 类型 |
|
||||||
34
chapter2/2-5 python3小白课:数值类型之浮点型.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# python3小白课:数值类型之浮点型
|
||||||
|
|
||||||
|
我们继续来讲数值类型。
|
||||||
|
|
||||||
|
浮点型(float)是另一种数据类型。
|
||||||
|
|
||||||
|
我们日常见到的小数,含有小数点的,你就可以理解为属于浮点型。
|
||||||
|
|
||||||
|
加上小数点,就会变成了浮点型。即使你写5000.0,它也是一个浮点型,请注意。
|
||||||
|
|
||||||
|
浮点型还能表示科学计数法,比如5e3表示5×10<sup>3</sup>即5000。
|
||||||
|
|
||||||
|
我们来看点例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = 3.14159
|
||||||
|
print(type(a))
|
||||||
|
b = 5000.0
|
||||||
|
print(type(b))
|
||||||
|
c = 5e3
|
||||||
|
print(c)
|
||||||
|
print(type(c))
|
||||||
|
```
|
||||||
|
|
||||||
|
大家自己在python shell里面动手试一下就好啦~
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ----- | ---------------- |
|
||||||
|
| float | 浮动,表示浮点型 |
|
||||||
30
chapter2/2-6 python3小白课:数值类型之复数.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# python3小白课:数值类型之复数
|
||||||
|
|
||||||
|
复数(complex)其实在日常不是那么常用到,本课你可以忽略掉也可以,了解下也可以。除非你用到高精尖的数学运算逻辑。按个人经验,复数这个东西其实也基本只在学校课本中提到过了。
|
||||||
|
|
||||||
|
复数是啥?如果不是很了解的童鞋可以看一下百度百科:
|
||||||
|
|
||||||
|
[https://baike.baidu.com/item/%E5%A4%8D%E6%95%B0/254365?fr=aladdin](https://baike.baidu.com/item/%E5%A4%8D%E6%95%B0/254365?fr=aladdin)
|
||||||
|
|
||||||
|
我们来看一下一个复数如何定义即可:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = 3 + 0.2j
|
||||||
|
print(a)
|
||||||
|
print(type(a))
|
||||||
|
```
|
||||||
|
|
||||||
|
用j或J表示虚部即可,其他为实部。
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> 本课不重要,理解不了可跳过。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------- | -------------------- |
|
||||||
|
| complex | 复杂的,表示复数类型 |
|
||||||
147
chapter2/2-7 python3小白课:字符串入门.md
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
# python3小白课:字符串入门
|
||||||
|
|
||||||
|
字符串(string)这个东西我们在前面的课程中已经见过了,从本节课开始我们来系统的学习一下字符串所需掌握的一些必备知识。在日常的编程处理中,字符串的处理可以说是一个大头,所以掌握好字符串的各项知识十分重要,请大家认真学习,我已经把最精练最常见的知识内容提炼给大家,大家只需要一步步跟着学习即可。
|
||||||
|
|
||||||
|
首先,如何定义字符串(str类型),我们直接来看例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = "我是小白我很白"
|
||||||
|
b = '我是小黑我不黑'
|
||||||
|
print(a)
|
||||||
|
print(type(b))
|
||||||
|
```
|
||||||
|
|
||||||
|
我们可以看到,使用单引号、双引号都可以定义字符串,他们并没有啥区别。
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 小白问,那么为啥我们要有两种符号支持呢?
|
||||||
|
|
||||||
|
来看看下面这个场景,当我们字符串内容中含有单引号或者双引号的时候:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = 'I'm little bai'
|
||||||
|
print(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
这时候python解释器会无法判定这个字符串的结尾在哪,是在中间还是在结尾?此时就会报错。我们可以修改成这样:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = "I'm little bai"
|
||||||
|
print(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
这时候单双引号均可的好处就凸显了。
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 小白又问了,那么要是字符串内容里,咱们既有单引号,又有双引号,这可咋办?
|
||||||
|
|
||||||
|
别怕,我们可以使用`\`符号写在字符串内的引号前面,表示**转义**。通过转义,python解释器在解释的时候,就会把它当做原来的单双引号输出了。来我们看一下例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = "I'm \"little bai\""
|
||||||
|
print(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 多个字符串拼接
|
||||||
|
|
||||||
|
如果我们有多个字符串需要拼接,通常的做法是使用`+`号。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = "hello"
|
||||||
|
b = "little bai"
|
||||||
|
print(a + " " + b)
|
||||||
|
```
|
||||||
|
|
||||||
|
你看,很简单的,我们还能把空格打出来。
|
||||||
|
|
||||||
|
这里需要注意的是,加在一起的内容中,都应该是字符串,如果含有数字加在一起,会报错,正确的方式是将数字通过str命令转化成字符串后再相加。(同理,转换成整型、浮点型你也可以用int、float内置命令实现从字符串转化成数值哦)
|
||||||
|
|
||||||
|
```python
|
||||||
|
#coding: utf-8
|
||||||
|
a = "my age is"
|
||||||
|
b = 19
|
||||||
|
print(a + " " + str(b))
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 多行字符串
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 如果我们有多行字符串内容,我们应该如何定义呢?
|
||||||
|
|
||||||
|
还记得我们学过的多行注释吗?没错,就是使用三个单引号或三个双引号来实现。在这样的定义方法中,我们不仅能保留多行之间的缩进能信息,还能省去使用转义符等内容。我们来看一下例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = """
|
||||||
|
朝辞白帝彩云间,
|
||||||
|
千里江陵一日还。
|
||||||
|
两岸猿声啼不住,
|
||||||
|
轻舟已过万重山。
|
||||||
|
I'm "little bai"
|
||||||
|
"""
|
||||||
|
print(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
是不是很方便呢?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 原始字符串
|
||||||
|
|
||||||
|
最后再来讲一个原始字符串,这个我个人的使用不是特别多,但了解下也可以的。我们前面知道,`\`为转义符号,所以当我们的字符串是一个windows的文件路径的时候,它就带有`\`,所以我们表示win路径的时候,通常需要这样写(一般我个人也是这么写的):
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = "E:\\Programs\\python3小白课\\python3小白课笔记"
|
||||||
|
print(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
如果不这样用,有时候在py脚本中就会给你报错。
|
||||||
|
|
||||||
|
如果你不喜欢用转义符来弄,可以用原始字符串(raw):
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = r"E:\Programs\python3小白课\python3小白课笔记"
|
||||||
|
print(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
即前面简单加上一个r修饰字符串即可。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### input函数
|
||||||
|
|
||||||
|
入了门,我们来学习一个新的内置函数:input。这个函数可以获取用户的输入内容,这个内容在python3中都会统一返回字符串(所以即使输入数字也无需转换成str类型),你可以用变量接收它的返回值并做后续处理。可以用作用户交互或者跟你自己的交互。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = input("你叫什么名字呀?")
|
||||||
|
print("你的名字是:" + a)
|
||||||
|
a = input("你多少岁呀?")
|
||||||
|
print("你" + a + "岁了")
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------ | --------------------------------------------- |
|
||||||
|
| string | 字符串,短一点的写法叫做str,也是一个内置命令 |
|
||||||
|
| my | 我的 |
|
||||||
|
| is | 是 |
|
||||||
|
| raw | 原始的 |
|
||||||
|
| input | 输入 |
|
||||||
39
chapter2/2-8 python3小白课:字节串.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# python3小白课:字节串
|
||||||
|
|
||||||
|
本节课所介绍的字节串(bytes)类型比较抽象一点,如果你无法理解掌握,可以先跳过,以后可以结合一些网上的资料再次学习。
|
||||||
|
|
||||||
|
这是python3新增的类型,byte表示字节,加个复数形式就当做串了。跟字符串类似,也是一串的内容,但是是以二进制来存储的。二进制可以用于网络传输数据,也可以存储各种二进制文件,如图片、音乐、视频、exe应用程序等。
|
||||||
|
|
||||||
|
字符串和字节串之间也可以相互转换,即把字符串弄成二进制表示了,后续更利于传输或者针对里面的内容更好的进行文本加密或解密,或编码,在这块更加方便一些。
|
||||||
|
|
||||||
|
有关字节串我们就不讲那么详细了,感兴趣的同学可以自行百度下相关知识,我们来看点简单的例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 将字符串转为bytes类型,用utf8编码,不指定默认也是这个
|
||||||
|
a = b'Hello' # 这种方式只能支持仅含ascii字符的字符串,含有中文会报错
|
||||||
|
print(a)
|
||||||
|
# 后面这两种方式结果一致,等效,爱用哪个用哪个
|
||||||
|
a = bytes("Hello 小白", encoding='utf-8')
|
||||||
|
print(a)
|
||||||
|
a = "Hello 小白".encode('utf-8')
|
||||||
|
print(a)
|
||||||
|
# 将字节串解码回字符串,用utf8编码,不指定默认也是这个
|
||||||
|
b = a.decode("utf-8")
|
||||||
|
print(b)
|
||||||
|
# 也可以这样解码,还是爱用哪个用哪个
|
||||||
|
b = bytes.decode(a, encoding="utf-8")
|
||||||
|
print(b)
|
||||||
|
```
|
||||||
|
|
||||||
|
可以注意到字节串打印输出的时候前面有一个b开头修饰,并且二进制内容在遇到非ascii字符时可能会用十六进制表示法来表示并打印出来。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| -------- | ------------------------------------------------- |
|
||||||
|
| bytes | 字节的复数形式,在python中翻译为字节串型 |
|
||||||
|
| encoding | 编码,encode的ing形式,encode为编码这个单词的原型 |
|
||||||
|
| decode | 解码 |
|
||||||
236
chapter2/2-9 python3小白课:字符串进阶.md
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
# python3小白课:字符串进阶
|
||||||
|
|
||||||
|
之前我们学习了python字符串的入门知识,它们内容不少,不知道大家消化得怎么样了呢?
|
||||||
|
|
||||||
|
这节课我们来学习一些字符串的进阶知识,掌握好本节课的内容,对你高效的使用字符串帮助颇大,我们依然提取最精练的内容传授给大家。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 转义字符
|
||||||
|
|
||||||
|
之前我们讲解过`\`符号可以作为转义字符。除了之前教学的场景之外,python还能支持一些其他的转义符,我们来列举常用的一些:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# \n表示换行符,比较常用到
|
||||||
|
a = "我是第一行\n我是第二行"
|
||||||
|
print(a)
|
||||||
|
# 当我们要循环打出一段字符串的时候,不需要写多遍,用*号,后面加上重复的次数即可,比如这里打印40个*号
|
||||||
|
print("*" * 40)
|
||||||
|
# \t表示制表符,类似你键盘上的Tab键的距离
|
||||||
|
b = "我是第一行\t我是第二行"
|
||||||
|
print(b)
|
||||||
|
```
|
||||||
|
|
||||||
|
上面的例子包含的知识点挺多哦,好好学习下。
|
||||||
|
|
||||||
|
其他还有一些自带支持的转义符我们就不一一列举了,感兴趣的同学可以自行找下资料。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 格式化字符串
|
||||||
|
|
||||||
|
还记得我们入门的时候,使用的是`+`号的方法把字符串联结起来,当遇到不同类型的数据的时候,我们需要把数据先转换成字符串型。这样有几点不便,其中的一点是,当字符串中的变量太多,需要写多个+号来联结,另一点是要经常关注数据类型,容易报错等。
|
||||||
|
|
||||||
|
这时候,我们更常用更常见的神器,格式化字符串,来了!
|
||||||
|
|
||||||
|
先来看下例子感受一下,我用了日常编程中更为常见的转换说明符来写:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = "我的名字是%s,我的年龄是%d。\n我知道,π的值为%.2f" % ("小白", 18, 3.1415926)
|
||||||
|
print(a)
|
||||||
|
b = "现在你在【%s】学习python小白课呢~" % "雪山凌狐教程"
|
||||||
|
print(b)
|
||||||
|
```
|
||||||
|
|
||||||
|
来我们来看一下,这两句示例代码都先用字符串定义了一串的内容,空格之后跟了一个`%`符号,再空格之后,对应的写入了一些内容,有的用括号括起来了,有的没用,对吧?
|
||||||
|
|
||||||
|
那么我们首先看一下第一部分的字符串内容,通过对比输出结果,我们可以看到,我们在字符串中也有`%`号,并且后面跟了一些字母等内容。接下来我们就来解释一下我们用到的几个转换说明符:
|
||||||
|
|
||||||
|
| 转换说明符 | 说明 |
|
||||||
|
| ---------- | ------------------------------------------------------------ |
|
||||||
|
| %s | 将内容(变量或者表达式)用str命令转换为字符串 |
|
||||||
|
| %d | 转换为带符号的十进制形式的整数 |
|
||||||
|
| %f | 转换为十进制形式的浮点数,.num表示保留小数点后面num位,如果给的值不够这个num大,则会补位 |
|
||||||
|
|
||||||
|
其他一些转换说明符还有,不过掌握几个常见的日常也基本够用了,这样大家记忆起来就不费力。如果你对其他的说明符感兴趣,可以自行查阅资料。
|
||||||
|
|
||||||
|
然后接下来是一个固定的`%`符号作为分隔符。
|
||||||
|
|
||||||
|
最后就是我们的内容了,内容可以直接写值也可以支持变量或者表达式的形式。如果前面的字符串定义了多个,需要用逗号`,`隔开,并且外面套上小括号,需要注意的是,前面定义了几个,后面就给几个,不要数量不正确,否则会报错哦。如果只定义了一个,那么直接写它就可以了。将一些内容用小括号括起来,在python中叫做`元组(tuple)`。有关元组的知识后面我们会另外再重点讲解,你稍微知道一下即可。
|
||||||
|
|
||||||
|
怎么样?是不是很方便?+号是不是少写了很多?
|
||||||
|
|
||||||
|
### format函数
|
||||||
|
|
||||||
|
这也是实战中用得比较多的格式化字符串的方法,我们来看个简单的例子就懂了:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# format函数的参数中,可以带上参数名,可以不按顺序,如果不带参数名,就必须按顺序给值
|
||||||
|
a = "我的名字是{name},我的年龄是{age}".format(age=18, name="小白")
|
||||||
|
print(a)
|
||||||
|
# 也可以这样写和定义
|
||||||
|
a = "我的名字是{},我的年龄是{}".format("小白", 98)
|
||||||
|
print(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
很简单,会了吗?用上`{}`大括号即可。
|
||||||
|
|
||||||
|
### f-string
|
||||||
|
|
||||||
|
上述的格式化方法是过去的版本python一直都有的,我们这里补充讲解一下据说是python3.6版本以上才新加的东东——`f-string`,让我们也来潮流一把。它可能比format函数更加顺畅哦。
|
||||||
|
|
||||||
|
`f-string`,亦称为格式化字符串常量(formatted string literals),是Python3.6新引入的一种字符串格式化方法,主要目的是使格式化字符串的操作更加简便。
|
||||||
|
|
||||||
|
来我们直接看例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
name = "小白"
|
||||||
|
age = 18
|
||||||
|
a = f"我的名字是{name},我的年龄是{age}"
|
||||||
|
print(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
其实在这里,大括号的作用是一个python表达式,你还可以在大括号里面写表达式的。基础使用我们就讲到这里吧,它的强大之处远远不止这些,如果你想深入了解,百度一下`f-string`即可得到很多你想要的答案了。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 字符串索引及相关方法
|
||||||
|
|
||||||
|
很多时候,我们仅需要取出一串字符串中的某些个内容,那么如何取出呢?这里我们来介绍一下索引的概念。
|
||||||
|
|
||||||
|
比如我们定义一个最简单的字符串:`a = "hello"`。
|
||||||
|
|
||||||
|
如果你算术够好,肯定能掰出五个手指头告诉我这里有**5**个字母。那么我们可以给他们每个字母编制一个索引。
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> 在python中,索引从**0**开始,务必记住!是0!不是1!很多编程语言的索引都从0开始(个别从1开始索引),这对于我们日常说一楼就是一楼的人有点难抽象出来,但定义如此,请你死记硬背好~
|
||||||
|
|
||||||
|
所以,我们的五个字母的索引分别为:`0, 1, 2, 3, 4`。
|
||||||
|
|
||||||
|
我们用`[]`中括号表示索引,如果需要取出字母e,我们可以这样表示:`print(a[1])`
|
||||||
|
|
||||||
|
我们还可以有其他写法,看例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = "hello"
|
||||||
|
# 我们有如下索引对应关系:
|
||||||
|
# [h -> 0], [e -> 1], [l -> 2], [l -> 3], [o -> 4]
|
||||||
|
print(a[1])
|
||||||
|
# 取出从右边开始第1个字符
|
||||||
|
print(a[-1])
|
||||||
|
# 取出索引从2到4(不含4)的字符(即索引2~3的字符),注意写冒号的话永远是包含头索引不包含尾索引
|
||||||
|
print(a[2:4])
|
||||||
|
# 取出倒数第3到倒数第1(不包含倒数第1)的字符串(不能反过来写哦)
|
||||||
|
print(a[-3:-1])
|
||||||
|
# 取出索引为2之后的所有字符串
|
||||||
|
print(a[2:])
|
||||||
|
# 取出索引为1(不包含1)之前的所有字符串
|
||||||
|
print(a[:1])
|
||||||
|
# 用in运算符判断某字符串在不在原字符串里面,在返回True真,不在返回False假,这个布尔型我们之前讲过
|
||||||
|
print("lo" in a)
|
||||||
|
# 获取字符的总长度,可以使用len函数
|
||||||
|
print(len(a))
|
||||||
|
# 经过测试,对于中文字符串,它的数数也是按照英文字符串那样来数的,你可以自行深入测试
|
||||||
|
b = "我是小白little bai"
|
||||||
|
print(b[1])
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
### 字符串str类型自带的一些内置方法
|
||||||
|
|
||||||
|
字符串还有一些它内置的方法,让我们处理起字符串来可以得心应手。
|
||||||
|
|
||||||
|
我们可以通过`dir(str)`命令查看内置的方法有哪些,dir命令也能查看其它类的内置方法,这个大家可以自己探索下。运行后,会返回一个命令列表(list),关于列表的知识我们在后面的课程中会详细的讲解,大家稍微知道一下中括号括起来的是一个列表就可以了。
|
||||||
|
|
||||||
|
我这里运行结果如下:
|
||||||
|
|
||||||
|
```python
|
||||||
|
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> 方法有很多,其中我们注意到有很多方法开头结尾都有`__`双下划线符号,这些命令为python系统定义的名字,是特殊方法专用的标识,请不要自己随意定义这类命令。
|
||||||
|
|
||||||
|
剩下的那些就是内置类方法啦,里面太多了,如果你感兴趣,可以使用我们学过的help命令来查看帮助文档哦。我们来挑一些重点的来写示例讲解:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 大小写相关方法
|
||||||
|
a = "my name is liTTle bai 小白"
|
||||||
|
# title方法,将每个单词首字母改为大写
|
||||||
|
print(a.title())
|
||||||
|
# lower方法,将每个字母改为小写。比如在比较文件后缀名时十分有用
|
||||||
|
print(a.lower())
|
||||||
|
# upper方法,将每个字母改为大写
|
||||||
|
print(a.upper())
|
||||||
|
|
||||||
|
# 删除空白相关方法,空格,制表符等都可以
|
||||||
|
b = " my name is liTTle bai 小白 "
|
||||||
|
# strip方法,删除首尾的空白
|
||||||
|
print(b.strip())
|
||||||
|
# lstrip方法,删除左边left的空白
|
||||||
|
print(b.lstrip())
|
||||||
|
# rstrip方法,删除右边right的空白
|
||||||
|
print(b.rstrip())
|
||||||
|
# 补充一句,这些方法有时候是可以嵌套的,不用写多行来处理,比如先变小写再删首尾空
|
||||||
|
print(b.lower().strip())
|
||||||
|
|
||||||
|
# 查找替换相关方法
|
||||||
|
c = "my name is little bai 小白"
|
||||||
|
# startswith方法,判断字符串是不是以传入的参数开头,会返回布尔型返回值真或假
|
||||||
|
print(c.startswith("my"))
|
||||||
|
# endswith方法,判断字符串是不是以传入的参数结尾,会返回布尔型返回值真或假
|
||||||
|
print(c.endswith("bai"))
|
||||||
|
# find方法,获取参数在字符串中出现的位置索引,没有找到返回-1
|
||||||
|
print(c.find("is"))
|
||||||
|
# replace方法,将字符串中的某些内容(如有),替换成别的内容
|
||||||
|
print(c.replace("小白", "小黑"))
|
||||||
|
|
||||||
|
# 分割、连接方法
|
||||||
|
# split方法,将字符串按照指定的分割符分割文本,默认分割符(如果不写)为空格(可以是多个空格)
|
||||||
|
d = "my name is liTTle bai 小白" # 出来的结果是一个列表list,后面我们可以再做详细讲解如何后续处理
|
||||||
|
print(d.split())
|
||||||
|
# join方法,刚才分割的反向操作,把一个列表的每个元素(列表中逗号分隔开的一个个称作元素)
|
||||||
|
# 按照指定的连接符(比如点号.)连接起来
|
||||||
|
print(".".join(d.split()))
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
说了这么多,可能大家都已经有些晕晕乎乎的了。不过没关系,本节课值得大家细细品味,如果一遍没有掌握,请多回来看几遍,记住常用的那些命令的单词,当你需要的时候就很容易了,它们的使用都是相当简单的。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------------------------- | ------------------------------------------- |
|
||||||
|
| Tab | 这里指键盘上的Tab键,会输出一个制表符\t |
|
||||||
|
| num | number数字的简写 |
|
||||||
|
| tuple | 元组 |
|
||||||
|
| format | 格式化 |
|
||||||
|
| formatted string literals | 格式化字符串常量 |
|
||||||
|
| dir | 全称为directory,你可以理解为目录,罗列出来 |
|
||||||
|
| list | 列表 |
|
||||||
|
| in | 在...里面 |
|
||||||
|
| len | length长度的简洁写法,这里是一个命令名 |
|
||||||
|
| title | 标题,这里是一个命令名 |
|
||||||
|
| lower | 下面的 |
|
||||||
|
| upper | 上面的 |
|
||||||
|
| strip | 除去,剥去 |
|
||||||
|
| lstrip | 应该是left strip的简写,left为左边 |
|
||||||
|
| rstrip | 应该是right strip的简写,right为右边 |
|
||||||
|
| startswith | start开始,with结合上下文理解为跟着啥 |
|
||||||
|
| endswith | end结束,with结合上下文理解为跟着啥 |
|
||||||
|
| find | 寻找 |
|
||||||
|
| replace | 替换 |
|
||||||
|
| split | 分割,分裂 |
|
||||||
|
| join | 连接,加入 |
|
||||||
|
|
||||||
5
chapter2/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# 二、变量、简单类型和运算符
|
||||||
|
|
||||||
|
本章节开始介绍一些python的基本概念、类型等,学习完本章节,你已经有了许多基础的工具可以在未来使用啦!
|
||||||
|
|
||||||
|
本章节会跟大家介绍:变量、常量、注释、数值类型、字符串、字节串、运算符等等内容。
|
||||||
40
chapter3/3-1 python3小白课:列表和元组的区别.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# python3小白课:列表和元组的区别
|
||||||
|
|
||||||
|
### python的序列
|
||||||
|
|
||||||
|
python中可以称之为序列的有字符串、列表(list)、元组(tuple)等。它们都可以通过索引来获取其中的成员内容,比如字符串也可以打散成多个字母,对吧?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 列表和元组的区别
|
||||||
|
|
||||||
|
列表和元组是一对兄弟,它们非常相像,我们来尝试定义一下:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 定义列表
|
||||||
|
a = [1, 2, 4]
|
||||||
|
# 定义元组
|
||||||
|
b = (1, 2, 4)
|
||||||
|
```
|
||||||
|
|
||||||
|
上述所示的代码为很简单的定义列表和元组的方法,我们可以观察到,他们的区别在于列表用的是`[]`,而元组用的是`()`来定义。内部可能有许多个元素,每个元素之间使用逗号`,`来分隔。
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 那么好像乍看起来除了用的符号框起来不一样,没啥不同呀?为什么有两种数据类型呢?
|
||||||
|
|
||||||
|
因为,列表是一种可变序列,即在定义后,你还可以往里面添加成员,减少成员等操作。但元组就不一样了,元组打从定义之后,就不允许增减,只允许读取和使用了。
|
||||||
|
|
||||||
|
所以大家应该看明白了,它们就是可变和不可变的关系。在实际编程当中,我们需要根据我们的需要来选择合适的序列使用,需要增减成员时用列表,如果确定不变的成员,并且也不允许做外部修改的的时候,用元组。
|
||||||
|
|
||||||
|
关于这两个数据类型的自带命令函数,如果不涉及成员增减的,那么它们经常都拥有这样的方法,但如果涉及成员增减的,应该说只有列表才有。从这个角度来看,你也可以认为列表是元组的增强版。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ----- | ---- |
|
||||||
|
| list | 列表 |
|
||||||
|
| tuple | 元组 |
|
||||||
109
chapter3/3-2 python3小白课:列表元组入门.md
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
# python3小白课:列表元组入门
|
||||||
|
|
||||||
|
上节课我们知道了列表元组之间是可变和不可变的关系,其他十分类似,因此我们在学习的时候可以一起学习进行类比。举一反三,这样大家掌握得比较快。
|
||||||
|
|
||||||
|
我们直接就着代码来进行学习吧:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 简单定义列表、元组,里面的元素可以是各种基础的数据类型,同一个列表、元组中可以多种类型混合
|
||||||
|
a = [1, "小白", None]
|
||||||
|
b = (1, "小白", None)
|
||||||
|
# 除了这种定义方法,还能使用关键字命令生成列表或元组,常用来转换
|
||||||
|
aa = list(b)
|
||||||
|
bb = tuple(a)
|
||||||
|
print(aa, bb)
|
||||||
|
print(list(), tuple(), [], ()) # 多种方法快速生成空的列表或元组
|
||||||
|
# 可以通过索引进行访问,还是用到[],跟之前字符串基本是类似的,取出来的称为子序列
|
||||||
|
print(a[0])
|
||||||
|
print(b[-2])
|
||||||
|
print(a[1:])
|
||||||
|
print(b[0:2:2])
|
||||||
|
# 列表之间、元组之间可以相加变成新序列,但不能列表+元组
|
||||||
|
print(a + [2])
|
||||||
|
# 当一个元组只有一个元素的时候,需要在结尾多写一个逗号,否则不能视为元组,这是规定:(2,)
|
||||||
|
# 如果写(2),它等价于数字2,要变成元组必须加上,
|
||||||
|
print((2) == 2) # 你可以这样测试
|
||||||
|
print(b + (2,))
|
||||||
|
# 列表和元组还支持乘法,可以让列表或元组重复n次
|
||||||
|
print(a * 3)
|
||||||
|
print(b * 4)
|
||||||
|
# 使用in运算符可以查看某元素在不在列表或元组中,这个我们已经学过
|
||||||
|
print(1 in a)
|
||||||
|
print(None in b)
|
||||||
|
# len函数可以查看列表或元组有多少个元素
|
||||||
|
print(len(a), len(b))
|
||||||
|
# max、min函数可以获取列表或元组中的最大或最小值,但需要元素是相同类型且可以比较大小才行
|
||||||
|
c = [3, 2, 9, 12, 30]
|
||||||
|
d = ("apple", "banana", "color", "zoo") # 如果是字符串,会进行字母比较
|
||||||
|
print(max(c), min(c))
|
||||||
|
print(max(d), min(d))
|
||||||
|
|
||||||
|
"""
|
||||||
|
python支持序列封包(Sequence Packing)和序列解包(Sequence Unpacking)的功能
|
||||||
|
序列封包:把多个值赋值给一个变量时,会自动将多个值封装为一个元组
|
||||||
|
序列解包:可以将列表和元组赋值给多个变量,这样元素会被依次赋值给每个变量
|
||||||
|
我们来看一下代码示例:
|
||||||
|
"""
|
||||||
|
# 序列封包
|
||||||
|
a = 1, 4, 8
|
||||||
|
print(a, type(a))
|
||||||
|
# 序列解包
|
||||||
|
a, b, c = [1, 2, 3]
|
||||||
|
d, e, f = (4, 5, 6)
|
||||||
|
print(a, b, c)
|
||||||
|
print(d, e, f)
|
||||||
|
# 在变量名左侧加上*号,这个变量就可以表示一个列表,支持在解包时存入列表
|
||||||
|
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
|
# 第一、第二个元素分别赋值给a1,a2,剩下的元素赋值给a3
|
||||||
|
a1, a2, *a3 = a
|
||||||
|
print(a1, a2, a3, sep="|")
|
||||||
|
# 同理也有如下写法,啥意思呢?效果可以自行测试
|
||||||
|
a1, *a2, a3 = a
|
||||||
|
print(a1, a2, a3, sep="|")
|
||||||
|
*a1, a2, a3 = a
|
||||||
|
print(a1, a2, a3, sep="|")
|
||||||
|
```
|
||||||
|
|
||||||
|
通过上面的学习,大家是不是对列表、元组的初步使用有了一个更深刻的认识呢?希望里面涉及的简单例子大家都自己跑一跑,保证自己能够理解和记忆。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### range函数
|
||||||
|
|
||||||
|
range函数是一个生成列表很重要的函数,通常会用在for循环的流程控制当中,关于流程控制,后面的课程我们将会有更加详细的讲解。
|
||||||
|
|
||||||
|
range函数经历了一些演变,我们只需要记忆python3中的概念就好,在python3中,range函数返回一个range对象。可以被遍历(遍历的知识我们在后面再详细讲解),也可以转换成列表或者元组,这里我们来讲讲转换吧。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# range支持1~3个参数传入,跟[]索引一样,分别表示开始、结束(不包含)、步长
|
||||||
|
# 我们可以通过list()函数转化为列表输出查看结果,如果要转成元组,使用tuple()转即可,不再赘述
|
||||||
|
print(list(range(10)))
|
||||||
|
print(len(range(10)))
|
||||||
|
print(list(range(1, 10)))
|
||||||
|
print(list(range(1, 10, 2)))
|
||||||
|
# 步长如果不传,默认为1,如果序列是逆向的,则需要传入负的步长
|
||||||
|
print(list(range(1, -10, -1)))
|
||||||
|
print(list(range(1, -10, -2)))
|
||||||
|
```
|
||||||
|
|
||||||
|
关于range的知识,大家需要先行了解,然后熟练掌握,后续我们做循环流程控制的时候,它是一种重要的手段。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------------------ | ------------------------------------------ |
|
||||||
|
| list | 列表 |
|
||||||
|
| tuple | 元组 |
|
||||||
|
| apple | 苹果 |
|
||||||
|
| banana | 香蕉 |
|
||||||
|
| color | 颜色 |
|
||||||
|
| zoo | 动物园 |
|
||||||
|
| max | 最大值 |
|
||||||
|
| min | 最小值 |
|
||||||
|
| Sequence Packing | 序列封包 |
|
||||||
|
| Sequence Unpacking | 序列解包 |
|
||||||
|
| range | 一系列,范围,区间,可以理解为生成区间序列 |
|
||||||
137
chapter3/3-3 python3小白课:深入列表.md
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
# python3小白课:深入列表
|
||||||
|
|
||||||
|
我们在前面的课程中已经初步了解了列表和元组的相关知识。
|
||||||
|
|
||||||
|
我们也知道,列表还有元组没有的增删成员等功能。因此,本节课我们再来深入了解一下列表特有的一些知识点吧。
|
||||||
|
|
||||||
|
直接上代码例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 增加列表元素,最最常用。列表有点像其他编程语言中所说的数组,但它支持多种类型的元素
|
||||||
|
# 很常用的一个场景是先定义一个空列表,后续把需要存储的成员一个个存进列表去
|
||||||
|
# 使用append方法可以将元素添加到列表中,这么写:
|
||||||
|
a = []
|
||||||
|
a.append("小白")
|
||||||
|
print(a)
|
||||||
|
# 也支持增加列表、元组等等序列类型作为单个成员,可以实现列表嵌套列表或元组等的效果
|
||||||
|
a.append((1, 2, 3))
|
||||||
|
print(a, len(a))
|
||||||
|
# 如果是要追加一个列表而不是加个列表元素呢?使用extend方法
|
||||||
|
a.extend(["apple", "banana"])
|
||||||
|
print(a, len(a))
|
||||||
|
# 刚才都是添加到列表尾部的,如果希望在中间插入元素呢?使用insert方法即可,需要指定插入位置的索引
|
||||||
|
a.insert(1, "我是插入的元素")
|
||||||
|
print(a)
|
||||||
|
|
||||||
|
# 删除列表元素
|
||||||
|
# 使用del语句,可以删除列表元素、列表子序列,还能删除变量呢
|
||||||
|
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
|
del a[1]
|
||||||
|
print(a)
|
||||||
|
del a[4:]
|
||||||
|
print(a)
|
||||||
|
# 删除变量是del命令带的功能,删除后再打印,会报错。但我们很少做这样的操作,你可以不掌握
|
||||||
|
name = "小白"
|
||||||
|
del name
|
||||||
|
print(name) # 这句会报错
|
||||||
|
# 你还可以使用remove方法来删除元素,它不根据索引删除,根据的是元素本身删除,如果找不到会报错
|
||||||
|
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
|
a.remove(4)
|
||||||
|
print(a)
|
||||||
|
a.remove(11) # 这里找不到,会报错
|
||||||
|
print(a)
|
||||||
|
# 如果你需要清空列表,将列表变回空列表,可以使用clear方法
|
||||||
|
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
|
a.clear()
|
||||||
|
print(a)
|
||||||
|
# 后面在修改元素列表的部分我们还有一种可以删除元素的方法,也是很好用的↓↓↓
|
||||||
|
|
||||||
|
# 修改列表元素
|
||||||
|
# 可以直接通过索引获取需要修改的元素来修改
|
||||||
|
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
|
a[1] = "啊哦,我被修改啦~"
|
||||||
|
print(a)
|
||||||
|
# 也可以通过索引的各种方法修改列表,也支持步长等修改
|
||||||
|
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
|
# 这里我们取出了两个元素,却给赋值三个元素,这样相当于删除两个,再插入三个,也是可以的
|
||||||
|
a[1:3] = ["修改1", "修改2", "修改3"]
|
||||||
|
print(a)
|
||||||
|
# 赋值为空列表,还能做到删除元素的功效,这也是一种便捷的删除元素的做法
|
||||||
|
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
|
a[1:3] = []
|
||||||
|
print(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 列表的一些其他常用方法
|
||||||
|
|
||||||
|
列表还有一些其他的常用方法,如果你有需要可以使用,大致了解即可,有需要时可以查资料
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 你可以查看有哪些内置方法,注意剔除私有方法和特殊方法
|
||||||
|
print(dir(list))
|
||||||
|
# count方法可以统计列表中某个元素出现的次数
|
||||||
|
a = [1, 2, 3, 4, 5, [5, 6, 7], 7, 8, 9, 10]
|
||||||
|
print(a.count(5))
|
||||||
|
# index方法判断某个元素在列表中出现的位置,可以在第二第三个参数中指定搜索的范围,找不到会报错
|
||||||
|
print(a.index(4, 2, 3))
|
||||||
|
# pop方法可以提供元素出栈功能,实现元素的先入后出,append方法是python中的类似入栈(push)的功能
|
||||||
|
# 使用pop方法可以将列表中最后一个元素移出栈,你可以简单理解为删除最后一个元素
|
||||||
|
print(a.pop()) # 会返回那个被移出栈的元素
|
||||||
|
print(a)
|
||||||
|
# reverse方法可以将元素反转,比如一堆数字,可以实现倒序排列的效果
|
||||||
|
a.reverse()
|
||||||
|
print(a)
|
||||||
|
# sort方法可以对元素进行排列
|
||||||
|
# 支持传入key、reverse两个参数,key参数可以指定生成比较大小的键
|
||||||
|
# reverse参数为布尔型,默认为False,从小到大排序,传入True则从大到小排列
|
||||||
|
a = ["12345", [5, 6, 7], "little bai"]
|
||||||
|
# key传入len方法,注意没有括号,会计算每个元素的长度,再倒序排列,注意必须每个元素都支持len方法
|
||||||
|
a.sort(key=len, reverse=True)
|
||||||
|
print(a)
|
||||||
|
# 也可以做数字排序
|
||||||
|
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
|
a.sort(reverse=True)
|
||||||
|
print(a)
|
||||||
|
|
||||||
|
# 上述讲的排序方法需要改变列表本身的顺序,如果我只想排序不想改变呢?
|
||||||
|
# 复制一个新列表,将新列表进行排序是一个办法,还有其他办法吗?
|
||||||
|
# reversed函数可以倒序列表,生成可迭代对象,可以转化为列表展示。但不会改变原列表
|
||||||
|
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
|
print(list(reversed(a)))
|
||||||
|
print(a)
|
||||||
|
# sorted函数可以排序列表,也不会改变原列表,还支持参数
|
||||||
|
b = [2, 1, 3, 4, 5, 8, 7, 6, 9, 10]
|
||||||
|
print(sorted(b))
|
||||||
|
# 这个也行,这样看来它可以替代reversed函数,但要写个参数,看个人方便吧
|
||||||
|
print(sorted(b, reverse=True))
|
||||||
|
print(b)
|
||||||
|
# key参数也可以传入一个自己定义的函数,返回排序序号啥的,关于自己定义函数,我们将在后面讲到
|
||||||
|
c = ["12345", [5, 6, 7], "little bai"]
|
||||||
|
print(sorted(c, reverse=True, key=len))
|
||||||
|
print(c)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ---------------- | ---------------------------------------------------------- |
|
||||||
|
| append | 附加,增补 |
|
||||||
|
| extend | 扩展 |
|
||||||
|
| insert | 插入 |
|
||||||
|
| del | delete删除这个单词的简写 |
|
||||||
|
| remove | 拿开,去除 |
|
||||||
|
| clear | 清除,清理 |
|
||||||
|
| count | 计数 |
|
||||||
|
| index | 索引 |
|
||||||
|
| Sequence Packing | 突然地出现,突然地伸出,这是理解为出栈命令 |
|
||||||
|
| push | 推,推进去,这里理解为入栈命令,其他语言可能有push这个命令 |
|
||||||
|
| reverse | 颠倒,使反转,reversed为这个单词的过去式,意思为已反转的 |
|
||||||
|
| sort | 排序,sorted为这个单词的过去式,意思为已排序的 |
|
||||||
|
| key | 关键,钥匙,键 |
|
||||||
|
|
||||||
89
chapter3/3-4 python3小白课:字典初识.md
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
# python3小白课:字典初识
|
||||||
|
|
||||||
|
### 字典的引入
|
||||||
|
|
||||||
|
这节课让我们来接触一个全新的数据类型——字典(dict)。
|
||||||
|
|
||||||
|
小时候陪伴我们成长的我想肯定是一本总是被翻烂的新华字典吧。字典,存在对应映射关系,你拿着一本英汉大字典,查询某个单词,就能查到对应的释义中文解释是什么。那么在python中的字典就类似这样的映射关系。
|
||||||
|
|
||||||
|
它同样可以存储很多的数据内容,但跟我们的列表、元素不同的是,它的内部是不存在顺序的,所以我们不能使用中括号的数字索引来获取字典元素值。
|
||||||
|
|
||||||
|
为什么会有字典呢?大家可以这么想,你在查英汉字典的时候,会有如下对应关系:
|
||||||
|
|
||||||
|
`apple -> 苹果`
|
||||||
|
|
||||||
|
`banana -> 香蕉`
|
||||||
|
|
||||||
|
如果我们是用列表或者元组来存储这样的对应关系,一种比较不错的方式是弄两个列表或元组,通过索引来进行一一对应。但这显然不是一种最优的方案。这时候,我们可以使用字典,字典通过`键值对`的方式来做一一对应的映射关系,都存在一个字典变量里面,可以达到这样的效果(注意这里不是真的python代码):
|
||||||
|
|
||||||
|
```python
|
||||||
|
a = {
|
||||||
|
apple -> 苹果
|
||||||
|
banana -> 香蕉
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
这里的英文单词就是字典中的`键(key)`,中文释义就是字典中的`值(value)`。它们组成key-value键值对。而且在内部没有顺序,比如你先定义banana这个键值对,跟先定义apple并没有任何区别。
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> 我们可以通过键来获取值,所以在python的字典中,键不允许重复。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 创建字典
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 那么在python中,如何定义字典呢?
|
||||||
|
|
||||||
|
我们来看看下面的代码:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 通过dict命令定义字典或{}定义字典,可以定义空字典
|
||||||
|
a = {} # 这种方式较常用
|
||||||
|
print(dict(), a)
|
||||||
|
# 可以这么写来定义,多个字典成员之间用逗号分隔,值可以是各种基础数据类型
|
||||||
|
a = {"语文": 90, "数学": 89, "计算机": None}
|
||||||
|
print(a)
|
||||||
|
# 对于字典,python还支持跨行定义,这样看起来比较美观,实际使用时也比较推荐
|
||||||
|
a = {
|
||||||
|
"语文": 90,
|
||||||
|
"数学": 89,
|
||||||
|
"计算机": 100
|
||||||
|
}
|
||||||
|
print(a)
|
||||||
|
# 不可变类型可以作为key,比如数字、元组等,不能是列表为key(思考为什么?)。看个例子:
|
||||||
|
# 这里我们用了三种类型的数据作为键,看起来相似,但实际不同
|
||||||
|
a = {
|
||||||
|
1: 90,
|
||||||
|
"1": 89,
|
||||||
|
(1,): 100
|
||||||
|
}
|
||||||
|
print(a)
|
||||||
|
|
||||||
|
# python还支持通过传入列表或元组创建dict,每个元素是一个键值对,比如:
|
||||||
|
a = [("语文", 90), ("数学", 89), ("计算机", None)]
|
||||||
|
print(dict(a))
|
||||||
|
a = [["语文", 90], ["数学", 89], ["计算机", None]]
|
||||||
|
print(dict(a))
|
||||||
|
|
||||||
|
# 还可以通过dict命令的关键字参数创建dict,此时关键字不用加引号,键会是字符串(大多数时候都是字符串键)
|
||||||
|
a = dict(语文=90, 数学=100)
|
||||||
|
print(a)
|
||||||
|
# 这种方式不支持关键字用元组哦~,会报错
|
||||||
|
a = dict((1,2,3)=90, bbb=100)
|
||||||
|
print(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ----- | ---------------------------- |
|
||||||
|
| dict | dictionary字典单词的简写形式 |
|
||||||
|
| key | 键 |
|
||||||
|
| value | 值 |
|
||||||
|
|
||||||
50
chapter3/3-5 python3小白课:字典操作基础.md
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# python3小白课:字典操作基础
|
||||||
|
|
||||||
|
字典中的键(key)是字典中的关键,各种基础操作是围绕key来进行的。
|
||||||
|
|
||||||
|
我们来看一些例子代码:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 访问字典的值,还记得列表元组使用[]加上索引来访问值吗,字典在中括号中加上键即可访问值
|
||||||
|
a = {
|
||||||
|
1: 90,
|
||||||
|
"1": 89,
|
||||||
|
(1,): 100
|
||||||
|
}
|
||||||
|
print(a[(1,)])
|
||||||
|
# 我们可以随意添加不存在的键值对
|
||||||
|
a["语文"] = 100
|
||||||
|
print(a)
|
||||||
|
# 如果上述语句所对应的键在字典中已经存在,就能对键值对修改它的值,很方便
|
||||||
|
a["语文"] = 88
|
||||||
|
print(a)
|
||||||
|
# 如果要删除某个键值对,可以使用del命令,但如果该键不存在会报错
|
||||||
|
del a["语文"]
|
||||||
|
print(a)
|
||||||
|
# 可以用in或者not in判断某个键(注意是键,不是值)在不在字典中,返回布尔值结果
|
||||||
|
print("语文" in a)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 字典用于格式化字符串
|
||||||
|
|
||||||
|
我们在讲字符串的章节学习过许多格式化字符串的方法,我们还记得是通过对应关系,将所需要的的值批量罗列格式化到字符串中,但这种方式只有两三个还好,如果有多个需要格式化的值内容,可能需要写很长的一串代码,有了字典,我们可以再度升华一下这种格式化的方式。
|
||||||
|
|
||||||
|
如下例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = {
|
||||||
|
"语文": 90,
|
||||||
|
"数学": 89,
|
||||||
|
"计算机": 100,
|
||||||
|
"英语": 89.57
|
||||||
|
}
|
||||||
|
# 还支持保留1位小数,注意这里不一定是四舍五入,比如英语成绩你设置为89.55试试?
|
||||||
|
# 这是python内存储机制的原因,我们可以不深究
|
||||||
|
b = "语文的分数是:%(语文)s,英语的分数为%(英语).1f" % a
|
||||||
|
print(b)
|
||||||
|
```
|
||||||
|
|
||||||
101
chapter3/3-6 python3小白课:字典的常用方法.md
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
# python3小白课:字典的常用方法
|
||||||
|
|
||||||
|
本节课我们来大概将一些字典自带的常用方法。
|
||||||
|
|
||||||
|
看例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 查看有哪些内置方法?(注意忽略私有方法和特殊方法)
|
||||||
|
print(dir(dict))
|
||||||
|
a = {
|
||||||
|
1: 90,
|
||||||
|
"1": 89,
|
||||||
|
(1,): 100,
|
||||||
|
"语文": 90,
|
||||||
|
"数学": 89,
|
||||||
|
"计算机": 100,
|
||||||
|
"英语": 89.57
|
||||||
|
}
|
||||||
|
# clear,跟列表元组一样,会将字典变为空字典,copy方法可以复制一个字典副本
|
||||||
|
# 注意不要用b = a这样的写法,这样写clear b时,a也会变空字典
|
||||||
|
b = a.copy()
|
||||||
|
b.clear()
|
||||||
|
print(b)
|
||||||
|
# get方法非常非常常用,用来取字典中某个键的值,使用[]取值如果键不存在会报错,但get方法取值不存在时,
|
||||||
|
# 会返回None,或者可以指定第二个参数作为返回值。因此,实际编写中更推荐用get而弃用[],除非你百分百保证存在该键
|
||||||
|
print(a.get("语文"))
|
||||||
|
print(a.get("美术"))
|
||||||
|
# 你也可以指定返回值
|
||||||
|
print(a.get("美术", 1))
|
||||||
|
# 我们需要区别于setdefault方法,这个方法可以设置一个键的默认值,当这个键找得到时,与get等效,返回值
|
||||||
|
# 但当这个键不存在时,setdefault会给字典新增这个键并赋值给的默认值,而get不会新增键
|
||||||
|
print(a.setdefault("美术", 99)) # 键不存在,返回设定的第二个参数并添加键到字典中
|
||||||
|
print(a)
|
||||||
|
print(a.setdefault("美术", 98)) # 这次键存在,因此不会修改它的值,可以返回
|
||||||
|
print(a)
|
||||||
|
# update方法可以用新字典包含的键值对来更新原有字典,当原有字典存在该键时,则更新
|
||||||
|
# 当原有字典不存在对应键时,则添加该键值对进去
|
||||||
|
a.update({"语文":0, "体育": 92})
|
||||||
|
print(a)
|
||||||
|
|
||||||
|
"""
|
||||||
|
上述的一些命令是在我们知道这个字典有什么key的情况下,有的时候,我们不知道这个字典有什么键。
|
||||||
|
有什么办法能够获取键的列表以及值的列表呢?
|
||||||
|
使用items()方法可以获取字典的每个键值对,通过list命令转化成列表,每个元素是一个键值对元组。
|
||||||
|
使用keys()方法可以获取字典的每个键,通过list命令转化成列表,每个元素是一个键名。
|
||||||
|
使用values()方法可以获取字典的每个值,通过list命令转化成列表,每个元素是一个值。
|
||||||
|
***这几个方法在做字典枚举时非常有用,请务必掌握。***
|
||||||
|
"""
|
||||||
|
print(list(a.items()))
|
||||||
|
print(list(a.keys()))
|
||||||
|
print(list(a.values()))
|
||||||
|
|
||||||
|
# pop方法用于弹出某个键值对,并删除它,找得到会返回对应的值,找不到会报错,跟列表类似
|
||||||
|
print(a.pop("语文"))
|
||||||
|
print(a)
|
||||||
|
# popitem方法可以弹出某个键值对,实际是弹出底层存储的最后一个键值对并删除
|
||||||
|
# 由于python的字典没有顺序,我们不能说是定义的最后一个,而是底层存储的最后一个
|
||||||
|
print(a.popitem())
|
||||||
|
print(a)
|
||||||
|
# 你也可以用两个变量分别接收键和值
|
||||||
|
k, v = a.popitem()
|
||||||
|
print(k, v)
|
||||||
|
print(a)
|
||||||
|
# fromkeys方法可以批量创建指定key的字典,还能给默认值。个人很少用这个感觉
|
||||||
|
# 用列表创建,不给默认值时值默认为None
|
||||||
|
a = dict.fromkeys(['a', 'b'])
|
||||||
|
print(a)
|
||||||
|
# 用元组创建
|
||||||
|
a = dict.fromkeys(('a', 'b'))
|
||||||
|
print(a)
|
||||||
|
# 指定默认值
|
||||||
|
a = dict.fromkeys(['a', 'b'], "我是默认值")
|
||||||
|
print(a)
|
||||||
|
# 如果是这样呢?会不会分别给a、b赋值默认值?请自行尝试
|
||||||
|
a = dict.fromkeys(['a', 'b'], ["我是默认值","111"])
|
||||||
|
print(a)
|
||||||
|
|
||||||
|
# 附送一个,利用字典来给列表去重的方法,尤其适用在列表元素量很大时,很方便
|
||||||
|
a = [1, 0, 3, 7, 7, 5, 5, 0, 1]
|
||||||
|
newList = list({}.fromkeys(a).keys())
|
||||||
|
print(newList)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ---------- | ------------------------------------------------------------ |
|
||||||
|
| clear | 清除,清理 |
|
||||||
|
| copy | 复制 |
|
||||||
|
| get | 获得,得到 |
|
||||||
|
| setdefault | set设置,default默认,合起来就是设置默认值 |
|
||||||
|
| update | 更新 |
|
||||||
|
| items | 项目,一件东西(复数) |
|
||||||
|
| keys | key键的复数 |
|
||||||
|
| values | value值的赋值 |
|
||||||
|
| pop | 出栈 |
|
||||||
|
| popitem | pop item两个单词合起来,将一件东西出栈,这里是把键值对抛出字典外 |
|
||||||
|
| fromkeys | from来自...,keys,键的复数,合起来就是以很多键来怎么怎么样的意思 |
|
||||||
11
chapter3/README.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# 三、列表、元组和字典
|
||||||
|
|
||||||
|
本章节我们来介绍另外几种十分常用的数据类型:列表、元组和字典。
|
||||||
|
|
||||||
|
为什么我们需要他们呢?
|
||||||
|
|
||||||
|
之前我们学习的数据类型基本上都是存储单个数据的,当我们有1~10这10个数字的时候,难道我们需要定义10个变量吗?即使定义了,你都记得住变量名吗?100个数据、1000个数据呢?
|
||||||
|
|
||||||
|
因此这样思考下来,我们之前的数据类型可能还不够,在实际编程的过程中,很大可能需要通过某个变量来批量保存大量的数据,而列表、元组和字典就能满足这样的需求。这些数据类型在我们日常的编程中也常常用到,都是必知必会的内容。
|
||||||
|
|
||||||
|
想知道它们是什么怎么用吗?快来跟我一起学习吧!
|
||||||
209
chapter4/4-1 python3小白课:if分支结构.md
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
# python3小白课:if分支结构
|
||||||
|
|
||||||
|
### 顺序结构
|
||||||
|
|
||||||
|
当我们没有指定代码运行结构的时候,python是一条路走到黑的,即从上往下一行行解析执行代码,排在前面的先执行,排在后面的后执行。
|
||||||
|
|
||||||
|
但我们的世界都是一条路走到黑的吗?
|
||||||
|
|
||||||
|
比如小白同学很不喜欢下雨,一下雨就不想出门,那么小白同学会这么想:出门前看看外面的天气,如果是大晴天,就出门,如果下雨,就不出门。
|
||||||
|
|
||||||
|
这样的需求顺序结构就无法解决。这时候我们就需要用到if分支结构了。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### if分支结构
|
||||||
|
|
||||||
|
if是如果的意思,那么它就可以用来控制我们的判断条件让程序判断一下,if语句有几种写法形式,照着小白同学的例子,我们可以写下如下的伪代码方便大家理解(注意不是真正的python代码):
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 写法1
|
||||||
|
if "外面大晴天":
|
||||||
|
"出门咯~"
|
||||||
|
|
||||||
|
# 写法2,else表示否则,后面不需要跟条件表达式,囊括所有其他的可能性
|
||||||
|
if "外面大晴天":
|
||||||
|
"出门咯~"
|
||||||
|
else:
|
||||||
|
"坚决不出门"
|
||||||
|
|
||||||
|
# 写法3,elif为else if单词的合并,表示否则如果,后面需要跟条件表达式。允许有多个elif
|
||||||
|
if "外面大晴天":
|
||||||
|
"出门咯~"
|
||||||
|
elif "外面大暴雨":
|
||||||
|
"坚决不出门"
|
||||||
|
else:
|
||||||
|
"看看情况再说"
|
||||||
|
```
|
||||||
|
|
||||||
|
通过上述伪代码,我们可以可以清晰的看到if分支结构的多种判断条件的写法方式以及对应怎么执行,分析上述代码,我们可以总结出if结构有如下几个写法注意点:
|
||||||
|
|
||||||
|
* if分支结构以if开头,后面跟随判断的条件表达式,如果表达式结果返回True,则执行if区段下面的语句,如果为False,则不执行会往下看
|
||||||
|
|
||||||
|
* 接下来如果有elif语句,会继续判断是否符合条件,如果为True,则执行elif下面的语句,否则继续往下
|
||||||
|
|
||||||
|
* 当下面再没有elif的时候,如果没有else语句,则分支运行结束,但如果有else语句,则直接运行else语句下面定义的python语句
|
||||||
|
|
||||||
|
* 需要注意,每个结构写完条件表达式之后的冒号`:`,不要漏掉了
|
||||||
|
|
||||||
|
* 结构下的可执行语句,大家应该很容易注意到我都是用了缩进的,这是python编程语言相比其他编程语言的一大特色(其他编程语言可能用花括号`{}`或者`end`等关键字来表示流程控制区段范围),python强制这些流程控制结构都需要采用缩进的方式来表达层级关系,比如`"出门咯~"`是缩进的,就表示它是if语句块下面要执行的分支代码,这样定义的好处是,遇到流程控制的时候,通过缩进就可以很容易区分那些是流程控制语句块下的代码,对于强迫症患者来说这是相当美观的。但它的不足之处也很明显,那就是代码编写时需要特别注意缩进,如果该缩进却没缩进,解释器是会报错的,缩进问题有时候搞疯很多人。
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 那么如何缩进呢?
|
||||||
|
|
||||||
|
我个人一般使用一个`Tab`键的制表符距离表示缩进一层,如果层级嵌套,比如if语句可以嵌套if语句,那么就根据层级关系放适当数量的Tab距离。当然,你也可以用四个空格键来缩进(你喜欢两个空格其实也可以,但不要有时候缩进两个空格,有时候四个)。实际编写中,建议统一规范,是统一空格键还是Tab键,有时候混着用解释器也是可能报错的。一些不错的IDE可以实现一键自动帮你转换成其中一种,很少有这样的困扰,比如`pycharm`就能做到。
|
||||||
|
|
||||||
|
来一个嵌套的例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = 10
|
||||||
|
if a >= 5:
|
||||||
|
if a >= 8:
|
||||||
|
print("大于8")
|
||||||
|
else:
|
||||||
|
print("大于等于5小于8")
|
||||||
|
elif a < 0:
|
||||||
|
print("小于0")
|
||||||
|
else:
|
||||||
|
print("介于0到5之间")
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> 不需要缩进的地方请不要随意缩进,比如一个顺序结构,顺着下来就行了,就没必要缩进了。
|
||||||
|
|
||||||
|
我们来看点没有好好遵循缩进原则所造成问题的例子(我们可以存到一个py文件中来运行):
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = input("你的语文考试多少分?")
|
||||||
|
if int(a) < 90:
|
||||||
|
print("成绩不过关,继续努力哦~")
|
||||||
|
print("哇你真棒呀,都90分以上啦!")
|
||||||
|
```
|
||||||
|
|
||||||
|
上述代码执行后,如果我们输入一个90分以上的分数,则输出的结果在逻辑上是没有问题的。但当我们输入一个90分以下的分数时,`print("哇你真棒呀,都90分以上啦!")`这句代码也被执行了,因为它没有缩进,没有在if分支结构中,是无论如何都会执行的。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### if结构的判断条件
|
||||||
|
|
||||||
|
if结构后面的条件一定要是条件表达式吗?其实也不一定的,它后面的条件还能跟字符串、列表、元组、字典等等东西,这些东西也能判断出True或者False。
|
||||||
|
|
||||||
|
你需要记住的是下面这些,它们在进行if判断的时候会返回False,其他均返回True。这是if语句很容易判断返回的内容是否为空值的`神器`:
|
||||||
|
|
||||||
|
`False、 None、 0、 ""、 ()、 []、 {}`
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 其他的类似,我们就不一一列举了,大家请自己尝试,这里拿空字符串做例子
|
||||||
|
a = ""
|
||||||
|
if a:
|
||||||
|
print("a不是空字符串")
|
||||||
|
else:
|
||||||
|
print("a为空字符串")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### if分支的逻辑错误
|
||||||
|
|
||||||
|
使用if分支时,有时候虽然程序不报错,但代码却犯了逻辑错误(这种错误是你的代码运行逻辑跟业务逻辑有差异,达不到你想要的效果,但在python解释器的语法上是过关的可以运行的。逻辑错误是我们编写代码的过程中比较难以发现的一种错误,因为解释器不会报错你能马上查问题,而是通过查看运行结果来分析的方式来判断我们写的是否有问题,它对于编程人员的逻辑思维、空间抽象思维的要求较高。但大家不要怕,遇到这种情况的时候,可以通过一些IDE软件的调试功能或者将逻辑抽象出来进行抽丝剥茧式的分析,是可以发现并解决问题的,相信你解决之后也会很有成就感),也就是没有达到我们要的业务效果。
|
||||||
|
|
||||||
|
我们来举个简单的例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
score = 85
|
||||||
|
if score > 60:
|
||||||
|
print("及格")
|
||||||
|
elif score > 80:
|
||||||
|
print("良好")
|
||||||
|
elif score > 90:
|
||||||
|
print("优秀")
|
||||||
|
```
|
||||||
|
|
||||||
|
我们来看下上面的例子,乍看之下我们的判断条件都没有问题,60分以上的算及格,80分以上的算良好,90分以上的算优秀。那么我们的成绩score为85分,怎么也算良好这一档,对吧?
|
||||||
|
|
||||||
|
执行代码,我们发现给我们返回的结果是:`"及格"`
|
||||||
|
|
||||||
|
咦?怎么不是良好呢?其实在这里我们就犯了一个逻辑错误。85分是不是也大于60分?是的,所以在流程控制中,我们直接就从及格那里跑出来了,根本没有进行后面是否大于80分的判断。
|
||||||
|
|
||||||
|
这就是一个简单的逻辑错误,那么我们应该怎么修改呢?我们可以加上范围限制条件:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
score = 85
|
||||||
|
if score > 60 and score <= 80:
|
||||||
|
print("及格")
|
||||||
|
elif score > 80 and score <= 90:
|
||||||
|
print("良好")
|
||||||
|
elif score > 90:
|
||||||
|
print("优秀")
|
||||||
|
```
|
||||||
|
|
||||||
|
通过这样的修改,我们就实现了每段判断的范围限定,就能输出`良好`啦。
|
||||||
|
|
||||||
|
有的同学思路很快,能想出下面更好的办法:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
score = 85
|
||||||
|
if score > 90:
|
||||||
|
print("优秀")
|
||||||
|
elif score > 80:
|
||||||
|
print("良好")
|
||||||
|
elif score > 60:
|
||||||
|
print("及格")
|
||||||
|
```
|
||||||
|
|
||||||
|
这段代码没有添加and,只是调换了一下几个判断条件的写的顺序,也能实现我们的效果,分析一下,既然我们都是往大于的方向进行判断,那么我们应该先判断最大的,当90不满足的时候,才能判断是否大于80这一档,在判断这一档的时候,已经隐含了一个条件,那就是肯定`<= 90`,所以一定不可能是`优秀`,这时候我们就不会错漏了。
|
||||||
|
|
||||||
|
通过上述几个简单例子的学习,大家是不是对逻辑错误有了更加形象的认识?在编写代码时,我们需要多思考流程控制的最佳逻辑,这样有助于训练我们的编程逻辑思维,对大家是很有帮助的。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### if表达式
|
||||||
|
|
||||||
|
之前介绍三目运算符的时候介绍过一行的if表达式写法。这里不再赘述。
|
||||||
|
|
||||||
|
当我们只有if判断想要写在一行的时候,也可以这么写:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = 10
|
||||||
|
if a > 5 : print("大于5")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### pass占位符
|
||||||
|
|
||||||
|
pass表示通过的意思,在python中,如果流程控制结构后面的代码执行体,我们不打算执行任何代码或者打算不进行任何代码处理,或者我们还没想好要执行啥,那么在编写时,不能够留空,会报错,这时候我们可以用`pass`来作为执行体的占位符,代码运行到这里就不执行任何代码往下了。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
score = 85
|
||||||
|
if score > 90:
|
||||||
|
print("优秀")
|
||||||
|
elif score > 80:
|
||||||
|
# 这里不写任何可执行的语句,可以写个pass,如果满足条件进来了,也不会执行任何东西
|
||||||
|
pass
|
||||||
|
elif score > 60:
|
||||||
|
print("及格")
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ----- | ------------------------------------------------------------ |
|
||||||
|
| if | 如果 |
|
||||||
|
| elif | else if合在一起的写法,其他语言可能是用的else if这样的,python注意用elif,表示否则如果 |
|
||||||
|
| else | 否则 |
|
||||||
|
| score | 成绩 |
|
||||||
|
| pass | 通过 |
|
||||||
160
chapter4/4-2 python3小白课:while循环结构.md
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
# python3小白课:while循环结构
|
||||||
|
|
||||||
|
### 循环结构
|
||||||
|
|
||||||
|
除了分支结构,我们的流程控制里面还有一个大类,叫做循环结构,它是我们的程序能帮我们省去很多人力的关键。顾名思义,循环结构的作用就是能让某一段代码执行体能够反复的执行我们规定的次数,同时在执行的过程中还能有一些自己智能的选择。
|
||||||
|
|
||||||
|
我们来举个例子:
|
||||||
|
|
||||||
|
比如我们都知道,重要的事情说三次,那么我们需要实现一个功能就是设定一句话,只需要设定一次,然后就会自动说三次。如果我们打印三行相同的print代码,也是可以实现的。但如果我们说重要的事情说10遍、100遍呢?这样敲代码我们是要累死的。这时候我们就可以用上循环结构了,只需要写一行print代码,就可以实现指定次数的反复执行。
|
||||||
|
|
||||||
|
我们再来举一个例子:
|
||||||
|
|
||||||
|
比如有一个饮料自动贩售机,里面有雪碧、芬达、可乐、矿泉水四种饮品。每种饮品我们假定有5瓶,所以总共有20瓶。现在我们就来贩售饮料,它的过程是,小白同学会按下需要什么饮料,然后扫码支付对应的金额对吧,然后饮料就从贩售机下方吐出来了。这就是一个完整的售卖饮料的过程,完成之后,又会陷入等待下一位消费者购买的循环,而下一位购买者也是这样的操作步骤,只不过,有可能买的不是同一种饮料罢了。
|
||||||
|
|
||||||
|
像这样的过程,我们就完全可以使用循环结构来智能地实现。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### while循环的语句结构
|
||||||
|
|
||||||
|
while循环的一般语句结构为:
|
||||||
|
|
||||||
|
```python
|
||||||
|
while 条件:
|
||||||
|
执行体
|
||||||
|
```
|
||||||
|
|
||||||
|
它是以while来作为关键字的,如果条件返回True,则会循环执行循环体的代码。执行完毕后,会再次判断条件是否为True,如果为False了,就会结束循环,否则再次执行循环体代码。
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 有的同学会问,那什么时候是个头呢?
|
||||||
|
|
||||||
|
我们可以看到,当上述结构中的条件部分返回True时,就会执行循环体的代码。如果它一直返回为True,那么这个循环称作死循环,死循环结构在某些业务场景下也可能会写,也是允许的,比如循环监控、循环等待下一步指令等等。
|
||||||
|
|
||||||
|
但当我们只是打算循环指定的次数或者满足某些条件退出的时候,我们在写循环结构的时候,就应该注意从`条件`这块下功夫,当执行完执行体,条件改变之后,是可以退出循环的。所以比如我们打算实现前面的重要的话只说3遍的效果,我们可以这样写。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = "我是小白,我很白,重要的话说三遍"
|
||||||
|
i = 0
|
||||||
|
while i < 3:
|
||||||
|
print(a)
|
||||||
|
i += 1
|
||||||
|
```
|
||||||
|
|
||||||
|
如代码所示,我们一般会设定一个循环变量,很多编程语言中都喜欢用`i`来做循环变量,当然你也可以用别的名字。设定初始值为0,条件设置为`i < 3`,每次执行完循环的执行体关键代码之后,将这个循环变量自增1。可以预见的是,`i`的值在循环内部会分别为`0, 1, 2`,当它变为3的时候,判断`i < 3`就不成立并返回False了,循环就会自动退出了,而代码正好循环了三次。
|
||||||
|
|
||||||
|
这就是我们在使用while循环时的一种通用的重复一定次数的做法。希望大家掌握它的使用。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 使用while循环遍历列表或元组
|
||||||
|
|
||||||
|
使用while循环的另一种场景是遍历列表或者元组的元素,我们以列表为例子,看下怎么写:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = [1, 2, 3, 4, 5]
|
||||||
|
i = 0
|
||||||
|
while i < len(a):
|
||||||
|
print(a[i]) # 可以将循环变量i作为索引访问列表成员
|
||||||
|
i += 1
|
||||||
|
```
|
||||||
|
|
||||||
|
结合len函数还有索引访问列表成员,我们就轻松实现了列表的遍历。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### while编写死循环以及break语句
|
||||||
|
|
||||||
|
我们在某些业务场景下,需要使用while死循环的,我们可以写一个永远为True的表达式,可以写`while True:`或者`while 1==1:`都行。我们看个例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
while True:
|
||||||
|
print("我是死循环,永远不会结束")
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> 但如果你吃饱了没事儿,还是不要随便乱写,要根据自己的业务需要来编写。
|
||||||
|
|
||||||
|
如果我们编写了死循环,就永远也无法出来了吗?还是有办法的,我们可以使用`break`语句来实现退出当前层级的循环(注意是当前层级,比如我们在while循环里面又嵌套了一个while循环,这是两层嵌套,这时候最内层的while循环碰到了`break`语句,只能退出最内层循环,但还得在最外层循环中根据条件来判断是否继续循环运行。if结构不是循环结构,使用break无效)。
|
||||||
|
|
||||||
|
我们看个例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
i = 0
|
||||||
|
while True:
|
||||||
|
print("我是死循环,但有时候还是会无奈地结束")
|
||||||
|
i += 1
|
||||||
|
if i >= 10:
|
||||||
|
break
|
||||||
|
```
|
||||||
|
|
||||||
|
这也是一个while结构跟if结构嵌套写的例子,大家注意看一下里面的缩进关系,编写python时缩进关系一定要注意好。这里会每次判断i的值,最后的效果是这句话只打印了10次,循环就退出了,这就是因为遇到了`break`语句的原因。
|
||||||
|
|
||||||
|
掌握了前面的知识,我们可以试着来写自动贩售机的源码了。大家也可以不看我写的代码,自己尝试先写一下,看能否用我们已经学过的知识写出来?
|
||||||
|
|
||||||
|
自动贩售机代码参考(我们也用上一点新知识,跟大家一同讲解提高):
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 自动贩售机源码参考
|
||||||
|
# 我们有雪碧、芬达、可乐、矿泉水四种饮品,每种饮品我们假定有5瓶
|
||||||
|
# 通过input语句获取用户需要什么饮品,可以用序号替代,买完后库存要减少
|
||||||
|
# 当需要的饮品卖完之后,会智能的弹出提示提示用户卖完了请买别的
|
||||||
|
|
||||||
|
# 定义饮品字典,通过数字序号作为key方便后续获取值
|
||||||
|
drinks = {
|
||||||
|
1: ["雪碧", 5],
|
||||||
|
2: ["芬达", 5],
|
||||||
|
3: ["可乐", 5],
|
||||||
|
4: ["矿泉水", 5]
|
||||||
|
}
|
||||||
|
while True:
|
||||||
|
# 这里用了多行文本,多行文本内如果使用了缩进,输出时也会保留缩进,所以我们不缩进
|
||||||
|
question = f"""
|
||||||
|
你想喝什么呢?
|
||||||
|
===================
|
||||||
|
1. 雪碧(剩余{drinks[1][1]}瓶)
|
||||||
|
2. 芬达(剩余{drinks[2][1]}瓶)
|
||||||
|
3. 可乐(剩余{drinks[3][1]}瓶)
|
||||||
|
4. 矿泉水(剩余{drinks[4][1]}瓶)
|
||||||
|
请输入你想喝的饮品序号并回车:
|
||||||
|
"""
|
||||||
|
answer = input(question)
|
||||||
|
# 字符串的isdigit方法会检查字符串是否均为数字,若是返回True
|
||||||
|
if not(answer.isdigit()):
|
||||||
|
print("\t\t\t>>> 请输入饮品序号!您的输入无法识别!")
|
||||||
|
# continue可以立即结束本次循环,但还会进入下一次循环
|
||||||
|
continue
|
||||||
|
answer = int(answer)
|
||||||
|
if answer in range(1, 5):
|
||||||
|
print("\t\t\t>>> 您选择的饮料是:%s" % drinks[answer][0])
|
||||||
|
if drinks[answer][1] > 0:
|
||||||
|
drinks[answer][1] -= 1
|
||||||
|
print("\t\t\t>>> 您要的饮料已弹出!")
|
||||||
|
else:
|
||||||
|
print("\t\t\t>>> 您要的饮料库存已不足!请重新选择!")
|
||||||
|
else:
|
||||||
|
print("\t\t\t>>> 啊哦,您要的饮料货架上没有,再看看吧!")
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| -------- | ------------------------------------------ |
|
||||||
|
| while | 当...的时候 |
|
||||||
|
| break | 弄坏,弄破,这里是退出当前循环体的语句 |
|
||||||
|
| drinks | drink饮品的复数形式 |
|
||||||
|
| question | 问题 |
|
||||||
|
| answer | 答案,回答 |
|
||||||
|
| isdigit | is是,digit数字,判断是否都为数字的命令 |
|
||||||
|
| continue | 继续,python中可以立即结束当前这一次的循环 |
|
||||||
|
|
||||||
163
chapter4/4-3 python3小白课:for-in循环结构.md
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
# python3小白课:for-in循环结构
|
||||||
|
|
||||||
|
### for-in循环结构
|
||||||
|
|
||||||
|
for-in循环一般用来遍历范围、列表、元组和字典等可迭代对象包含的元素。可迭代的意思是它可以多次调用获取。比如你有一个箱子,里面有40个球球,我定义,每次我喊你的名字`小白同学`的时候,你就会从箱子里给我拿一个球球出来,下一次喊你还是一样的拿球球。那么这个箱子就是一个可迭代对象了。
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> 而遍历的含义就是将所有的可能的内容都枚举出来,for-in循环更适合做这样一个事情。
|
||||||
|
|
||||||
|
for-in循环的一般语法结构为:
|
||||||
|
|
||||||
|
```python
|
||||||
|
for 循环变量 in 字符串|范围|列表元组字典等:
|
||||||
|
执行体
|
||||||
|
```
|
||||||
|
|
||||||
|
循环变量我们不需要自己赋值,它在进入循环的时候,就会自动从后面的`字符串|范围|列表元组字典等`这些可迭代对象中取出1个来,赋值给循环变量,然后进入循环。这些可迭代对象通常的理解来说是有限的,因此会循环几次基本也是可定的。在执行体的部分我们可以执行代码,下一次进入循环时还会再次执行。在执行体的部分还能访问到`循环变量`的值,这样就可以做一些智能化的循环操作。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### for-in小例子
|
||||||
|
|
||||||
|
为了大家更快速的理解,我们还是拿之前的重要的话说三遍的例子来讲一下,之前我们是使用while循环完成的代码,这节课我们用可能更为合适这个场景的for-in循环来试一下。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = "我是小白,我很白,重要的话说三遍"
|
||||||
|
for i in range(3):
|
||||||
|
print(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
我们使用了range函数来生成了一个序列,它是可迭代对象,可以直接迭代使用。可以看到,这样写,我们的代码更为简洁。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### for-in遍历列表和元组和字符串
|
||||||
|
|
||||||
|
列表、元组可以直接被遍历到,我们来看下例子,这时候,循环变量代表取出来的元素,根据需要,可以做进一步判断处理:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = [1, 2, 3]
|
||||||
|
b = (1, 2, 3)
|
||||||
|
for i in a:
|
||||||
|
print(i)
|
||||||
|
for i in b:
|
||||||
|
print(i)
|
||||||
|
```
|
||||||
|
|
||||||
|
字符串也能被遍历,遍历出来是每个字符:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = "我是小白,little bai"
|
||||||
|
for i in a:
|
||||||
|
print(i)
|
||||||
|
```
|
||||||
|
|
||||||
|
你还可以使用索引来进行遍历,是另一种比较常见的写法:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = [1, 2, 3]
|
||||||
|
b = (1, 2, 3)
|
||||||
|
c = "我是小白,little bai"
|
||||||
|
for i in range(len(a)):
|
||||||
|
print(a[i])
|
||||||
|
for i in range(len(b)):
|
||||||
|
print(b[i])
|
||||||
|
for i in range(len(c)):
|
||||||
|
print(c[i])
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### for-in遍历字典
|
||||||
|
|
||||||
|
字典是键值对的形式的,但我们可以通过`items()、keys()、values()`这几个命令来获取字典的情况:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = {"语文": 90, "数学": 89, "英语": 95}
|
||||||
|
for key, value in a.items():
|
||||||
|
print("key: %s" % key)
|
||||||
|
print("value: %s" % value)
|
||||||
|
print("*" * 40)
|
||||||
|
for key in a.keys():
|
||||||
|
print("key: %s" % key)
|
||||||
|
print("*" * 40)
|
||||||
|
for value in a.values():
|
||||||
|
print("value: %s" % value)
|
||||||
|
print("*" * 40)
|
||||||
|
```
|
||||||
|
|
||||||
|
通过字典,我们还可以统计列表中不同元素出现的次数。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = [1, 2, 3, 4, 2, 3, 4, 2, 3, 4, 5, 6, 6, 4, 4, 5, 6, 7, 4]
|
||||||
|
a_dict = {}
|
||||||
|
for key in a:
|
||||||
|
a_dict[key] = a_dict.get(key, 0) + 1
|
||||||
|
print("a_dict:", a_dict)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 在循环结构中使用else
|
||||||
|
|
||||||
|
循环结构也是支持else语句的,这是在python中相它编程语言一种比较特别的语法,在实际使用中,可能比较少使用吧。它使用后的逻辑为,当while或者for-in循环的循环体中没有遇到`break`语句强制退出时,会执行else代码段中的内容,但循环是通过`break`强制退出的话,那么就不会执行else代码段中的内容了。
|
||||||
|
|
||||||
|
我们来看个例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
i = 0
|
||||||
|
while i < 3:
|
||||||
|
print(i)
|
||||||
|
if i == 2:
|
||||||
|
break
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
print("enter")
|
||||||
|
|
||||||
|
print("*" * 40)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
while i < 3:
|
||||||
|
print(i)
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
print("enter")
|
||||||
|
|
||||||
|
print("*" * 40)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for i in range(3):
|
||||||
|
print(i)
|
||||||
|
if i == 2:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print("enter")
|
||||||
|
|
||||||
|
print("*" * 40)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for i in range(3):
|
||||||
|
print(i)
|
||||||
|
else:
|
||||||
|
print("enter")
|
||||||
|
```
|
||||||
|
|
||||||
|
如果有需要,那可以考虑使用这种结构,但我个人也极少会使用到。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------ | ---------------------------------------------- |
|
||||||
|
| for-in | for in两个单词组成的结构,意思为对于xx在xx里面 |
|
||||||
|
| enter | 进入 |
|
||||||
111
chapter4/4-4 python3小白课:for表达式.md
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
# python3小白课:for表达式
|
||||||
|
|
||||||
|
### for表达式基本使用
|
||||||
|
|
||||||
|
for表达式通常用于使用区间、元组、列表等可迭代对象来创建新的列表,在实战中的某些场景偶尔会用到,如果掌握比较困难,也可以不学这个。for表达式的语法如下:
|
||||||
|
|
||||||
|
```python
|
||||||
|
[表达式 for 循环变量 in 可迭代对象]
|
||||||
|
```
|
||||||
|
|
||||||
|
for表达式只有一行,跟一般的循环结构是有点区别的,我们对比一下,它将表达式放到了for的前面,表达式部分就是我们之前讲for-in循环时的执行体部分,然后我们还注意到,外面增加了一个`[]`,表示将生成的结果生成一个列表来包裹起来,最终返回一个列表,所以有时候我们也称之为列表推导式。
|
||||||
|
|
||||||
|
我们来看个小例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = range(5)
|
||||||
|
# 我们来获取一下a这个列表每个元素的平方的新列表
|
||||||
|
b = [x * x for x in a]
|
||||||
|
print(b)
|
||||||
|
# 我们还能添加if条件在后面,满足条件元素为偶数的才计算
|
||||||
|
b = [x * x for x in a if x % 2 == 0]
|
||||||
|
print(b)
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 有的同学会想,如果我们将表达式的`[]`换成`()`是否可以呢?将列表换成元组,会生成一个元组吗?
|
||||||
|
|
||||||
|
我们来看一下。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = range(5)
|
||||||
|
b = (x * x for x in a)
|
||||||
|
print(b)
|
||||||
|
print(type(b))
|
||||||
|
```
|
||||||
|
|
||||||
|
我们会发现,返回的是一个`generator`对象,这个对象是一个生成器,是可以迭代的,我们可以使用for-in循环迭代。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = range(5)
|
||||||
|
b = (x * x for x in a)
|
||||||
|
for i in b:
|
||||||
|
print(i)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### for表达式支持嵌套
|
||||||
|
|
||||||
|
for表达式也支持嵌套,两层或者三层的循环嵌套也是可以的,当然如果有if条件的需要也可以加上。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 我们拿稍微简单一点的两层循环嵌套来说明写法
|
||||||
|
a = [(x, y) for x in range(5) for y in range(3) if x > y]
|
||||||
|
print(a)
|
||||||
|
# 上述写法跟这样的写法是一样的:
|
||||||
|
a = []
|
||||||
|
for x in range(5):
|
||||||
|
for y in range(3):
|
||||||
|
if x > y:
|
||||||
|
a.append((x, y))
|
||||||
|
print(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
看,是不是方便许多?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### zip压缩函数
|
||||||
|
|
||||||
|
这里我们小小的介绍一个有用的函数zip压缩函数。它可不是我们日常理解的一种压缩文件命令,而是可以将几个列表压缩成一个zip对象(可迭代对象),这样可以使用循环来并行遍历两个列表了。
|
||||||
|
|
||||||
|
我们来看个小小的例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = ['a', 'b', 'c']
|
||||||
|
b = [4, 5, 6]
|
||||||
|
c = [x for x in zip(a, b)]
|
||||||
|
print(c)
|
||||||
|
```
|
||||||
|
|
||||||
|
可以看到,我们将两个列表压缩成了多个元组组合,最后再生成个列表,就是一个列表了。
|
||||||
|
|
||||||
|
如果两个列表成员数不一致会怎么样呢?
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
a = ['a', 'b', 'c']
|
||||||
|
b = [4, 5]
|
||||||
|
c = [x for x in zip(a, b)]
|
||||||
|
print(c)
|
||||||
|
```
|
||||||
|
|
||||||
|
可以看到效果是以短的列表为准来进行压缩。
|
||||||
|
|
||||||
|
这个函数大家知道一下即可。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ---- | ---- |
|
||||||
|
| zip | 压缩 |
|
||||||
|
|
||||||
7
chapter4/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# 四、流程控制
|
||||||
|
|
||||||
|
经过了前面一系列基础的学习,相信大家已经对python有了更进一步的了解,但我们之前的代码基本都是顺序执行,一写到底的。那么我们的程序就只有那么死板的一条路走到黑吗?
|
||||||
|
|
||||||
|
当然不是的,通过本章节——流程控制的学习,你会对此有一个全新的认识,通过代码的编写,你可以为你的程序注入不一样的活力,让它们像个只能机器人一样,能够智能地判断应该走哪一条路,运行哪一些代码。
|
||||||
|
|
||||||
|
越来越好玩了,不是吗?
|
||||||
35
chapter5/5-1 python3小白课:函数是什么.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# python3小白课:函数是什么
|
||||||
|
|
||||||
|
### 函数是什么
|
||||||
|
|
||||||
|
上学的时候,我相信大家学习过一种简单的函数,比如`y = x + 1`,通过映射关系,输入x的值,就能计算出y的值。
|
||||||
|
|
||||||
|
类似的,在编程语言中,函数可以是一段封装好的代码,你只要给它喂进去它规定需要的零到多个参数,它通过一通群魔乱舞之后就能给你吐出来结果。就像刚才说的函数等式一样,编程语言中封装的函数也能够多次进行调用。
|
||||||
|
|
||||||
|
从咱们开始学习到现在,我想使用得最多的就是内置的`print`函数了吧,你只需要喂给它你需要打印输出的内容,它就会输出到控制台中。同时这个命令还能无限次进行调用。
|
||||||
|
|
||||||
|
使用它的人无需在意它在内部如何群魔乱舞的细节,只需要了解它要喂什么,和它会吐什么就可以了。
|
||||||
|
|
||||||
|
但定义它的人不一样,既需要知道它需要喂什么,吐什么,还需要知道内部运行的细节,这可比仅仅使用它难多了。这跟我们制造东西一样,使用一台电脑很好学习,但制造一台电脑对个人来说可不是个容易的事情。
|
||||||
|
|
||||||
|
本章节我们主要就来讲讲定义它的一些细节。
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> 放心,定义函数的难易程度跟你要实现的目的有关,对于逻辑简单的函数,其实并不费什么功夫。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 为啥要用函数
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 有的同学会好奇,我们使用之前学习的内容,直接写我们要执行的代码不好吗?干嘛还要定义个函数,然后再调用它听起来这种听起来很麻烦的做法呢?
|
||||||
|
|
||||||
|
其实我们可以有这么一些个好处:
|
||||||
|
|
||||||
|
(1)控制代码运行的开关。函数定义后,没有调用它的情况下是不会执行的,这样我们结合流程控制,可以智能地选择要运行的代码,当不想运行的时候,注释掉调用语句或者不写调用即可,用不着把大段的代码逻辑给注释掉或删除掉,非常方便。
|
||||||
|
|
||||||
|
(2)代码复用。函数为代码复用的重要手段,比如我们要计算一个我们想要的复杂的计算结果需要传入1个参数,然后跑200行的代码后才能获得正确的结果。如果没有函数,那么我们每次计算都写一遍这200行代码吗?这么做显然是低效而且浪费资源的。我们做程序员就是为了`偷懒`,别人辛辛苦苦干一天的活,我们整个自动化程序,自己跑个一小时就干完了,大大提高了生产力,所以重复的代码还是尽量交给计算机来完成比较好,这样我们有更多的时间来思考业务实现逻辑的优化。这也体现了`封装`的思想,将经常需要使用的相同或相似代码打个包,用到的时候拿出来玩玩,用不到的时候它就乖乖躺一边,多舒服啊。
|
||||||
|
|
||||||
|
当然使用函数还有其他一些好处,这里就不再赘述了。总之它很好,就对了。
|
||||||
148
chapter5/5-2 python3小白课:函数入门.md
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
# python3小白课:函数入门
|
||||||
|
|
||||||
|
### 函数的定义和调用
|
||||||
|
|
||||||
|
定义一个函数很简单,用到def关键字来定义。我们来看一下语法:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def 函数名([形参们]):
|
||||||
|
[执行体]
|
||||||
|
[return [返回值]]
|
||||||
|
```
|
||||||
|
|
||||||
|
上述语法中的`[]`表示里面的内容是可选的,可以填可以不填,不是列表的意思。
|
||||||
|
|
||||||
|
使用def来声明这是一个函数,接下来写函数的名字,跟变量的命名规则类似,这里就不赘述了,需要注意的是,函数名不要跟一些系统保留关键字、类型名等相同,否则会报错或者覆盖内置的函数,使内置函数在脚本中无法使用。所以函数名尽量有意义一些,根据你的业务场景来命名有意义的,你能理解的命名。
|
||||||
|
|
||||||
|
接下来是一个小括号,里面可以设定要传入的参数在执行体中的名字(这样在执行体中可以获取到传入的参数),也可以是一个不需要参数的函数。
|
||||||
|
|
||||||
|
函数的内里部分需要缩进(否则不算函数的一部分),这一点需要大家注意一下。
|
||||||
|
|
||||||
|
当需要这个函数在调用完成后对外返回内容的时候,可以使用`return`关键字来进行返回,但它不是必须的。如果没有返回值就不写,如果有返回值就写。可以是什么都不返回,也可以在一个空格之后填写返回值,返回值可以是各种我们之前学习的数据类型。
|
||||||
|
|
||||||
|
执行体和return语句不能同时不存在。如果你还没想好这个函数要做什么,可以使用学过的`pass`占位符占位。
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> 在函数中,一旦碰到return语句函数就会立即结束调用并返回,即时在return语句的后面还有执行的语句也是不会执行的。所以它也可以用于`结束循环结构的循环体`。
|
||||||
|
|
||||||
|
我们来尝试定义一个十分简单的函数,并且调用它来理解:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def add_1(num):
|
||||||
|
return num + 1
|
||||||
|
a = add_1(1)
|
||||||
|
print(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
这个例子是定义一个函数,这个函数可以让传入的值加上1之后返回。从这个简单的例子我们还能看到一些小知识点。
|
||||||
|
|
||||||
|
比如这是一个没有执行体部分的函数,但计算的逻辑代码写在了return语句的部分,所以return语句是支持表达式的。
|
||||||
|
|
||||||
|
形参传入了一个叫做num的变量,它是不允许为空的变量,必须传入值,否则调用函数时会报错。
|
||||||
|
|
||||||
|
函数返回之后,可以用变量接收结果进行进一步处理。函数的定义代码在调用之前,调用函数跟我们之前调用系统内置函数似乎区别不大。
|
||||||
|
|
||||||
|
同理,定义函数时不设定形参,就是一个不需要传入参数即可直接调用的函数,我们看个例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def print_3():
|
||||||
|
text = "重要的事情说三遍!"
|
||||||
|
for i in range(3):
|
||||||
|
print(text)
|
||||||
|
print_3()
|
||||||
|
```
|
||||||
|
|
||||||
|
这个函数是`重要的事情说三遍`的函数实现,今后,你只需要带上这个函数,就可以一条命令调用这个功能了,十分方便。当然,如果你需要实现传入任意的话语都能自动说三遍,你也可以设定一个形参,传入你要说的话。
|
||||||
|
|
||||||
|
这个函数没有return语句,也是可以的。具体怎么写,你可以根据你的业务需要,灵活思考变动,举一反三。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 函数多个返回值
|
||||||
|
|
||||||
|
刚才我们举的小例子都是返回一个返回值或者不返回的。
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 那么同一个函数支持多个返回值吗?
|
||||||
|
|
||||||
|
在python中,是支持的。我们直接来看个例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def get_fruits():
|
||||||
|
return "apple", "banana", "orange"
|
||||||
|
print(get_fruits())
|
||||||
|
```
|
||||||
|
|
||||||
|
这个例子返回了三种水果的名字字符串,我们注意到在return语句中使用了`,`分隔,这样就可以返回多个返回值了,返回的返回值会自动组装成一个列表。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 你可以使用一个变量接收后使用索引访问,也可以定义多个变量,用序列解包的方式赋值给每个变量。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 为函数提供帮助文档
|
||||||
|
|
||||||
|
之前的课程中,我们学习过使用`help`命令来查看函数命令的帮助文档,这些文档是哪儿来的呢?其实这都是这些函数在创建之初,就定义好的供人查询用的。如果开发者懒一点没有定义,那么有可能你是看不到这个文档的。
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 那么你自己编写的函数呢?可以自己定义文档吗?
|
||||||
|
|
||||||
|
答案是可以的,而且非常简单。
|
||||||
|
|
||||||
|
我们来看个例子。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def get_fruits():
|
||||||
|
"""
|
||||||
|
我就是函数的文档,使用多行文本的写作方式就可以,写在函数执行体的前面
|
||||||
|
这个函数是支持中文的。
|
||||||
|
因为是多行文本,某一行你也可以选择不缩进,总之怎么方便怎么来。
|
||||||
|
你可以写任意的内容到文档里面
|
||||||
|
通常的写法是:
|
||||||
|
函数作用:获取几种水果的名字
|
||||||
|
参数:没有参数。如果有多个参数可以分多行写
|
||||||
|
返回值:没有返回值可以不写
|
||||||
|
|
||||||
|
你还可以写一些使用范例等等
|
||||||
|
|
||||||
|
写好之后,可以使用help命令来查看你写的效果,如果不喜欢,还可以修改
|
||||||
|
"""
|
||||||
|
return "apple", "banana", "orange"
|
||||||
|
print(get_fruits())
|
||||||
|
print("*" * 40)
|
||||||
|
print(help(get_fruits))
|
||||||
|
print("*" * 40)
|
||||||
|
# 你还可以使用函数的__doc__属性查看帮助文档,注意前后各有两个_
|
||||||
|
print(get_fruits.__doc__)
|
||||||
|
```
|
||||||
|
|
||||||
|
可见,有的时候定义一个函数的文档,内容甚至可能比代码的量还大,当然,如果你不想写那么多,也没有强制要求,你可以不写文档或者只写一两行,一切看你自己。
|
||||||
|
|
||||||
|
如果你写的函数文档是怕自己忘了或者给别人看的,还记得我们讲过的注释的好处吗?一个好的帮助文档是可以帮助团队省事的,要写多少,看你咯。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------ | --------------------------------- |
|
||||||
|
| def | define定义这个单词的简写 |
|
||||||
|
| return | 返回 |
|
||||||
|
| add | 加,加法 |
|
||||||
|
| num | number数字的简写 |
|
||||||
|
| text | 文本 |
|
||||||
|
| get | 获取 |
|
||||||
|
| fruits | fruit是水果的意思,这里是复数形式 |
|
||||||
|
| apple | 苹果 |
|
||||||
|
| banana | 香蕉 |
|
||||||
|
| orange | 橙子,柑橘 |
|
||||||
|
| help | 帮助 |
|
||||||
|
| doc | document文档这个单词的简写 |
|
||||||
87
chapter5/5-3 python3小白课:递归函数.md
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
# python3小白课:递归函数
|
||||||
|
|
||||||
|
### 递归函数的定义
|
||||||
|
|
||||||
|
在一个函数的定义中,可以调用其他函数来完成一些操作。但如果在函数的定义内部调用函数自身(即自己调用自己),那么这个函数就称之为递归函数,递归函数是一种有趣的函数定义形式,在某些业务场景之下十分便利。比如文件层级遍历、目录树、一些数学算法等。
|
||||||
|
|
||||||
|
本节课我们就拿一个简单的数学算法来讲讲递归函数是如何定义的以及注意点。
|
||||||
|
|
||||||
|
> 引用百科的内容:
|
||||||
|
>
|
||||||
|
> 斐波那契数列(Fibonacci sequence),又称黄金分割数列、兔子数列,是数学家列昂纳多·斐波那契于1202年提出的数列。
|
||||||
|
>
|
||||||
|
> 斐波那契数列为1、1、2、3、5、8、13、21、34……此数列从第3项开始,每一项都等于前两项之和,递推公式为F(n)=F(n-1)+F(n-2),n≥3,F(1)=1,F(2)=1。
|
||||||
|
>
|
||||||
|
> 在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从1963年起出版了以《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊载这方面的研究成果。
|
||||||
|
|
||||||
|
要完成斐波那契数列的递推生成,使用递归函数就是一个不错的选择。我们先来看一下代码:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def fib(n):
|
||||||
|
if n in [1, 2]:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return fib(n - 1) + fib(n - 2)
|
||||||
|
fib_seq = [fib(i) for i in range(1, 31)]
|
||||||
|
print(fib_seq)
|
||||||
|
```
|
||||||
|
|
||||||
|
如代码所示,我们通过for表达式循环获取了一个斐波那契数列列表,共30个元素,传入是要求这个n要大于等于1,这里就不写其他的判断语句了,为了说明的简洁。
|
||||||
|
|
||||||
|
可以看到进入函数之后,首先判断n是否为1或者2,如果是的话,则是固定的数1,如果大于等于3的话,就会返回调用自身函数的表达式,只不过传入的参数变成了`n -1`或者`n - 2`。这样传入之后,就会各自调用自身来进行计算,当减少到一定程度之后,一定会到获取`fib(1)、fib(2)`的值,而这两个值是固定的,为1。所以整个函数调用得以结束。
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> 编写递归函数时,当自身自调用到一定程度的时候,它能够获取确定的值,不再调用自身,如果不能,就会形成一种死循环,这是无意义的。
|
||||||
|
>
|
||||||
|
> 因此在写递归函数的时候,需要注意,递归一定要朝着已知的方向进行。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 防止堆栈溢出
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> 这部分是比较偏底层原理的内容,如果不好理解,可以跳过。
|
||||||
|
|
||||||
|
使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> 因此我们在使用递归函数的时候,需要注意调用递归的层级不要太深,太深容易导致栈溢出,会报错,在python中目前没有良好的机制来处理,所以是存在这个问题的。
|
||||||
|
|
||||||
|
多深呢?比如上千层的递归调用。
|
||||||
|
|
||||||
|
还有一种情况是递归程度深,系统运算困难,速度慢。就拿刚才讲到的斐波那契数列来说,我们把代码改成这样:
|
||||||
|
|
||||||
|
这次我们一次次获取数列中的每个值,打算跑1000次。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def fib(n):
|
||||||
|
if n in [1, 2]:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return fib(n - 1) + fib(n - 2)
|
||||||
|
for i in range(1, 1001):
|
||||||
|
print("i: %s, fib(i): %s" % (i, fib(i)))
|
||||||
|
```
|
||||||
|
|
||||||
|
我们来运行看一下效果。
|
||||||
|
|
||||||
|
可以看到随着递归层级的加深,运算速度也在逐步减慢,有的时候甚至半天出不来一个结果了。
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> 因此我们在实际运用中,注意递归层级不要过深。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------------------ | ------------------------------------------------------ |
|
||||||
|
| Fibonacci sequence | 斐波那契数列,fib,seq为长单词短写,本身不是单词 |
|
||||||
|
| stack | 栈,你可以理解为在一个容器中一块块放入木板,为加一层栈 |
|
||||||
|
|
||||||
47
chapter5/5-4 python3小白课:关键字参数.md
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# python3小白课:关键字参数
|
||||||
|
|
||||||
|
定义函数的时候我们可以设定形参,而在调用函数的时候需要传入对应的参数,我们最简单的方式是直接按定义时的顺序传入,这时候传入的参数就叫做位置参数。它会按照传入的位置赋值给对应的形参。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def info(name, age):
|
||||||
|
print("姓名:%s,年龄:%d" % (name, age))
|
||||||
|
info("小白", 18)
|
||||||
|
```
|
||||||
|
|
||||||
|
但我们有的时候记不住这个顺序,或者想只赋值其中的几个参数的时候,就不一定要按照定义的顺序来了,我们可以使用关键字参数来定义。关键字参数就是在调用的时候使用`关键字=值`的定义形式,这样解释器就能够自动的关联到对应的形参了。
|
||||||
|
|
||||||
|
看个例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def info(name, age):
|
||||||
|
print("姓名:%s,年龄:%d" % (name, age))
|
||||||
|
info(age=18, name="小白")
|
||||||
|
```
|
||||||
|
|
||||||
|
运行后可以看到,也是能够正确的匹配的。
|
||||||
|
|
||||||
|
如果我们在调用时,有时候用位置参数,有时候用关键字参数调用,可以吗?答案是可以的。但我们需要注意一个原则,就是位置参数必须写在关键字参数之前,否则解释器会搞不清你要将传入的参数赋值给哪个形参,导致报错。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def info(name, age, sex):
|
||||||
|
print("姓名:%s,年龄:%d,性别:%s" % (name, age, sex))
|
||||||
|
# 这样写会报错:
|
||||||
|
# info(age=18, sex="男", "小白")
|
||||||
|
# 正确的写法
|
||||||
|
info("小白", sex="男", age=18)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ---- | ------------------------- |
|
||||||
|
| info | information信息的简写形式 |
|
||||||
|
| name | 姓名 |
|
||||||
|
| age | 年龄 |
|
||||||
|
| sex | 性别 |
|
||||||
|
|
||||||
25
chapter5/5-5 python3小白课:参数默认值.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# python3小白课:参数默认值
|
||||||
|
|
||||||
|
在某些情况下,我们还能给函数在定义时设定参数的默认值,这样在调用的时候,我们可以做到当不传入参数时,则自动使用默认值,如果传入参数,则使用传入的参数,大大丰富了我们的业务场景。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def info(name, age=18, sex="男"):
|
||||||
|
print("姓名:%s,年龄:%d,性别:%s" % (name, age, sex))
|
||||||
|
info("小白")
|
||||||
|
info("小黑", 20, "女")
|
||||||
|
info("小红", sex="女")
|
||||||
|
```
|
||||||
|
|
||||||
|
定义默认值的方式很简单,在定义形参的时候使用`形参名=默认值`的方式定义即可。需要注意的是,定义了默认值的参数必须放在没有定义默认值的参数的后面,还是那个解释器不好找不好对应参数的问题。
|
||||||
|
|
||||||
|
这里我们给两个参数定义了默认值,它们就变成了`选填参数`,在实际调用的时候,就只需要传递第一个参数即可,第一个参数没有定义默认值,所以我们也称之为`必填参数`。
|
||||||
|
|
||||||
|
当然我们也可以几个参数都赋值,这样就会应用我们赋值进去的值。
|
||||||
|
|
||||||
|
结合我们学习过的关键字参数,我们还可以跳着赋值,比如只赋值第一、第三个值,这就是关键字参数赋值的另一种运用场景。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 在一些别人定义好的函数当中,可能也会大量的定义包含默认值的参数,使用位置参数+关键字参数结合的调用方法,就可以很方便的调用函数了。
|
||||||
|
|
||||||
101
chapter5/5-6 python3小白课:参数收集.md
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
# python3小白课:参数收集
|
||||||
|
|
||||||
|
### 普通参数收集
|
||||||
|
|
||||||
|
python跟很多编程语言一样,支持定义个数可变的参数,这样定义起来很方便,也能支持处理多个传入的参数。
|
||||||
|
|
||||||
|
在定义形参的时候,我们可以在形参前面添加一个`*`星号用来表示这个形参支持接收多个参数值,多个参数值会自动组装成元组并传入,在函数内部我们就可以使用处理元组的方式来处理传入参数了。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def info(name, *nickname):
|
||||||
|
print(f"您的名字为:{name}")
|
||||||
|
print(f"您的昵称有这些:{nickname}")
|
||||||
|
info("小白", "little bai", "白白", "小白白", "超级白")
|
||||||
|
```
|
||||||
|
|
||||||
|
这里我们使用了f-string来格式化文本,这里的第一个参数被赋值给`name`这个形参,而后面不论增加赋值多少个参数,都会组合成元组,赋值给`nickname`,需要注意的是,在函数内部调用`nickname`的时候,不需要带`*`号。
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> 这种带一个`*`号的能收集参数的形参在同一个函数中仅能定义一个,因为多了解释器就不好识别并自动分配了。
|
||||||
|
|
||||||
|
这样的形参还能放在前面,我们看个例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def info(*nickname, name):
|
||||||
|
print(f"您的名字为:{name}")
|
||||||
|
print(f"您的昵称有这些:{nickname}")
|
||||||
|
info("little bai", "白白", "小白白", "超级白", name="小白")
|
||||||
|
```
|
||||||
|
|
||||||
|
由于加`*`的形参支持读取可变个数的参数,因此其他的参数,解释器默认不能正常找到,如果我们要赋值给name参数,就必须使用关键字参数,而关键字参数需要在调用参数的最后来写,所以就写成了我们上述代码的样子。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 关键字参数收集
|
||||||
|
|
||||||
|
除了之前一个`*`的普通关键字收集,python函数在定义时,还支持在形参前加两个`*`号,即`**形参名`,这样写后,会将传入的关键字参数收集成字典,在函数内部可以调用。
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> 同样的,在同一个函数定义中,也只允许有一个关键字参数收集的参数定义。
|
||||||
|
>
|
||||||
|
> 不过,关键字参数的收集可以跟普通参数收集同时存在。
|
||||||
|
|
||||||
|
具体的使用大家可以根据自己的业务场景来设计,我们来看个简单的使用。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def info(name, *nickname, **score):
|
||||||
|
print(f"您的名字为:{name}")
|
||||||
|
print(f"您的昵称有这些:{nickname}")
|
||||||
|
print(f"您的成绩为:{score}")
|
||||||
|
info("小白", "little bai", "白白", "小白白", "超级白", 语文=89, 数学=99)
|
||||||
|
```
|
||||||
|
|
||||||
|
你也可以在函数内部使用字典的方法来获取内容。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 逆向参数收集
|
||||||
|
|
||||||
|
除了前面讲的正向的参数收集,python函数定义还支持逆向参数收集。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def info(name, nickname):
|
||||||
|
print(f"您的名字为:{name}")
|
||||||
|
print(f"您的昵称为:{nickname}")
|
||||||
|
a = ["小白", "白白"]
|
||||||
|
info(*a)
|
||||||
|
```
|
||||||
|
|
||||||
|
我们再来看一个传入字典的逆向收集。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def info(name, nickname, score):
|
||||||
|
print(f"您的名字为:{name}")
|
||||||
|
print(f"您的昵称为:{nickname}")
|
||||||
|
print(f"您的成绩为:{score}")
|
||||||
|
a = {
|
||||||
|
"name": "小白",
|
||||||
|
"nickname": "白白",
|
||||||
|
"score": 94
|
||||||
|
}
|
||||||
|
info(**a)
|
||||||
|
```
|
||||||
|
|
||||||
|
这样函数就会自动寻找字典中的键来匹配了。我尝试了一下,如果字典中多定义一个键,发现会报错的。所以函数需要哪几个,就传入哪几个键的字典就好了。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| -------- | ---------- |
|
||||||
|
| nickname | 昵称,外号 |
|
||||||
|
| name | 姓名 |
|
||||||
|
| score | 成绩 |
|
||||||
88
chapter5/5-7 python3小白课:变量作用域.md
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
# python3小白课:变量作用域
|
||||||
|
|
||||||
|
我们定义的变量,是有作用域范围的。作用域是什么呢?就是这个变量在哪里能被调用,在哪里不能。
|
||||||
|
|
||||||
|
就拿我们学过的没在函数里面直接定义的变量和在函数内部定义的变量来说,它们的作用域就不同。
|
||||||
|
|
||||||
|
我们分成如下两种:
|
||||||
|
|
||||||
|
* 全局变量。在函数外部定义的全局可用的变量。
|
||||||
|
* 局部变量。在函数内部定义的,也包括参数,仅在函数内部可调用的变量。
|
||||||
|
|
||||||
|
每次函数在执行时,系统会自动给这个函数的调用分配一块临时内存空间用来存储局部变量,当函数调用结束,这块内存空间就会被释放,局部变量也就失效了。
|
||||||
|
|
||||||
|
但全局变量是在python脚本运行时分配的内存空间,在函数外可以调用,在函数内也可以调用的。
|
||||||
|
|
||||||
|
我们来看点例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
name = "小白"
|
||||||
|
def test():
|
||||||
|
print(name)
|
||||||
|
test()
|
||||||
|
```
|
||||||
|
|
||||||
|
运行后可以发现,我们能在函数中访问到全局变量。
|
||||||
|
|
||||||
|
我们再来看下如下代码:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
name = "小白"
|
||||||
|
def test():
|
||||||
|
name = "小黑"
|
||||||
|
print(name)
|
||||||
|
test()
|
||||||
|
```
|
||||||
|
|
||||||
|
我们来运行一下,发现输出的结果为`小黑`。
|
||||||
|
|
||||||
|
这是因为在函数内部,重新定义了`name`变量,这样前面定义的全局变量就被遮蔽了。那么我们要不试试先输出全局变量看下?
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
name = "小白"
|
||||||
|
def test():
|
||||||
|
print(name)
|
||||||
|
name = "小黑"
|
||||||
|
print(name)
|
||||||
|
test()
|
||||||
|
```
|
||||||
|
|
||||||
|
运行发现,程序报错了,提示`UnboundLocalError: local variable 'name' referenced before assignment`。即告诉你局部变量`name`还没有定义。还是那个原因,因为在函数内部有定义`name`局部变量的语句,全局变量就被遮蔽了,所以按python的规定,在运行第4行的时候就找不到局部变量`name`了。
|
||||||
|
|
||||||
|
为了避免在函数中对全局变量赋值,我们可以使用`global`语句来声明全局变量,上述错误代码可以改成这样:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
name = "小白"
|
||||||
|
def test():
|
||||||
|
global name
|
||||||
|
print(name)
|
||||||
|
name = "小黑"
|
||||||
|
print(name)
|
||||||
|
test()
|
||||||
|
print(name)
|
||||||
|
```
|
||||||
|
|
||||||
|
我们可以看到,这次不再报错了,并且首先打印出了`小白`,然后打印出了`小黑`,最后打印出了`小黑`。
|
||||||
|
|
||||||
|
这是因为我们把`name`声明为了全局变量,后续一切更改和打印都是基于全局变量的操作,就没有局部变量存在了。
|
||||||
|
|
||||||
|
关于全局变量、局部变量大家可以根据自己的业务需要来再仔细研究一下,但为了大家写代码和理解方便,通常来讲,如果在函数中调用了全局变量的,不要修改它的值,以免造成其他问题。如果确实需要修改全局变量的,可以使用`global`语句将变量定义为全局变量,后续的修改就是基于全局变量的了。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ----------------- | ------------------------------------------------------------ |
|
||||||
|
| test | 测试 |
|
||||||
|
| UnboundLocalError | unbound,unbind的过去式,未绑定的,local,局部,本地,error,错误 |
|
||||||
|
| local | 局部,本地 |
|
||||||
|
| variable | 变量 |
|
||||||
|
| referenced | reference的过去式或被动式,理解为被引用 |
|
||||||
|
| before | 在...之前 |
|
||||||
|
| assignment | 分派,布置,理解为赋值吧这里 |
|
||||||
|
| global | 全球的,全世界的,这里理解为全局 |
|
||||||
166
chapter5/5-8 python3小白课:局部函数.md
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
# python3小白课:局部函数
|
||||||
|
|
||||||
|
### 局部函数定义
|
||||||
|
|
||||||
|
前面我们学习的函数都是在全局范围内定义的,在整个py脚本中都可以调用到它。如果在函数定义的内部再定义函数呢?python也是支持的,这时候的函数就称之为`局部函数`。
|
||||||
|
|
||||||
|
接下来我们把在全局范围定义的函数称为封闭函数,封闭函数内定义的函数称之为局部函数。默认情况下,局部函数对外是隐藏的,仅能在封闭函数内进行调用。但你也可以做出一些变动,让外部也能调用到局部函数来进行计算。
|
||||||
|
|
||||||
|
我们来看个小例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def fengbi(method, num):
|
||||||
|
def add_1(num):
|
||||||
|
return num + 1
|
||||||
|
def add_2(num):
|
||||||
|
return num + 2
|
||||||
|
def add_3(num):
|
||||||
|
return num + 3
|
||||||
|
if method == "add_1":
|
||||||
|
return add_1(num)
|
||||||
|
elif method == "add_2":
|
||||||
|
return add_2(num)
|
||||||
|
elif method == "add_3":
|
||||||
|
return add_3(num)
|
||||||
|
else:
|
||||||
|
return "不支持的方法名"
|
||||||
|
print(fengbi("add_1", 1))
|
||||||
|
print(fengbi("add_2", 1))
|
||||||
|
print(fengbi("add_4", 1))
|
||||||
|
```
|
||||||
|
|
||||||
|
由于直接在内部定义并调用比较简单我们就不举例子了。我们来举一个从外部调用到内部局部函数的方法例子,这里我们定义了一个封闭函数,支持传入方法名,在函数内部首先定义好那几个局部函数方法,后续可以通过if结构判断给的是什么方法,来调用具体的局部函数返回。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 局部函数访问封闭函数中的局部变量
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> 本部分知识比较不常用,可以学习也可以跳过。
|
||||||
|
|
||||||
|
由于我们这里在函数内部又有函数定义,势必有可能会遇到在局部函数中调用到封闭函数中定义的局部变量的情形。此时还是跟之前学习作用域时讲的一样,可以在局部函数中直接调用在封闭函数中定义的局部函数。(这么听起来比较拗口,我们看个例子吧)
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def fengbi():
|
||||||
|
num = 1
|
||||||
|
def add_1():
|
||||||
|
return num + 1
|
||||||
|
print(add_1())
|
||||||
|
fengbi()
|
||||||
|
```
|
||||||
|
|
||||||
|
可见,是可以直接访问的。如果我们在局部函数中修改封闭函数中的局部变量呢?
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def fengbi():
|
||||||
|
num = 1
|
||||||
|
def add_1():
|
||||||
|
print(num)
|
||||||
|
num = 2
|
||||||
|
return num + 1
|
||||||
|
print(add_1())
|
||||||
|
fengbi()
|
||||||
|
```
|
||||||
|
|
||||||
|
这次运行又报错了,报错信息为:`UnboundLocalError: local variable 'num' referenced before assignment`,看起来还是我们讲变量作用域时说过的问题。怎么解决呢?此时我们就不用`global`语句了,因为那是对付全局变量的。我们可以使用`nonlocal`语句来解决,用法跟`global`语句是一致的。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def fengbi():
|
||||||
|
num = 1
|
||||||
|
def add_1():
|
||||||
|
nonlocal num
|
||||||
|
print(num)
|
||||||
|
num = 2
|
||||||
|
return num + 1
|
||||||
|
print(add_1())
|
||||||
|
print(num)
|
||||||
|
fengbi()
|
||||||
|
```
|
||||||
|
|
||||||
|
此时我们会发现,num在上述代码中就一直指代封闭函数中的`num`局部变量了,不会有报错的情况发生,对于`num`的修改也会造成`num`局部变量的值改变。
|
||||||
|
|
||||||
|
如果你对这部分知识感兴趣,可以往下学习我们下面的`函数:前沿`部分。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 函数:前沿
|
||||||
|
|
||||||
|
关于函数的知识,我们还有一些高级内容,但作为入门小白,经过审慎考虑,我认为像市面上一本百科全书一样把一个东西讲得太多太难太细对大家是没有太大帮助的,大家只会学着学着感叹,哇呀,怎么函数这么难?这么多知识这么难记?哇呀,python太难学了我不学了。
|
||||||
|
|
||||||
|
为了避免大家出现这种难过的情绪,我希望大家始终保持必要的学习激情,我们前面讲过的知识,基础运用是非常简单的,如果你对于某一块有兴趣,可以找找网上的资料,进一步自学即可,在入门时不必太过于执着和纠结你听不懂记不住的知识,够用就好。
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> 关于函数的一些更难的知识,我们将会安排在进阶或高级课程中跟大家一起去啃这些硬骨头,它们适合python编程已经有一定基础,想要进一步突破瓶颈的同学。
|
||||||
|
|
||||||
|
这里我们就着前面讲过的内容,再扩展一点点前沿知识,如果你学不会看不懂,请跳过,没有关系的,当你做好了进一步突破瓶颈的准备,比如在一个美好的清晨,你休息得很好,脑袋适合研究点什么,再回过头来听一听你感兴趣的内容。
|
||||||
|
|
||||||
|
\*\*\*华丽的分割线\*\*\*
|
||||||
|
|
||||||
|
好,给大家随便灌了点鸡汤,我们继续讲课。
|
||||||
|
|
||||||
|
函数还有比较高级的定义方法,因为函数本身是一个对象,所以函数本身既可以用于赋值,也可以用于作为调用的参数传进别的函数中,还可以作为其他函数的返回值。
|
||||||
|
|
||||||
|
这里我们来讲个小例子,看下函数作为返回值是怎样的。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def createCounter():
|
||||||
|
n = 0
|
||||||
|
def counter():
|
||||||
|
nonlocal n
|
||||||
|
n += 1
|
||||||
|
return n
|
||||||
|
return counter
|
||||||
|
|
||||||
|
# 验证计数器
|
||||||
|
mycounter = createCounter()
|
||||||
|
|
||||||
|
for i in range(5):
|
||||||
|
print(mycounter())
|
||||||
|
```
|
||||||
|
|
||||||
|
这是从网上找到的一个小题目,代码也是参考了下网上的朋友的,做了一些优化修改。
|
||||||
|
|
||||||
|
我们的题目是定义一个函数计数器,这个计数器内部可以存档一个计数,每次调用函数的时候,可以实现计数次数的增长。
|
||||||
|
|
||||||
|
首先我们可以先跑一下运行结果,可以看到每次输出的结果都会自增1,分别输出`1, 2, 3, 4, 5`这几个值来。
|
||||||
|
|
||||||
|
然后我们来分析一下代码。
|
||||||
|
|
||||||
|
首先我们定义了一个`createCounter`创建计数器的函数,这个函数内部呢,定义了一个`n`变量,这个变量就是计数器的值了。接着我们定义了一个`counter`的局部函数,这个函数就使用了我们前面讲到的`nonlocal`语句,申明局部函数用到的`n`变量是用的封闭函数中的那个,这样后续赋值就不会重新定义一个`n`变量了,实现了访问变量的目的。接下来在局部函数内将变量的值自增1,并返回最新的结果。
|
||||||
|
|
||||||
|
需要注意的是,这个`createCounter`函数的return语句返回的是一个函数,如果返回函数`counter`,直接写函数名即可,没有括号什么的。
|
||||||
|
|
||||||
|
这样返回如何调用呢?首先运行这个`createCounter`函数,将它的返回值赋值给一个变量`mycounter`,此时`mycounter`就有了`counter`函数的功能了。接下来在调用时,只需要调用`mycounter`这个函数即可。
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> 这是一种闭包的概念,如果我们的n是一个全局变量,那么这个计数器在每次使用时,你还需要在自己的代码中定义它,或者需要查看这个函数内部的代码实现。
|
||||||
|
>
|
||||||
|
> 当使用闭包后,变量n的作用域仅限于封闭函数中,这在某些时候就给了使用者一些便利。
|
||||||
|
|
||||||
|
在python脚本运行期间,每次调用,我们会发现`n`的值,是在不断自增的,你可以理解为,我们只访问了`counter`函数,并没有再次访问`createCounter`函数,所以这个`n`不会重新赋值,而`counter`函数又能访问到`n`并自增,这样就实现了一个计数器的效果。
|
||||||
|
|
||||||
|
是不是很有意思呢?
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> 关于函数还有其他知识点,我们在入门课就不跟大家讲那么深那么难了,感兴趣的同学可以关注我们的进阶或高级课程学习或者自行网上查阅资料学习。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------------- | ------------------------------------------------------------ |
|
||||||
|
| method | 方法 |
|
||||||
|
| nonlocal | non为否定前缀,local为局部的,在这里理解为非局部的 |
|
||||||
|
| createCounter | create创建,Counter计数器,count计数,合起来理解为创建计数器 |
|
||||||
|
| counter | 计数器 |
|
||||||
|
| mycounter | my我的,理解为我的计数器 |
|
||||||
8
chapter5/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# 五、自定义函数
|
||||||
|
|
||||||
|
恭喜你,又上了一个台阶!如今,我们可以自如地使用python的各种类型也可以使用流程控制让我们的代码更加智能了,接下来我们需要学习什么呢?
|
||||||
|
|
||||||
|
大家还记得我们之前的课程中一直在使用的python内置的一些函数、方法吗?它们是怎么来的呢?它们够用了吗?我们可不可以自己定义自己的函数、方法,实现我们自定义的需求?
|
||||||
|
|
||||||
|
本章节将带你拉开全新的大门。
|
||||||
|
|
||||||
102
chapter6/6-1 python3小白课:模块的导入.md
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
# python3小白课:模块的导入
|
||||||
|
|
||||||
|
python安装后,就自带有许多内置的模块,我们可以导入它们来增强我们的代码功能。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> python安装非自带的需要你联网下载安装或离线安装的后续我们称之为三方库,导入三方库的方法和导入内置模块的方法一致,区别在于本机使用这些三方库前需要先安装而已。
|
||||||
|
|
||||||
|
模块的导入通常有以下两种语法:
|
||||||
|
|
||||||
|
* import 模块名1[ as 别名1], 模块名2[ as 别名2], ...
|
||||||
|
* from 模块名 import 成员名1[ as 别名1], 成员名2[ as 别名2], ...
|
||||||
|
|
||||||
|
上述语法中的方括号表示里面的内容可选填。
|
||||||
|
|
||||||
|
关于单词的含义大家可以看一下本节课结尾的单词释义。
|
||||||
|
|
||||||
|
* 第一种导入方式为导入整个模块,如果你导入多个模块,中间使用`,`隔开。有时候模块名你不喜欢或太长不好打不好记,你也可以用`as`给导入的模块指定别名,在后续的代码中可以通过别名来调用模块命令。后续代码中调用时,需要使用`模块名或别名.成员名`的方式调用。
|
||||||
|
* 第二种导入方式是从某个模块里导入成员,成员可以是函数,也可以是变量、类(关于类的知识,我们将在后面的课程中讲解)等其他东西。成员也可以一样的设置别名,支持导入多个成员。后续代码中调用时,可以直接使用`成员名`来进行调用。如果你需要导入模块中的所有成员,也可以写成`from 模块名 import *`,`*`代表所有,但我们一般不推荐这么做。
|
||||||
|
|
||||||
|
> [!warning]
|
||||||
|
>
|
||||||
|
> 使用`from 模块名 import *`语句进行模块导入,会让代码降低可读性,别人在读你的代码时,会不知道你一股脑的导入了什么。另外,当模块中比如有函数的名字跟你的代码中定义的函数名字相同时,也会受到影响。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 为什么有两种导入方式呢?
|
||||||
|
|
||||||
|
我想是因为重名的原因,有些模块定义的函数等可能跟你自己在代码中定义的重名,使用第一种方式就不会起冲突。但也有时候模块命令使用第一种方式调用太长太繁琐,自己的代码中也没有什么冲突的,那么第二种方式是一种省事的选择。具体使用哪一种,可以根据自己的业务需要来决定。
|
||||||
|
|
||||||
|
我们来看点例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
print(sys.argv[0])
|
||||||
|
print(os.listdir("."))
|
||||||
|
```
|
||||||
|
|
||||||
|
这里我们导入了自带的`sys`和`os`两个模块(有的时候习惯叫法可能也会叫做包,如果后续我称之为包,也不要奇怪)。它们的作用,你可以自行使用`help`命令查看。
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> 记得模块需要先导入,才能看帮助文档。
|
||||||
|
|
||||||
|
导入后,可以使用`模块名.成员名`的形式调用,如果是函数,还能传入参数,如果是可迭代对象(比如是个列表、元组等),可以传入索引等等。我们这里尝试了这俩模块里的俩命令。第一个是获取python程序运行时的命令行参数,第一个元素为python脚本的名字。第二个是获取指定路径的文件和文件夹列表,传入的参数表示脚本所在的当前文件夹。
|
||||||
|
|
||||||
|
可以看到,引用模块非常之简单。我们再来看下其他写法:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
import sys as s
|
||||||
|
import os as o
|
||||||
|
print(s.argv[0])
|
||||||
|
print(o.listdir("."))
|
||||||
|
```
|
||||||
|
|
||||||
|
指定别名之后,可以使用别名。
|
||||||
|
|
||||||
|
我们来看一下另一种导入方式的例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
from sys import argv as aaa
|
||||||
|
print(aaa[0])
|
||||||
|
```
|
||||||
|
|
||||||
|
可以看到,使用第二种导入方式可以直接导入成员,也能指定成员的别名,后续调用时,只需要使用成员名或者指定的别名即可调用,无需添加模块名。
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> 如果没有指定别名,需要注意成员名跟你自己写的代码中定义的成员不能重名。
|
||||||
|
>
|
||||||
|
> 如果指定了别名,需要注意指定的别名跟你自己写的代码中定义的成员不能重名,此时模块的原成员名可以重名没关系。
|
||||||
|
|
||||||
|
我们再来看个例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
from sys import *
|
||||||
|
print(argv[0])
|
||||||
|
```
|
||||||
|
|
||||||
|
这里我们使用了`from 模块名 import *`的写法,导入了`sys`模块的所有成员,也可以直接调用里面的成员。但你需要很了解里面有什么命令,降低了可读性,而且也只能使用内部成员原本的名字,也可能导入了一些不必要的成员造成程序有重名的风险。所以一般情况下,我们不太推荐这么写。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------- | ------------------------------------------------------------ |
|
||||||
|
| import | 导入 |
|
||||||
|
| as | 作为... |
|
||||||
|
| from | 从...哪里 |
|
||||||
|
| sys | system系统的简写 |
|
||||||
|
| os | operating system操作系统的简写 |
|
||||||
|
| argv | 查一下,为argument vector,参数向量,指的应该是传入的参数列表 |
|
||||||
|
| listdir | list列举,列表,dir,directory目录,命令可以枚举给定路径的文件和文件夹 |
|
||||||
|
|
||||||
260
chapter6/6-10 python3小白课:虚拟环境使用.md
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
# python3小白课:虚拟环境使用
|
||||||
|
|
||||||
|
上节课我们安装好了虚拟环境,这节课我们来教会大家基本的使用,关于其他使用命令,日常不常用的,我就不讲解了,讲多了大家也记不住。
|
||||||
|
|
||||||
|
接着上节课我们打开了一个cmd窗口对吧,目前还是没有任何虚拟环境的。
|
||||||
|
|
||||||
|
### 创建虚拟环境
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
mkvirtualenv test
|
||||||
|
```
|
||||||
|
|
||||||
|
回车,就创建好了,你可以使用`workon`查看到生成了一个名为`test`的虚拟环境,并且直接激活进入了该虚拟环境。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
这里`mkvirtualenv`就是创建新的虚拟环境的命令,你记住`mk`即可,应该是英文单词`make`制造。后面跟随的是空格和虚拟环境的名字,它会在之前的`WORKON_HOME`路径下创建一个以这个名字命名的文件夹,所以你的名字也别太花哨了,文件夹名不支持的字符不要作为名字哦~比如我们这里就是名字为`test`,到资源管理器中查看该路径,确实该文件夹已经创立。
|
||||||
|
|
||||||
|
这种命令的写法默认会使用你`当前的系统python的版本`创建一个虚拟环境。
|
||||||
|
|
||||||
|
像这种创建方法你可以直接进入到新虚拟环境中,大家可以看到在上图中命令提示符最后一行的最左侧多了`(test)`这样的标识,这就是已进入虚拟环境的标志。在虚拟环境进入后,我们可以输入`python`进入当前虚拟环境版本的`python shell`,也可以使用`python py文件名`或`pip`命令来使用虚拟环境。这时你若使用`pip install 包名`命令,安装的包只会存在于虚拟环境,不会安装到系统的python环境,这就能让项目的三方包环境非常整洁干净,未来你需要看一下这个项目用了哪几个三方包,版本号是多少的时候就会极其方便。
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> 如果你感兴趣,可以到虚拟环境的存放目录,看一下虚拟环境跟普通已安装好的python有什么区别。
|
||||||
|
>
|
||||||
|
> 可以发现,其实就是将已安装的python进行虚拟化,复制一份,文件夹也做了一些优化,让它可以作为独立环境运行。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 退出已激活的虚拟环境
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 创建好了虚拟环境,怎么退出呢?
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
deactivate
|
||||||
|
```
|
||||||
|
|
||||||
|
`activate`是激活的意思,加上否定前缀就是不激活咯,就是退出虚拟环境了,而`activate`也是一个激活的命令,后面我们会讲到。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
如图,命令提示符最后一行的最左侧恢复了正常。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 激活或切换虚拟环境
|
||||||
|
|
||||||
|
如上面的截图例子所示,我们的当前目录在`C:\Users\xueshanlinghu`这个路径下,我们可以切换当前工作目录到你要激活的那个虚拟环境目录下的`Scripts`文件夹下,如`E:\ProgramFiles\virtualpython\test\Scripts`,在这里我们可以运行
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
activate
|
||||||
|
```
|
||||||
|
|
||||||
|
即可激活虚拟环境。
|
||||||
|
|
||||||
|
但我一般很少这样操作。还记得我们上节课学习过的可以通过`workon`命令查看当前有多少个虚拟环境吗,它会把所有虚拟环境的名字罗列出来。你如果知道你要进入哪个虚拟环境的名字,可以在任意工作目录下输入命令:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
workon test
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
这样我们可以更轻松进行虚拟环境的激活了,`test`这个虚拟环境名你可以换成你的。通常推荐大家这样用。
|
||||||
|
|
||||||
|
顺便,我们来看一下`pip list`和`pip --version`的运行效果:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
可以看到,都是单独的。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 删除虚拟环境
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 当某虚拟环境不准备再使用了怎么办?
|
||||||
|
|
||||||
|
那就删除呗。
|
||||||
|
|
||||||
|
你可以到虚拟环境的文件夹将该虚拟环境文件夹直接删除即可。
|
||||||
|
|
||||||
|
我个人一般会用命令删除:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
rmvirtualenv test
|
||||||
|
```
|
||||||
|
|
||||||
|
这样就可以把`test`这个虚拟环境删除了。其实就是前面加了`rm`,应为`remove移除`的意思,很好理解和记忆。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 安装其他版本的python的虚拟环境
|
||||||
|
|
||||||
|
这里我们的系统环境python是3.8.2版本,我们拿安装python2.7.18和python3.6.6版本的虚拟环境为例跟大家做讲解,其他的可以举一反三。
|
||||||
|
|
||||||
|
安装包下载(我也会在课程中提供给大家,这里均为64位的安装包为例):
|
||||||
|
|
||||||
|
* python3.6.6:[https://www.python.org/ftp/python/3.6.6/python-3.6.6-amd64.exe](https://www.python.org/ftp/python/3.6.6/python-3.6.6-amd64.exe)
|
||||||
|
* python2.7.18:[https://www.python.org/ftp/python/2.7.18/python-2.7.18.amd64.msi](https://www.python.org/ftp/python/2.7.18/python-2.7.18.amd64.msi)
|
||||||
|
|
||||||
|
#### python3.6.6虚拟环境创建
|
||||||
|
|
||||||
|
安装很简单,跟之前学习的差不多,需要注意的是,不要选择添加到环境变量就可以了。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
这里比如我安装在`E:\ProgramFiles\virtualpython\purepython\python3.6.6`目录下。
|
||||||
|
|
||||||
|
安装完成后复制一份该文件夹到当前目录下。复制后,就可以到系统程序与功能-卸载或更改程序那里,将python3.6.6版本卸载掉了,这样可以让系统不那么乱,更绿色。卸载后,将刚才备份的文件夹重命名跟复制前`python3.6.6`一样。
|
||||||
|
|
||||||
|
完成后即可在cmd输入命令创建了,例如:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
mkvirtualenv -p "E:\ProgramFiles\virtualpython\purepython\python3.6.6\python.exe" py36
|
||||||
|
mkvirtualenv --python "E:\ProgramFiles\virtualpython\purepython\python3.6.6\python.exe" py36
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 上面两种方法均可以创建,任选一种即可,我个人喜欢第一种。-p参数后面跟上你安装的其他版本python的python.exe解释器的绝对路径,如果路径中没有空格可以不加引号,如果有需要加上引号,我建议你都加上就好了。写完后再写上需要创建的虚拟环境名称即可。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
你看,成功了!
|
||||||
|
|
||||||
|
#### python2.7.18虚拟环境创建
|
||||||
|
|
||||||
|
由于安装包是msi的后缀,所以稍微跟python3的有一点点小区别。
|
||||||
|
|
||||||
|
安装时注意点我就不多说了,参考我们之前安装python的时候,需要注意的是不要选择添加到环境变量,默认就是不选的,按默认的就行:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
这里我安装到了`E:\ProgramFiles\virtualpython\purepython\python2.7.18`这个文件夹下。复制一下这个文件夹。
|
||||||
|
|
||||||
|
接下来这一步很重要,你需要到`C:\Windows\System32`这个目录,搜索`python27.dll`这个文件并拷贝到另一个地方备份。
|
||||||
|
|
||||||
|
然后到系统程序与功能-卸载或更改程序那里将python2.7.18版本卸载了,卸载完成后,将刚才复制备份的文件夹修改回`python2.7.18`这个文件夹名。
|
||||||
|
|
||||||
|
将`python27.dll`这个文件还原到`C:\Windows\System32`这个目录。
|
||||||
|
|
||||||
|
这样,绿色版的python2.7.18就制作好了。
|
||||||
|
|
||||||
|
你可以输入命令来创建一个python2.7的虚拟环境了:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
mkvirtualenv -p "E:\ProgramFiles\virtualpython\purepython\python2.7.18\python.exe" py27
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
可以看到,确实使用了python2.7.18的版本。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 在python2语法中,打印输出使用的是`print 要打印的内容`这样的写法,而在python3中,变成了`print(要打印的内容)`,你可以很好地辨别用的是python2还是python3,请知悉。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 冻结项目所用的包
|
||||||
|
|
||||||
|
之前我们在学习解锁心仪的三方包的时候,学习过可以使用`pip freeze > requirements.txt`命令来冻结所用到的三方包的情况,我们来举个例子。
|
||||||
|
|
||||||
|
我们分别在cmd中输入下面的命令:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
workon py36 # 切换py36虚拟环境
|
||||||
|
pip install requests # 安装requests三方包及相关包
|
||||||
|
pip list # 查看目前的pip列表
|
||||||
|
pip freeze > requirements.txt # 冻结目前所用的所有三方包保存到文件
|
||||||
|
type requirements.txt # cmd中打开文本文件并打印输出所有内容
|
||||||
|
```
|
||||||
|
|
||||||
|
运行结果如下:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
Microsoft Windows [版本 10.0.18363.778]
|
||||||
|
(c) 2019 Microsoft Corporation。保留所有权利。
|
||||||
|
|
||||||
|
C:\Users\xueshanlinghu>workon py36
|
||||||
|
(py36) C:\Users\xueshanlinghu>pip install requests
|
||||||
|
Collecting requests
|
||||||
|
Downloading requests-2.23.0-py2.py3-none-any.whl (58 kB)
|
||||||
|
|████████████████████████████████| 58 kB 363 kB/s
|
||||||
|
Collecting certifi>=2017.4.17
|
||||||
|
Using cached certifi-2020.4.5.1-py2.py3-none-any.whl (157 kB)
|
||||||
|
Collecting chardet<4,>=3.0.2
|
||||||
|
Using cached chardet-3.0.4-py2.py3-none-any.whl (133 kB)
|
||||||
|
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1
|
||||||
|
Using cached urllib3-1.25.9-py2.py3-none-any.whl (126 kB)
|
||||||
|
Collecting idna<3,>=2.5
|
||||||
|
Using cached idna-2.9-py2.py3-none-any.whl (58 kB)
|
||||||
|
Installing collected packages: certifi, chardet, urllib3, idna, requests
|
||||||
|
Successfully installed certifi-2020.4.5.1 chardet-3.0.4 idna-2.9 requests-2.23.0 urllib3-1.25.9
|
||||||
|
|
||||||
|
(py36) C:\Users\xueshanlinghu>pip list
|
||||||
|
Package Version
|
||||||
|
---------- ----------
|
||||||
|
certifi 2020.4.5.1
|
||||||
|
chardet 3.0.4
|
||||||
|
idna 2.9
|
||||||
|
pip 20.0.2
|
||||||
|
requests 2.23.0
|
||||||
|
setuptools 46.1.3
|
||||||
|
urllib3 1.25.9
|
||||||
|
wheel 0.34.2
|
||||||
|
|
||||||
|
(py36) C:\Users\xueshanlinghu>pip freeze > requirements.txt
|
||||||
|
|
||||||
|
(py36) C:\Users\xueshanlinghu>type requirements.txt
|
||||||
|
certifi==2020.4.5.1
|
||||||
|
chardet==3.0.4
|
||||||
|
idna==2.9
|
||||||
|
requests==2.23.0
|
||||||
|
urllib3==1.25.9
|
||||||
|
|
||||||
|
(py36) C:\Users\xueshanlinghu>
|
||||||
|
```
|
||||||
|
|
||||||
|
换一个项目,所用的包不同,则你可以再创建一个新项目的虚拟环境,在里面任意折腾,当不需要时,删除该虚拟环境即可。
|
||||||
|
|
||||||
|
我们退出虚拟环境,再看一下系统python的`pip list`有没有什么变化,结果如下:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
(py36) C:\Users\xueshanlinghu>deactivate
|
||||||
|
|
||||||
|
C:\Users\xueshanlinghu>pip list
|
||||||
|
Package Version
|
||||||
|
--------------------- -------
|
||||||
|
appdirs 1.4.3
|
||||||
|
distlib 0.3.0
|
||||||
|
filelock 3.0.12
|
||||||
|
pip 20.0.2
|
||||||
|
setuptools 46.1.3
|
||||||
|
six 1.14.0
|
||||||
|
virtualenv 20.0.18
|
||||||
|
virtualenvwrapper-win 1.2.6
|
||||||
|
|
||||||
|
C:\Users\xueshanlinghu>
|
||||||
|
```
|
||||||
|
|
||||||
|
可以看到,只有之前安装`virtualenv`的一些相关的包,清清爽爽,干干净净。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------------ | -------------------------------------------- |
|
||||||
|
| mkvirtualenv | mk,make创建、制造的简写,virtualenv虚拟环境 |
|
||||||
|
| deactivate | 让...停止工作,就是退出激活的意思 |
|
||||||
|
| activate | 激活 |
|
||||||
|
| rmvirtualenv | rm,remove移除的简写,virtualenv虚拟环境 |
|
||||||
119
chapter6/6-2 python3小白课:自己写模块.md
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
# python3小白课:自己写模块
|
||||||
|
|
||||||
|
### 模块定义
|
||||||
|
|
||||||
|
要自己写一个模块,语法也非常非常简单,其实模块就是一个自己写的python脚本文件!你可以在一个py文件中定义变量、函数、类等等内容,保存起来,就是一个模块了。模块的名字就是这个py文件的文件名!
|
||||||
|
|
||||||
|
因此这节课我们来学习定义一个简单的自己的模块吧!
|
||||||
|
|
||||||
|
定义模块练习我们就定义一个简单的函数吧,将下面的代码保存成`mymodule.py`文件吧:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
|
||||||
|
def add_1(num):
|
||||||
|
return num + 1
|
||||||
|
```
|
||||||
|
|
||||||
|
这样我们就定义好了一个最简单的模块,里面的函数就是其中一个成员,我们可以在别的py文件中导入并使用,将你的模块文件跟你的测试py文件放在同一个目录下即可。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 模块的说明文档
|
||||||
|
|
||||||
|
除了可以给函数添加说明文档,你还可以给模块添加说明文档。在所有可执行的代码前面使用长文本字符串定义说明文档即可,我们在刚才的文件前面补充一下:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
|
||||||
|
"""
|
||||||
|
模块名:mymodule
|
||||||
|
小白同学的第一个模块
|
||||||
|
这是说明文档
|
||||||
|
命令:add_1(num)
|
||||||
|
将传入的数字加上1后返回
|
||||||
|
"""
|
||||||
|
|
||||||
|
def add_1(num):
|
||||||
|
"""将传入的数字加上1后返回,这是函数的文档"""
|
||||||
|
return num + 1
|
||||||
|
```
|
||||||
|
|
||||||
|
编写完成后,我们可以在其他地方导入该模块,使用`help`命令即可查看模块帮助文档,也可以访问模块的`__doc__`属性。
|
||||||
|
|
||||||
|
比如我们再在`同一个目录下`定义一个`test.py`文件:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
import mymodule
|
||||||
|
|
||||||
|
help(mymodule)
|
||||||
|
print("*" * 40)
|
||||||
|
print(mymodule.__doc__)
|
||||||
|
|
||||||
|
print(mymodule.add_1(1))
|
||||||
|
```
|
||||||
|
|
||||||
|
我们还顺便测试了一下里面定义的函数。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 成功运行后,我们可以发现在模块所在目录下看到一个名为`__pycache__`的文件夹,里面会为模块生成一个`.pyc`文件,这是python为模块编译生成的字节码文件,是用来提升模块运行效率的,你知道并忽略它即可,将模块复制走的时候无需带上它。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 模块的测试代码
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 模块写好之后,只能通过外部导入模块来进行测试吗?
|
||||||
|
|
||||||
|
非也,别忘了模块本身也是一个python脚本文件,它自己也能跑起来。我们可以自行在模块的文件中定义一些函数或者执行语句来测试我们编写的模块,但如果写的是执行语句的话,这些语句会在导入模块时运行一遍。但我们在使用时,是不希望执行测试代码的。
|
||||||
|
|
||||||
|
别急,python中有一种不错的机制可以满足你的需求。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> python模块有一个内置的变量`__name__`,如果直接执行模块的代码,这个变量的值就为`__main__`,但如果是通过外部导入模块的方式,这个变量的值为模块的名字。
|
||||||
|
|
||||||
|
利用这个机制,我们可以在模块的结尾编写流程控制来区分是导入模块还是直接执行,看下如下模块代码:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
|
||||||
|
"""
|
||||||
|
模块名:mymodule
|
||||||
|
小白同学的第一个模块
|
||||||
|
这是说明文档
|
||||||
|
命令:add_1(num)
|
||||||
|
将传入的数字加上1后返回
|
||||||
|
"""
|
||||||
|
|
||||||
|
def add_1(num):
|
||||||
|
"""将传入的数字加上1后返回,这是函数的文档"""
|
||||||
|
return num + 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print("这是在测试模块")
|
||||||
|
help(__name__)
|
||||||
|
print("*" * 40)
|
||||||
|
print(__doc__)
|
||||||
|
print(add_1(100))
|
||||||
|
```
|
||||||
|
|
||||||
|
这样,如果是直接运行这段代码,就会运行17~21行的部分代码了,但如果是导入模块的话,这部分代码就不会被执行。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> `if __name__ == '__main__':`这种写法,在你的一个普通的py脚本文件中也可以这么用的,不一定是在模块中才能用。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| -------- | ---------------------------------- |
|
||||||
|
| mymodule | my我的,module模块,我的模块的意思 |
|
||||||
|
| name | 名字 |
|
||||||
|
| main | 主要的 |
|
||||||
119
chapter6/6-3 python3小白课:导入模块详解.md
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
# python3小白课:导入模块详解
|
||||||
|
|
||||||
|
### 哪儿导入我们的模块?
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 编写好模块之后,我们可以把模块放在哪里供我们的其他py程序导入和使用?
|
||||||
|
|
||||||
|
我们通常有两种方式:
|
||||||
|
|
||||||
|
* 使用环境变量
|
||||||
|
* 从默认模块加载路径导入
|
||||||
|
|
||||||
|
#### 使用环境变量
|
||||||
|
|
||||||
|
这种方式我不太用,说的是可以在系统环境变量中,添加一个名为`PYTHONPATH`的环境变量,这个变量的值支持多个路径值,可以支持在多个路径寻找。比如我们可以设置`d:\test`进去试一试。如果加入`用户变量`则只对当前用于生效,如果加入`系统变量`则可以对所有用户生效。`系统变量`的查找优先顺序大于`用户变量`。
|
||||||
|
|
||||||
|
#### 从默认模块加载路径导入
|
||||||
|
|
||||||
|
我们可以通过`sys.path`查看模块的默认导入路径有哪些。
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
import sys, pprint
|
||||||
|
# pprint可以替代print函数,在需要输出的内容较多时,可以更友好的显示打印结果
|
||||||
|
pprint.pprint(sys.path)
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 可以看到,默认都会从我们的脚本所在的同一个目录导入,多数时候,我们放在同一个目录下是最方便的。
|
||||||
|
|
||||||
|
同时也会有些python的安装目录等。
|
||||||
|
|
||||||
|
在这里,我们需要注意到一个目录,今后我们安装一些三方库的时候,通常都是会安装到python安装目录下的`lib\site-packages`目录下的,因此如果你需要将自己写的模块放到一个python目录下,通常可以放到这个目录下。
|
||||||
|
|
||||||
|
你还可以临时性扩展这个列表:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
import sys, pprint
|
||||||
|
sys.path.append("d:\\test")
|
||||||
|
pprint.pprint(sys.path)
|
||||||
|
import mymodule
|
||||||
|
|
||||||
|
help(mymodule)
|
||||||
|
print("*" * 40)
|
||||||
|
print(mymodule.__doc__)
|
||||||
|
|
||||||
|
print(mymodule.add_1(1))
|
||||||
|
```
|
||||||
|
|
||||||
|
这里可以承接我们之前课时中讲过的已写好的模块来测试。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 这样的添加是临时的,运行另外的python脚本程序这个路径就不会再找了,也不会影响系统环境变量等,也是一个比较推荐的编写方式。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 模块的\_\_all\_\_变量
|
||||||
|
|
||||||
|
之前我们讲过,使用`from 模块名 import *`这样的语句会导入模块的所有成员。但有的时候我们不希望我们的每个成员都供外界使用,这时我们可以在模块中定义一个\_\_all\_\_变量,它是一个列表,我们想像外界暴露什么就写进去,没写的就不会暴露。
|
||||||
|
|
||||||
|
我们尝试定义一个`mymodule.py`文件如下:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
def add_1(num):
|
||||||
|
return num + 1
|
||||||
|
def add_2(num):
|
||||||
|
return num + 2
|
||||||
|
def add_3(num):
|
||||||
|
return num + 3
|
||||||
|
|
||||||
|
__all__ = ["add_1", "add_2"]
|
||||||
|
```
|
||||||
|
|
||||||
|
我们再在同一个目录下定义一个`test.py`文件用来测试:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
from mymodule import *
|
||||||
|
print(add_1(1))
|
||||||
|
print(add_2(1))
|
||||||
|
print(add_3(1))
|
||||||
|
```
|
||||||
|
|
||||||
|
此时运行它,就会发现报错,会发现`add_3`这个命令找不到。这个变量就实现了它的意义。
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 如果定义了这个变量,还是需要使用没在列表里面的成员怎么办呢?
|
||||||
|
|
||||||
|
* 可以使用`import 模块名`导入模块,这样是可以访问到的。
|
||||||
|
* 使用`from 模块名 import 成员名`导入成员,这样也是可以导入的。
|
||||||
|
|
||||||
|
具体大家可以试一下哦~
|
||||||
|
|
||||||
|
参考例子:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
from mymodule import add_1, add_2, add_3
|
||||||
|
print(add_1(1))
|
||||||
|
print(add_2(1))
|
||||||
|
print(add_3(1))
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------------- | ------------------------------------------------------------ |
|
||||||
|
| PYTHONPATH | path,路径,pythonpath在这里是python脚本查找模块的路径 |
|
||||||
|
| path | 路径 |
|
||||||
|
| lib | 通常指程序的一些库文件 |
|
||||||
|
| site-packages | site网站,站点,packages,package包的复数形式,合起来理解为一些三方包吧 |
|
||||||
29
chapter6/6-4 python3小白课:包是什么.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# python3小白课:包是什么
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> python中除了模块,还有一中叫做`包`的叫法,那么它究竟是什么呢?
|
||||||
|
|
||||||
|
事实上,我们可以在一个模块中包含可供外界调用的各种成员,但当里面的成员非常多的时候,模块的维护会变得困难。这时候`包(package)`就出现了,它可以把一个冗长模块中的成员拆成多个py文件模块,然后统一放到一个文件夹里,文件夹的名字就是`包名`。后续在使用时,可以像模块几乎一致的语法来使用`包`,如导入模块时,导入文件夹名作为模块名即可。
|
||||||
|
|
||||||
|
从这个角度看,包其实也是一种模块,只不过它比单文件更加好维护和扩展。包是一个文件夹,而且python不是会轻易认任何一个文件夹为包的,我们在定义这个文件夹为`包`的时候,需要在这个文件夹的根目录创建一个文件`__init__.py`。这是一个初始化包的文件,它可以不写任何内容,python遇到这种文件夹的时候就知道它是一个包了。
|
||||||
|
|
||||||
|
导入包跟导入模块是一样的写法,python寻找包的方式也跟我们讲过的导入模块详解中的内容一致,这里就不赘述了。
|
||||||
|
|
||||||
|
在编写包代码的时候,可以仅将模块所有代码写在`__init__.py`这个文件下。此时导入包时,会自动执行该文件中的所有代码。
|
||||||
|
|
||||||
|
另一种方式是在文件夹中将你的模块代码拆分成多个py文件,每个文件有自己的名字,它们就是包中的子模块,`__init__.py`这个文件完全可以留空。
|
||||||
|
|
||||||
|
给包编写帮助文档也很简单,使用多行字符串的方式在包中的`__init__.py`文件或其他py文件最前面写帮助文档即可。
|
||||||
|
|
||||||
|
关于定义包、导入包的知识,我们将在后面的课程中详细讲解。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------- | ------ |
|
||||||
|
| package | 包 |
|
||||||
|
| init | 初始化 |
|
||||||
|
|
||||||
105
chapter6/6-5 python3小白课:定义包.md
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
# python3小白课:定义包
|
||||||
|
|
||||||
|
### 在\_\_init\_\_.py文件中定义包
|
||||||
|
|
||||||
|
我们可以单独在单文件中定义包,接下来我们来尝试一下。
|
||||||
|
|
||||||
|
首先创建一个文件夹名叫`xiaobai`,它就是未来的包名和导入名了。在文件夹中创建`__init__.py`文件,并编写如下内容:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
|
||||||
|
"""
|
||||||
|
小白同学的包
|
||||||
|
这是说明文档
|
||||||
|
命令:add_1(num)
|
||||||
|
将传入的数字加上1后返回
|
||||||
|
"""
|
||||||
|
|
||||||
|
def add_1(num):
|
||||||
|
"""将传入的数字加上1后返回,这是函数的文档"""
|
||||||
|
return num + 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print("这是在测试模块")
|
||||||
|
help(__name__)
|
||||||
|
print("*" * 40)
|
||||||
|
print(__doc__)
|
||||||
|
print(add_1(100))
|
||||||
|
```
|
||||||
|
|
||||||
|
该文件可以自执行来测试。
|
||||||
|
|
||||||
|
接下来我们在跟`xiaobai`这个文件夹同级的目录下创建一个`test.py`文件,编写代码如下:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
import xiaobai
|
||||||
|
|
||||||
|
help(xiaobai)
|
||||||
|
print("*" * 40)
|
||||||
|
print(xiaobai.__doc__)
|
||||||
|
|
||||||
|
print(xiaobai.add_1(1))
|
||||||
|
```
|
||||||
|
|
||||||
|
执行该文件,发现确实导入包就会导入`__init__.py`这个文件。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 包内定义多个py文件
|
||||||
|
|
||||||
|
接下来我们尝试在包中的多个py文件中定义几个子模块吧。
|
||||||
|
|
||||||
|
此时`__init__.py`这个文件创建后留空,什么也不写。
|
||||||
|
|
||||||
|
我们在`xiaobai`这个包文件夹下创建一个名为`module1.py`的py文件,编写内容如下:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
"""
|
||||||
|
我是module1
|
||||||
|
"""
|
||||||
|
NAME = "小白"
|
||||||
|
AGE = 18
|
||||||
|
```
|
||||||
|
|
||||||
|
创建一个名为`module2.py`的文件,编写内容如下:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
"""
|
||||||
|
我是module2
|
||||||
|
"""
|
||||||
|
def add_1(num):
|
||||||
|
return num + 1
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 你还可以多定义几个文件,把你原本的模块拆成子模块,这样每个文件内容可能都会变少,或者更加明确分类,这对于后续的维护帮助很大。
|
||||||
|
|
||||||
|
接下来我们在跟`xiaobai`这个文件夹同级的目录下创建一个`test.py`文件,编写代码如下:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
from xiaobai.module1 import NAME, AGE
|
||||||
|
import xiaobai.module2 as mod2
|
||||||
|
print(NAME, AGE)
|
||||||
|
print(mod2.add_1(100))
|
||||||
|
```
|
||||||
|
|
||||||
|
这里仅做了简单的调用示例,可以正常获取到模块的成员内容并调用。
|
||||||
|
|
||||||
|
后续我们将再详细讲解调用包中的成员的更多知识。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 包中定义子包
|
||||||
|
|
||||||
|
当包的大小达到一定程度之后,感觉又不好维护了,或者这个包本身就是由好几个团队分别维护的,这时候这个包就很大功能很全。
|
||||||
|
|
||||||
|
由于我们讲过包其实本质也是模块,那么在包中再嵌套多个文件夹,每个文件夹像包一样的定义好,形成包中的子包,也是支持的。
|
||||||
|
|
||||||
|
关于这个,你知道了解即可,我们就不进行深入探讨了。
|
||||||
93
chapter6/6-6 python3小白课:包成员导入.md
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# python3小白课:包成员导入
|
||||||
|
|
||||||
|
### 包成员导入的一般方法
|
||||||
|
|
||||||
|
这部分讲的方法比较适用于在`__init__.py`文件中未做其他操作或者该文件为空的场景。
|
||||||
|
|
||||||
|
我们就拿上节课讲到的定义的`xiaobai`这个包来说起。
|
||||||
|
|
||||||
|
我们再回顾一下这几个文件的内容:
|
||||||
|
|
||||||
|
`module1.py`文件:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
"""
|
||||||
|
我是module1
|
||||||
|
"""
|
||||||
|
NAME = "小白"
|
||||||
|
AGE = 18
|
||||||
|
```
|
||||||
|
|
||||||
|
`module2.py`文件:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
"""
|
||||||
|
我是module2
|
||||||
|
"""
|
||||||
|
def add_1(num):
|
||||||
|
return num + 1
|
||||||
|
```
|
||||||
|
|
||||||
|
基于上述内容我们有如下一些说明的导入用例,用于写在`test.py`文件中(它不是一个可用用例,只是为了解释说明一些导入的方法):
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# 直接导入xiaobai包,实际上就是导入__init__.py文件
|
||||||
|
import xiaobai
|
||||||
|
# 可以导入包中的子模块,如果未指定别名,使用时需要用导入的这么一长串来作为调用前缀
|
||||||
|
import xiaobai.module1
|
||||||
|
# 这种方式导入子模块,调用时前缀能稍微短一点
|
||||||
|
from xiaobai import module1
|
||||||
|
# 也可以导入某个模块的成员进来,可以不用前缀直接使用
|
||||||
|
from xiaobai.module2 import add_1
|
||||||
|
```
|
||||||
|
|
||||||
|
通过上述几个,相信你已经有了举一反三的能力,获取对应包的成员或对应包的导入也就不在话下了。我们注意到,这其中的关健就是`.`这个符号,这个符号能够进入更深的包层级,有了它,即使你有更深层级的子包定义也能顺利导入了。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 通过\_\_init\_\_.py文件整合包成员
|
||||||
|
|
||||||
|
因为写导入包本身的本质就是会执行`__init__.py`文件,所以包内的子模块的成员,我们可以在这个文件中编写导入。
|
||||||
|
|
||||||
|
我们说一下常见的两种写法的区别(下述不是真正可用的文件代码):
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
# .表示当前模块,这种写法的话相当于将模块导入包名中,调用时依然还是需要使用长长的方式调用
|
||||||
|
# 比如在__init__.py中这样写导入(该文件不能直接自执行,只能被导入,否则会报错):
|
||||||
|
from . import module1
|
||||||
|
# test.py中调用时要这样写:
|
||||||
|
import xiaobai
|
||||||
|
print(xiaobai.module1.NAME)
|
||||||
|
# 上述写法很长,我们可以写成这样,在__init__.py文件中:
|
||||||
|
from .module1 import *
|
||||||
|
# 这样在外部就可以用xiaobai前缀来调用module1的全部成员了,在test.py中:
|
||||||
|
import xiaobai
|
||||||
|
print(xiaobai.NAME)
|
||||||
|
```
|
||||||
|
|
||||||
|
基于前面讲的内容,我们这会儿来补充一下`__init__.py`文件的内容如下:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
from .module1 import *
|
||||||
|
from .module2 import *
|
||||||
|
```
|
||||||
|
|
||||||
|
然后可以在`test.py`文件中这样写来方便调用:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
import xiaobai
|
||||||
|
print(xiaobai.NAME, xiaobai.AGE)
|
||||||
|
print(xiaobai.add_1(100))
|
||||||
|
```
|
||||||
|
|
||||||
|
这样可以实现在包中方便管理代码,在外部调用时也调用方便。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 上述写法比较适用于多个子模块之间没有重名的情况,如果有重名的情况,可能会存在某些成员被覆盖等问题,具体你可以自行测试一下。起名时尽量不要重名,如果非要重名,可以使用之前讲过的导入子模块的方式,而不在初始化文件中做导入。
|
||||||
57
chapter6/6-7 python3小白课:模块内容查看.md
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# python3小白课:模块内容查看
|
||||||
|
|
||||||
|
包本质也是模块,本课我们讲的内容也适用于包。
|
||||||
|
|
||||||
|
### 查看模块成员
|
||||||
|
|
||||||
|
之前我们讲过,可以使用`dir()`命令查看包含哪些命令,在这里依然是适用的,参数传入模块名即可,模块需要先行导入。
|
||||||
|
|
||||||
|
需要注意的是,使用该命令会把那些包含`_`下划线的开发者定义的内部成员或特殊方法都给获取到,如果你不希望获取到,可以输入如下命令来获取:
|
||||||
|
|
||||||
|
`[i for i in dir(模块名) if not i.startswith("_")]`
|
||||||
|
|
||||||
|
使用列表推导式,替换模块名之后即可查看所有非内部成员。
|
||||||
|
|
||||||
|
你还可以使用`__all__`成员来查看开发者想让你知道的有哪些成员,但并非所有模块都有定义该成员,若未定义,可以使用`dir()`命令或介绍的列表推导式来获取。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 查看模块文档
|
||||||
|
|
||||||
|
我们多次讲过,一个好的帮助文档是我们必不可少的,定义好之后,可以使用`help()`命令或`__doc__`属性来查看帮助文档。
|
||||||
|
|
||||||
|
有些python自带的标准库的文档可能不够详实,你可以参考官方的文档:
|
||||||
|
|
||||||
|
[https://docs.python.org/zh-cn/3/library/index.html](https://docs.python.org/zh-cn/3/library/index.html)
|
||||||
|
|
||||||
|
你还可以使用如下命令来查看包文档:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python -m pydoc -p 8899
|
||||||
|
```
|
||||||
|
|
||||||
|
在cmd中运行后,会启动一个服务器页面[http://localhost:8899/](http://localhost:8899/),点击访问你就可以看到你已有的所有包的文档。你也可以在运行改代码之后,在cmd中输入`b`并回车,打开浏览器访问该页面,按`q`并回车,退出服务。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 查看模块路径
|
||||||
|
|
||||||
|
当我们觉得这个模块的代码不错,需要进一步研读python代码了解开发逻辑时(python的源码理论上都是开源的),可以使用`__file__`属性来查看模块的路径,打开路径中所示的文件即可具体查看代码。一些不错的IDE比如pycharm还支持直接跳转并打开模块所对应的文件,十分方便查看。
|
||||||
|
|
||||||
|
比如我们可以这样写:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# coding:utf-8
|
||||||
|
import xiaobai
|
||||||
|
print(xiaobai.__file__)
|
||||||
|
```
|
||||||
|
|
||||||
|
在python中,还有部分与底层交互的模块不是用python写的,而是用C语言写的,这些程序可能没有`__file__`属性,请知悉。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ---- | ---- |
|
||||||
|
| file | 文件 |
|
||||||
204
chapter6/6-8 python3小白课:解锁你心仪的三方包.md
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
# python3小白课:解锁你心仪的三方包
|
||||||
|
|
||||||
|
### 三方包管理仓库
|
||||||
|
|
||||||
|
**PyPI**(*Python Package Index*)是python**官方的第三方库的仓库**,所有人都可以下载第三方库或上传自己开发的库到PyPI。
|
||||||
|
|
||||||
|
它的网址为(如果访问比较慢可以寻找一些国内的镜像源站如清华大学包源[https://www.lfd.uci.edu/~gohlke/pythonlibs/](https://www.lfd.uci.edu/~gohlke/pythonlibs/),或者扶墙):
|
||||||
|
|
||||||
|
[https://pypi.org/](https://pypi.org/)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 查看、下载三方包
|
||||||
|
|
||||||
|
无需注册,你可以输入你想要查看或下载的包名,搜索详细信息,我们来随意搜索一个,比如做爬虫的一个很不错的三方包`requests`。输入并点击搜索按钮后会跳转到结果界面:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
可以看到有很多很多个搜索结果,可以点击进去最匹配的那个结果。这里看到的`2.23.0`是最新版本的版本号。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
如上图所示,我们进入了包的详情页面,在这里可以看到包的最新版本,底下的`pip install requests`是使用包管理工具`pip`来下载包的命令行,可以复制该行放到cmd中执行。关于包管理工具`pip`,后面我们会再详细讲解。
|
||||||
|
|
||||||
|
右上角是现在的版本是否为最新版本以及该版本的发布日期等信息。
|
||||||
|
|
||||||
|
在下面正文内容的左侧边栏有一个导航条,如图我们标注出了功能信息,默认进入的是项目描述页,会告诉我们这个包是做啥的,你可以了解一下,该信息由包的开发者提供,如果开发者比较懒,你也可能看不到啥信息。
|
||||||
|
|
||||||
|
发行历史部分是查看历史版本时间线用的,如果你需要下载一个指定的历史已发布的版本可以从这里进入。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
下载文件部分是展示有哪些资源可供下载的。你可以查看文件类型,适合的python版本,上传日期,哈希值等信息。还可以点击链接进行下载。
|
||||||
|
|
||||||
|
比如这里我们看到有两个资源可供下载,`.whl`文件是wheel文件,轮子的意思,我觉得取的寓意很好,下载了轮子你就不用重复造轮子了。这是python打包中比较新的一种很不错的打包格式,是编译过的包文件,不需要下载代码后自己本机编译,提高了安装的成功率。下载后可以直接通过`pip`包管理工具安装,网上有些说法是说需要先安装`wheel`这个三方包才能安装,实测是不需要的。而安装`wheel`这个库之后可以自己来打包自己的`whl`文件。
|
||||||
|
|
||||||
|
> [!tip]
|
||||||
|
>
|
||||||
|
> 你可以尝试把下载好的whl文件后缀名修改为zip,发现它可以用压缩软件打开,实际它是一个压缩打包文件。
|
||||||
|
|
||||||
|
另一种格式是`tar.gz`格式,这是源码文件压缩格式,在有能用的`whl`包的时候我们都不太推荐用这种格式,因为有的时候需要你自己本机编译一些原始代码,如果电脑中缺少某些编译库,则会出现各种各样的报错问题,所以不到不得已不使用。
|
||||||
|
|
||||||
|
可能还有一些其他你可能见到的格式,你都可以从网上找到对应的安装方法。
|
||||||
|
|
||||||
|
上面讲的是到pypi官网去找到包并下载的,这种操作比较适合给一些公司内网(不能连接外网下载)离线安装,或者想看看有些什么包可以用的情况,实际我们在知道要安装什么包的时候,极少会登录pypi官网去下载。
|
||||||
|
|
||||||
|
#### 自己贡献三方库
|
||||||
|
|
||||||
|
除了使用全球开发者提供的各种各样的三方库之外,你也可以贡献自己的三方库。
|
||||||
|
|
||||||
|
只需要在pypi官网注册登录并按照要求上传相关的文件即可。需要注意自己注册的三方库名字不能跟官网中已有的重复即可,这个在注册项目的时候是可以搜索看一下的。
|
||||||
|
|
||||||
|
关于这块内容,入门的同学们可以不做掌握,如果大家感兴趣的话,今后在进阶或高级课程中会详细再跟大家讲解。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### pip包管理工具
|
||||||
|
|
||||||
|
前面我们已经提到了`pip`这款包管理工具,同很多其他编程语言一样,通过这款工具,我们可以轻松的做到python的三方库的管理、安装、卸载等操作。
|
||||||
|
|
||||||
|
这部分我们来着重讲解一下日常常见的使用。
|
||||||
|
|
||||||
|
`pip`工具是一个命令行工具,可以在cmd命令提示符中使用。目前的python安装包通常都会自带`pip`工具一起安装的,也可以自己去下载安装,可以看一下我们第3课的截图,已经默认安装了。
|
||||||
|
|
||||||
|
可以在cmd中输入命令查看是否已安装:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
pip --version
|
||||||
|
```
|
||||||
|
|
||||||
|
如果成功弹出版本号,说明安装成功而且可以正常调用。
|
||||||
|
|
||||||
|
如果告诉你找不到`pip`这款工具,首先你可以看一下环境变量中是否已经将python安装目录下的`Scripts`目录加入了环境变量中,如果也确实加入了,可以重启再看一看。
|
||||||
|
|
||||||
|
如果还是不成功,可能你就需要手动安装一下`pip`了。需要手动安装的同学可以看下,手动安装我们参考官网介绍:[https://pip.pypa.io/en/stable/installing/](https://pip.pypa.io/en/stable/installing/)
|
||||||
|
|
||||||
|
首先我们需要戳这个下载相关文件:[https://bootstrap.pypa.io/get-pip.py](https://bootstrap.pypa.io/get-pip.py)
|
||||||
|
|
||||||
|
然后运行命令在线安装pip:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python get-pip.py
|
||||||
|
```
|
||||||
|
|
||||||
|
如果我们保证`pip`已经安装好了,就来看一下如何使用吧。
|
||||||
|
|
||||||
|
我们有如下一些命令来使用:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 通过pip在线安装三方库,如requests,这个命令最常使用,务必牢记
|
||||||
|
# 它会自动下载适合你目前安装的python的包并安装(如果包依赖于其他包,也会一并下载安装)
|
||||||
|
pip install requests
|
||||||
|
|
||||||
|
# 查看目前已安装的三方库列表
|
||||||
|
pip list
|
||||||
|
|
||||||
|
# 查看目前有哪些三方库有新版本了
|
||||||
|
pip list -o
|
||||||
|
|
||||||
|
# 如果pip不是最新版本,pip运行完一些命令时还会经常提醒你升级,升级pip自身的命令(一般也会给出)
|
||||||
|
# 从这个命令我们知道,前面加上python -m也能调用pip相关命令,适用于Scripts文件夹未加入环境变量的情况或升级自身的情况
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
|
||||||
|
# 查看pip的帮助
|
||||||
|
pip --help
|
||||||
|
|
||||||
|
# 升级某个三方包,有两种写法(一般来讲功能可以用就无需更新到最新版本,因为可能不兼容)
|
||||||
|
pip install --upgrade 包名
|
||||||
|
pip install -U 包名
|
||||||
|
|
||||||
|
# 卸载某个包
|
||||||
|
pip uninstall 包名
|
||||||
|
|
||||||
|
# 安装一个wheel包,如果已进入whl文件所在路径,直接写完整文件名,否则写完整路径(可加引号)
|
||||||
|
pip install 本地whl文件名
|
||||||
|
|
||||||
|
# 安装源码包
|
||||||
|
pip install 本地tar.gz文件名
|
||||||
|
# 顺带一提:也可以将该压缩包解压,cmd进入解压后的文件夹,运行如下命令安装:
|
||||||
|
python setup.py install
|
||||||
|
|
||||||
|
# 当包下载过慢的时候,设置使用国内镜像,你可以网上搜到很多,我们以清华源镜像为例:
|
||||||
|
# 帮助参考:https://mirrors.tuna.tsinghua.edu.cn/help/pypi/
|
||||||
|
# 临时一次性使用:
|
||||||
|
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名
|
||||||
|
# 永久使用配置:
|
||||||
|
# 先升级pip最新版(需要>=10.0.0版本)
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
# 注意不要使用上述网站让你用的这个命令:pip install pip -U,实测卸载pip以后无法安装,会报找不到pip了
|
||||||
|
# 源设置:
|
||||||
|
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
|
# 设置完之后按往常那样安装包即可
|
||||||
|
|
||||||
|
# 离线下载包(如果包依赖于其他包,也会一并下载)
|
||||||
|
pip download 包名
|
||||||
|
# 上述会在cmd当前目录下载包,你可以指定保存目录,更推荐
|
||||||
|
pip download -d 保存目录 要下载的包名
|
||||||
|
# 比如下载一个ipython包
|
||||||
|
pip download -d "E:\Programs\编程开发\python3\package\ipython" ipython
|
||||||
|
|
||||||
|
# 将离线下载好的包给不能联网的电脑离线安装:
|
||||||
|
pip install --no-index --find-links=下载的离线包保存目录 包名
|
||||||
|
# 比如安装ipython的包
|
||||||
|
pip install --no-index --find-links="E:\Programs\pythonpackage\for python3\ipython" ipython
|
||||||
|
|
||||||
|
# 冻结项目所用的三方包(后续我们会讲到虚拟环境,只会冻结虚拟环境中用到的包):
|
||||||
|
# 会将三方包的名称版本号写进requirements.txt这个文件中,供后续换电脑移植快速恢复三方包环境使用
|
||||||
|
# 约定俗称用requirements.txt,你喜欢也可以改为其他文件名
|
||||||
|
pip freeze > requirements.txt
|
||||||
|
# 如果新安装的电脑能联网
|
||||||
|
pip install -r requirements.txt
|
||||||
|
# 如果新安装的电脑无法联网
|
||||||
|
# 先找台能联网的电脑,批量下载这些三方包
|
||||||
|
pip download -d "保存目录路径" -r requirements.txt
|
||||||
|
# 新电脑批量安装本地离线包
|
||||||
|
# 这里可能的报错的情况是:当包分py2、py3版本却下载了错误版本时,当python安装的是32位的,但安装包是64位的时。
|
||||||
|
# 这时候到pypi官网下载正确适合的包即可。
|
||||||
|
pip install --find-links="下载的离线包保存目录" -r requirements.txt
|
||||||
|
|
||||||
|
# 搜索三方包
|
||||||
|
pip search 包名
|
||||||
|
```
|
||||||
|
|
||||||
|
基本上日常常用的`pip`命令就这些,大家可以只记住最基本的在线安装命令,因为多数时候我们也只用到这个命令而已。其他的命令,先做一个大致了解,当需要时再回来本次课程查阅即可。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
本课涉及到的一些英语单词也比较多,我挑了比较重要的都列举出来了,大家可以看一下加强学习记忆。
|
||||||
|
|
||||||
|
当你都记住之后,上面的命令的记忆就基本不成问题了(偷偷告诉你,很多其他编程语言的管理工具的命令行工具的命令是类似的,记住之后对你很有帮助哦)。
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| -------------------- | --------------------------------------------------------- |
|
||||||
|
| python package index | python包索引,简称PyPI,全球的官方python包仓库 |
|
||||||
|
| search projects | 搜索项目 |
|
||||||
|
| requests | 请求request的复数 |
|
||||||
|
| pip | python的三方包管理工具 |
|
||||||
|
| install | 安装 |
|
||||||
|
| latest version | 最新的版本 |
|
||||||
|
| navigation | 导航 |
|
||||||
|
| project description | 项目描述 |
|
||||||
|
| release history | 发行历史 |
|
||||||
|
| download files | 下载文件 |
|
||||||
|
| filename, size | 文件名,大小 |
|
||||||
|
| file type | 文件类型 |
|
||||||
|
| wheel | 轮子 |
|
||||||
|
| source | 源码 |
|
||||||
|
| python version | python的版本 |
|
||||||
|
| hashes | 哈希值hash的复数 |
|
||||||
|
| scripts | 脚本script的复数 |
|
||||||
|
| upgrade | 升级 |
|
||||||
|
| uninstall | 卸载 |
|
||||||
|
| setup | 安装 |
|
||||||
|
| config | 配置 |
|
||||||
|
| set | 设置,动词 |
|
||||||
|
| global.index-url | global全局的,index-url首页地址 |
|
||||||
|
| download | 下载 |
|
||||||
|
| --no-index | 没有索引,其实我也没太搞懂这个参数用来干嘛的 |
|
||||||
|
| --find-links | 寻找链接,后面给个离线包的目录,告诉pip安装包从该目录下找 |
|
||||||
|
| freeze | 冻结 |
|
||||||
|
| requirements | 要求requirement的复数形式,约定俗称的冻结后保存的文件名 |
|
||||||
|
| search | 搜索 |
|
||||||
75
chapter6/6-9 python3小白课:虚拟环境介绍和安装.md
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# python3小白课:虚拟环境介绍和安装
|
||||||
|
|
||||||
|
### 虚拟环境介绍
|
||||||
|
|
||||||
|
在本套课程的第1课我就跟大家提到过,如果你所在的公司大多数项目都在使用python2.7,或者你有多个项目需要使用不同版本的三方包时,你使用你喜欢的python版本开发好程序后也无需担心,因为我们有`虚拟环境`,可以轻松让多版本的python以及多版本的三方包(适用于你的项目的)共存。
|
||||||
|
|
||||||
|
有许多可用的虚拟环境包供我们选择,我个人比较喜欢用的是`virtualenv`这个,你如果喜欢别的,也可以去学习了解。
|
||||||
|
|
||||||
|
过去我还不知道还能弄虚拟环境的时候,曾经电脑里安装了python2.7和python3的版本,这时候调用起来这个环境变量的优先级顺序就颇为麻烦,虽然后来是找到办法来解决共存问题,但我又遇到了新的挑战,那就是包管理。默认情况下,你可以通过`pip list`命令来查看目前已安装的三方包有哪些,我们默认通过`pip install 包名`的方式安装的包都会直接安装在你的系统python下。同一个包,只允许存在一个,比如你安装了这个包的`1.0`版本,你就无法使用`2.0`版本,这在这台电脑只有你自己开发用的情况下还影响不大,无非就是统一用某一个版本开发就好了呗。
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 你要想这样的场景:你的电脑自己平时开发使用的这个包用的是`2.0`版本。有一天你的老板给你布置了一个项目要求你用这个三方包用跟公司项目统一的`1.0`版本,这时候你怎么办?难道跟老板说咱不用1.0好嘛用2.0?或者妥协一下卸载自己装的2.0用1.0?
|
||||||
|
|
||||||
|
不必那么麻烦,有了虚拟环境,这些包的安装管理都是独立了,你再也没有这样的烦恼了。
|
||||||
|
|
||||||
|
同时,每一个虚拟环境还支持不同的python版本,这样python2.7和python3就可以友好共存了,即时你有个项目需要使用python3.8.2,另一个项目却要求python3.6.6,他们都能互不干扰,和平共处,神奇吧?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 虚拟环境包安装和初始配置
|
||||||
|
|
||||||
|
相信大家已经了解了虚拟环境的高效性了,那么其实我们今后推荐你的系统python安装一个主版本,然后日常开发的每个项目都单独弄一个虚拟环境出来(支持不同python版本和独立的包管理列表),这样你将步入专业的开发之流。
|
||||||
|
|
||||||
|
一般来讲,我们在win系统推荐将`virtualenv`的扩展包一起安装,使用起来更方便,后续我们将基于它们来讲解。
|
||||||
|
|
||||||
|
安装很简单,在cmd运行以下命令安装(如果网络连接失败可以多试几次或者扶墙或者镜像安装):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
pip install virtualenvwrapper-win
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!danger]
|
||||||
|
>
|
||||||
|
> 需要说明的是,目前我的系统python安装的是3.8.2版本,如果你的系统python是2.7版本的,也是支持安装上述包的,然后可以创建python3的任意虚拟环境。
|
||||||
|
|
||||||
|
直接安装上述包,它会自动安装`virtualenv`这个依赖包和其他依赖的三方包等,省时省力。
|
||||||
|
|
||||||
|
安装后比如我这里显示的包列表如下:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
C:\Users\xueshanlinghu>pip list
|
||||||
|
Package Version
|
||||||
|
--------------------- -------
|
||||||
|
appdirs 1.4.3
|
||||||
|
distlib 0.3.0
|
||||||
|
filelock 3.0.12
|
||||||
|
pip 20.0.2
|
||||||
|
setuptools 46.1.3
|
||||||
|
six 1.14.0
|
||||||
|
virtualenv 20.0.18
|
||||||
|
virtualenvwrapper-win 1.2.6
|
||||||
|
```
|
||||||
|
|
||||||
|
完成后,我们还需要去`手动`配置一下环境变量,打开系统的环境变量配置。
|
||||||
|
|
||||||
|
新建一个变量名为`WORKON_HOME`的系统变量,变量值写你未来想用来存放各个虚拟环境的文件夹,你可以自定义:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
完成后确定保存,重启计算机一下。
|
||||||
|
|
||||||
|
重启后,打开一个新的cmd窗口。输入命令`workon`,这时就会列举出你在刚才系统环境变量时设定的变量值那个文件夹下的所有虚拟环境了。由于目前我们还没有创建任何一个虚拟环境,所以目前列表为空。
|
||||||
|
|
||||||
|
在下一节课我将教会大家虚拟环境的创建、删除、切换激活、取消激活等等高端操作,我们还支持某虚拟环境指定python版本地创建,记得来学习哦~
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| --------------------- | ------------------------------------------------------------ |
|
||||||
|
| virtualenv | virtual虚拟的,env,environment环境的简写 |
|
||||||
|
| virtualenvwrapper-win | 前面部分讲过了,不赘述,wrapper包装纸,封皮,封套,这里理解为封装扩展包,win,windows平台,linux平台对应应安装的包为virtualenvwrapper |
|
||||||
|
| workon_home | work on合并词,向...做工作,我理解为在哪个路径下工作,home家 |
|
||||||
19
chapter6/README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# 六、模块和包
|
||||||
|
|
||||||
|
之前的章节,我们学习了许多python自带的命令,它们在安装好python后就自带的,可以直接使用。但python的功能就仅限于那些吗?剩下的都需要自己定义吗?
|
||||||
|
|
||||||
|
当然不可能!
|
||||||
|
|
||||||
|
python之所以能被各行各业广泛应用,我们之前已经说过,是它有着十分强大的生态系统,这个系统这里我们可以说到很大一部分是它的模块化系统。除了内置函数,python还有内置的模块,这些模块里面又有许许多多已经定义好的函数命令可以供我们使用。
|
||||||
|
|
||||||
|
如果你觉得这些还不够,全世界有许许多多的开发者都可以参与模块的贡献,它们可以可以把自己开发的模块(我们称之为三方包)上传到python官方提供的站点中,供全世界开发者`免费`下载。
|
||||||
|
|
||||||
|
我们称这些模块为`轮子`,可能你听过一句话是`不要重复造轮子`,说的就是如果别人开发有,且好用的话,你就拿来用就可以了。有了很多趁手的工具,我们的编程就可以事半功倍。这些扩展库也形成了python的`生态圈`。
|
||||||
|
|
||||||
|
如果这些还不够你用怎么办?你还可以自己定义模块,我们会在课程中学习到它。
|
||||||
|
|
||||||
|
当模块中的内容比较庞杂,变量、函数、类(类的知识,我们将在后面的章节讲解)等较多的时候,我们使用单文件来编写模块会使得这个文件非常庞大,不利于维护,不利于模块化开发。
|
||||||
|
|
||||||
|
所以我们还引入了`包`的概念,通过`包`,我们可以把这些东西都管理起来,方便后续的调用,本章节我们也会进行学习。
|
||||||
|
|
||||||
|
请大家进入我们的学习吧!
|
||||||
BIN
chapter6/assets/6-10-1.jpg
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
chapter6/assets/6-10-2.jpg
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
chapter6/assets/6-10-3.jpg
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
chapter6/assets/6-10-4.jpg
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
chapter6/assets/6-10-5.jpg
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
chapter6/assets/6-10-6.jpg
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
chapter6/assets/6-10-7.jpg
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
chapter6/assets/6-10-8.jpg
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
chapter6/assets/6-10-9.jpg
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
chapter6/assets/6-8-1.jpg
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
chapter6/assets/6-8-2.jpg
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
chapter6/assets/6-8-3.jpg
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
chapter6/assets/6-8-4.jpg
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
chapter6/assets/6-9-1.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
101
chapter7/7-1 python3小白课:一节课搞懂面向对象.md
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
# python3小白课:一节课搞懂面向对象
|
||||||
|
|
||||||
|
在学习python的类(class)和对象(object)之前,我们先来搞懂什么是面向对象编程(OOP)(有些同学会戏称为面向`对象(你家的男女朋友)`编程,开个玩笑,能记住最好)。
|
||||||
|
|
||||||
|
因为概念相对比较抽象,咱一板一眼的解释大家肯定看不懂,所以我思虑再三,也结合了一些网络资料的解释,用最通俗易懂的生活中的故事来跟大家解释面向对象的思想以及面向对象的三大特性——封装(Encapsulation)、继承(Inheritance)、多态(Polymorphism)。
|
||||||
|
|
||||||
|
本例中的图片源于网络并做了一定的PS,仅供学习说明使用。
|
||||||
|
|
||||||
|
### 类的封装
|
||||||
|
|
||||||
|
冬天到了,屋里好冷啊,这时候我们就需要一个`暖风机`了。暖风机插上电之后就可以送暖风了。
|
||||||
|
|
||||||
|
这时候我们就有一家生产暖风机的厂商,他们生产的暖风机如图所示:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
从上图的特点,我们类比面向对象的概念,暖风机这类产品它的生产规范是固定好的,有上图打勾的三个特点,这一`类`产品,我们称之为`暖风机类`,这个类里面可以定义一些东西,比如:
|
||||||
|
|
||||||
|
* 类的成员变量:机身、加热片
|
||||||
|
* 类的成员属性:机身是`红色`的
|
||||||
|
* 类的成员方法:可以通过温控旋钮方法来启动关闭暖风机,传入不同的参数还可以有不同档位的温度(是不是有点像函数?)
|
||||||
|
|
||||||
|
`类`是一系列特征的抽象形式,`暖风机类`仅能定义规范,但不是实实在在到你手中的产品。所以我们需要使用`对象`来将`类`实例化,比如这个工厂参照着这样的标准,生产了1000台暖风机,如果你编个号,那就是暖风机1号、暖风机2号……
|
||||||
|
|
||||||
|
这些具体的产品,就是我们所说的`对象`,就是抽象`类`实例化后的产物。
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> 如果这个例子你不好理解,我补充一个小例子。人类是`类`,是抽象的,但我们许许多多的不同的人就是`人类`实例化后的产物,所以我们是`对象`,也叫一个类的`实例`。
|
||||||
|
|
||||||
|
类里面,我们可以定义一些变量、属性、方法等,方法就类似我们平常说的函数,可以执行一系列的动作等,但只有这个类才拥有这些方法,外部需要调用该类的方法,比如对类进行实例化。比如理论上每个人都会`走路`这个方法,需要实例化到每个人,才能调用每个人的`走路`方法。
|
||||||
|
|
||||||
|
将变量、属性、方法等定义到某个类中,仅有这个类或类的实例(也就是对象)才能访问它们,它可以将内部的一些实现细节隐藏起来,跟外界隔绝,如果各种实例的方法实现均需要修改,则修改类内部的成员定义即可,维护起来也是颇为方便的。
|
||||||
|
|
||||||
|
这,就是`类的封装`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 类的继承
|
||||||
|
|
||||||
|
有一天,这个暖风机工厂的老板说,暖风机上如果有`摇头`的功能,那些暖风可以不一直吹着某个位置,肯定能卖得更好!所以要求工厂生产一种全新的暖风机,我们称之为`会摇头的暖风机`。
|
||||||
|
|
||||||
|
这时候,工厂有如下选择:
|
||||||
|
|
||||||
|
* 设计一个全新的`会摇头的暖风机`
|
||||||
|
* 在现有`暖风机`的基础上,增加一个按钮,按下去就摇头,再按一下就固定
|
||||||
|
|
||||||
|
> [!question]
|
||||||
|
>
|
||||||
|
> 从节约成本的角度来说,你会选择哪种方案?
|
||||||
|
|
||||||
|
显然,选择第二种方案更加节约成本,因为它只是增加了一个按钮,我们可以将它设计为暖风机的`新方法`。
|
||||||
|
|
||||||
|
这时候我们直接在之前的`暖风机类`上改设计的代码吗?不对,因为`暖风机类`我们之前已经定义过,就是具有之前那几个特征的普通暖风机。
|
||||||
|
|
||||||
|
这时,我们在代码中可以使用`继承`的方法,将新的`会摇头的暖风机类`继承自原来的`暖风机类`,这样它就默认拥有了之前`暖风机类`的特点、方法等。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
继承后,我们在新的`会摇头的暖风机类`中额外定义一个新的方法:摇头,即可。
|
||||||
|
|
||||||
|
实现继承的类`会摇头的暖风机类`称之为继承类或子类,被继承的类`暖风机类`被称为父类、基类或超类。我个人多数会叫`父类`、`子类`这样的叫法。继承类会自动拥有基类的所有特征成员,子类更像是父类的进一步扩展,这里好像颇有青出于蓝而胜于蓝之意,代码维护起来也颇为方便。
|
||||||
|
|
||||||
|
这,就是`类的继承`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 类的多态
|
||||||
|
|
||||||
|
基于封装和继承的特性,面向对象还能延伸出多态的特性来,简单来说,就是不同的对象对于同样的方法可以呈现出多种不同的状态。
|
||||||
|
|
||||||
|
我们举例说明,还是接着上面的例子。
|
||||||
|
|
||||||
|
夏天到了,暖风机卖不动了,即使工厂的暖风机能360°摇头估计销量也不太行了,天气太热了,当然还是空调(落地那种)比较好。
|
||||||
|
|
||||||
|
这时候,我们就不说方案了,直接选择继承之前`会摇头的暖风机类`来进一步开发比较省事省钱,新的类名为`会摇头的冷风机类`。
|
||||||
|
|
||||||
|
但是这机身里面放的是啥?是加热片!那怎么能制冷呢?这时候我们可以`重写`父类里面的成员和方法,比如变量修改为机身+制冷片,旋钮的方法修改为调节旋钮可以控制冷风的大小。我们改成下图这样:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
同样是调用同名的成员变量(机身组成)和成员方法(温控旋钮),我们的冷风机却展现出截然不同的功能。
|
||||||
|
|
||||||
|
> [!note]
|
||||||
|
>
|
||||||
|
> 再补充一个小例子,一般的鸟类都会飞,鸵鸟也是一种鸟,继承了`鸟类`这个类,但它不会飞,所以它内部改写了`会动翅膀`这个方法的实现,普通的鸟实现下来就是飞起来了,而鸵鸟的代码实现却是飞不起来的。
|
||||||
|
|
||||||
|
这,就是`类的多态`。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 单词释义
|
||||||
|
|
||||||
|
| 单词 | 释义 |
|
||||||
|
| ------------- | ------------------------------------------- |
|
||||||
|
| class | 类 |
|
||||||
|
| object | 对象 |
|
||||||
|
| OOP | Object Oriented Programming面向对象程序设计 |
|
||||||
|
| Encapsulation | 封装性 |
|
||||||
|
| Inheritance | 继承性 |
|
||||||
|
| Polymorphism | 多态性 |
|
||||||