人工智能总目录网页链接
1、Unix
Mac OS 、Solaris
2、Linux
RedHat、CentOS、Ubuntu 16.04(教学环境版本)
3、Windows
win7、win8、win10
1、功能强大的桌面虚拟计算机软件
2、开发、测试、部署应用程序的利器
3、教学(开发、测试部署)环境安装
1、下载VMware Workstation安装包并安装
2、下载Linux操作系统镜像文件.iso(纯净版) :Ubuntu 16.04
3、打开VMware Workstation,文件 -> 新建虚拟机(组装电脑)
4、CD/DVD -> 插入光盘(.iso文件)
5、开启此虚拟机 -> 通电开机
6、安装完成后安装一系列的软件、模块
1、终端 :用来输入Linux命令
1、点击图片
2、点击 "搜索计算机" -> gnome-terminal
2、目录树
1、根 / :代表文件系统的起始位置
2、路径 :代表一个文件/目录的字符串
/home/tarena/AID09
3、Linux命令基本格式
命令名 [选项] [参数] #[]代表里面内容可有可无
1、pwd :显示当前所在路径
2、ls :显示目录的详细内容(文件、子目录)
1、常用选项
ls -l :以列表(长格式)显示文件、目录详细信息
ls -a :显示所有(包含隐藏) 以 . 开头为隐藏
ls -la
ls -al
3、路径
1、绝对路径: 以 / 开始的路径
2、相对路径: 不以 / 开始的路径
. 当前目录
.. 上一级目录
~ 用户主目录/家目录(/home/tarena)
3、主目录/家目录
1、超级用户 :root
2、创建用户时会自动在/home下创建1个和用户名同名的目录,为此用户主目录
用户名 :tarena 主目录 :/home/tarena
用户名 :zhanshen 主目录 :/home/zhanshen
4、cd :切换目录(路径)
1、用法
cd 路径(绝对、相对路径都可以)
cd /home/tarena 、cd /home/tarena/aid1809
cd aid1809 #前提是现在主目录下
2、cd 直接回车 :回到用户主目录/home/tarena
cd ~ : 回到用户主目录
cd - : 从最近访问的两个目录之间来回切换
3、TAB键自动补齐命令/路径(熟练使用!!!!!)
1、速度快
2、路径不会错,TAB不出来说明路径有问题
4、练习
1、切换到目录 :/home/tarena/anaconda3/bin
cd /home/tarena/anaconda3/bin/
2、查看当前所在路径
pwd
3、以列表形式列出当前目录所有内容(包含隐藏)
ls -la
4、切换到当前目录的上一级目录,即
:/home/tarena/anaconda3
cd ..
5、切换到/etc目录,查看/etc下有哪些内容
cd /etc/
6、直接切换到用户主目录
cd
5、mkdir :创建1个或n个目录(文件夹)
1、格式 :mkdir 目录名1 目录名2 ...
2、常用选项
-p :逐层创建目录
mkdir -p One/Two/Three/Go
# 如果中间目录不存在,直接创建
6、touch
1、作用
1、文件不存在 -> 创建
2、文件存在 -> 用系统时间更新文件修改时间
2、格式 :touch 文件名1 文件名2 文件名3 ...
3、练习
1、在用户主目录下创建目录 A1/B1/C1/D1
cd
mkdir -p A1/B1/C1/D1
2、在D1下创建文件 file1.txt file2.txt
cd A1/B1/C1/D1
touch file1.txt file2.txt
3、在C1下创建文件 file3.txt file4.txt
cd ..
touch file3.txt file4.txt
4、切换到A1目录,查看当前所在路径
cd ../../
pwd
5、直接切换到用户主目录
cd
7、技巧类
1、自动补齐 :TAB键
2、翻出历史执行命令 :键盘 上、下键
3、清屏 :Ctrl + l 或者 clear
4、终止命令执行 :Ctrl + c
5、终端字体放大 :Ctrl + Shift + "+"
6、终端字体缩小 :Ctrl + "-"
8、练习
1、一条命令创建:
/home/tarena/目录下创建目录 :广东省
在 广东省 下创建目录 :深圳市
在 深圳市 下创建目录 :宝安区
2、在 宝安区 下创建文件 :福永小姐姐
3、在用户主目录下创建如下结构:
Python
|
+-------+-------+------+
| | | |
Shanghai Wuchang Chengdu Shijiazhuang
目录 目录 目录 目录
9、rm :删除文件/目录
1、rm 选项 文件/目录
-r :删除全部文件/目录
-f :强制删除,不给任何提示
-i :删除前给提示(y代表yes,n代表no)
rm -rf 文件名/目录名
5、文本编辑器vi/vim
1、格式 :vi 文件名
2、vi的三种工作模式
1、浏览模式 :启动时进入,不能编辑文本
2、插入模式(a/i/o) :编辑文本
3、命令行模式(ESC -> shift + :) :保存退出..
3、文本写入步骤
1、vi 文件名
2、按 a/i/o :编辑文本
3、按 ESC
4、按 shift + : --> 命令行模式
5、wq :保存退出
q! :不保存直接退出
w :保存
6、作业1
1、在用户主目录下创建文件 :tarena.txt
2、在tarena.txt中写入如下内容保存退出:
仰天大笑出门去,我辈岂是蓬蒿人
rm -rf删除后不可恢复,使用时要小心进去
常用Linux操作系统:Ubuntu、CentOS、RedHat
Linux中把文件夹叫做目录
mkdir -p为递归创建目录
3、查看tarena.txt的内容
cat tarena.txt
4、切换到当前路径的上一级目录
5、查看当前所在路径
6、直接切换到用户主目录
7、作业2
1、在用户主目录下创建目录 :AID09
2、在AID09下创建三个目录:
Linux
Pbase
AI
3、在Linux目录下创建2个目录 :day01、day02
4、在day01下创建文件 :day01.txt
5、在Pbase下创建3个文件夹:
day01、day02、day03
6、在day03目录下创建 day03.txt
7、删除Pbase目录和Linux下的day01目录
8、切换到用户主目录
http://code.tarena.com.cn
用户名:tarenacode
密码:code_2013
路径:/AIDCode/aid1809/
Day01回顾
1、测试环境安装
1、下载材料 :VMware、Ubuntu 16.04 iso镜像文件
2、组装电脑 :文件 -> 新建虚拟机
3、插入光盘 :CD/DVD -> Ubuntu 16.04***.iso
4、通电开机 :开启此虚拟机
5、安装软件 :搜狗输入法、Chrome浏览器 ... ...
2、Linux
1、路径
1、绝对路径 : / 开始
2、相对路径 :. .. ~ 目录名/......
2、pwd :显示当前路径
3、ls -la :查看目录下内容
4、cd :切换目录
1、cd /home/tarena/AID09
2、cd AID09/Linux
3、cd ~
4、cd
5、cd -
5、mkdir :创建目录
1、mkdir dir1 dir2 dir3
2、mkdir -p dir1/dir2/dir3
6、touch :创建文件
touch file1 file2 file3
7、技巧
1、自动补齐 :TAB键
2、历史命令 :键盘上、下键
3、清理屏幕 :Ctrl + l / clear
4、终端放大 :Ctrl + Shift + "+"
5、终端缩小 :Ctrl + "-"
8、rm -rf :删除文件/目录
9、文本编辑器 vi/vim
1、三种模式 :浏览模式、插入模式、命令行模式
2、操作步骤
1、vim 文件名
2、浏览模式->插入模式 :a/i/o
3、插入模式->浏览模式 :ESC
4、浏览模式->命令行模式 :Shift + :
5、退出操作
wq!
q!
1、cp :复制文件/目录
1、复制文件 :cp 源文件 路径
2、复制目录 :cp -r 源目录 路径
3、cp *.txt /home/tarena/AID09
2、mv :剪切/重命名
1、剪切 :mv 文件名 路径
mv 目录名 路径
2、重命名 :mv 文件名1 文件名2
mv 目录名1 目录名2
3、练习
1、在用户主目录下创建文件:game.txt
2、用vim在game.txt中写入如下内容:
我的大刀早已饥渴难耐了
cp命令复制目录要加-r选项
mv命令作用有2个,剪切和重命名
3、将game.txt剪切到主目录下AID09(如无请创建)
4、给game.txt重命名为 :Dota.txt
5、把 AID09 目录复制到 /tmp
3、cat :查看文件内容(在终端输出)
cat 文件名
4、tar :打包并压缩
1、格式
tar -zcvf 压缩包名字.tar.gz 需要压缩文件/目录
-z :用gzip对包进行压缩
-c :创建包(create)
-v :显示明细(verbose)
-f :file
2、解压缩
tar -zxvf 压缩包名字.tar.gz -C 路径
-C :指定解压路径,不写默认解压到当前目录
3、练习
1、在用户主目录下创建目录 你 、我
cd
mkdir 你 我
2、在目录 你 下面创建文件:file1 file2 file3
cd 你
touch file1 file2 file3
3、用 vi 在 file1中写入:
vi file1
人生苦短,我用Python
野路子:ll tar xf ...
4、将目录 你 打包压缩为 你.tar.gz
cd
tar -zcvf 你.tar.gz 你/
5、将 你.tar.gz 剪切到 目录 我 下
mv 你.tar.gz 我/
6、将 你.tar.gz 解压缩到当前目录
cd 我/
tar -zxvf 你.tar.gz
5、文件权限
1、查看 :ls -l 文件名
-rw-rw-r-- tarena tarena 2 A.txt
2、最左侧一列 :-代表类型
1、d :目录
2、- :文件
3、l :链接(link)
3、权限
r :读
w :写(编辑)
x :可执行
4、rwx权限分组
第1组 :文件所有者权限
第2组 :同组用户对文件权限
第3组 :其他组用户对文件权限
场景(3个用户)
用户1 :tarena 组:tarena :rw-
用户2 :tarena2 组:tarena :rw-
用户3 :cloud 组:cloud :r--
6、chmod :修改文件权限
1、方式1
1、给所有用户添加相关权限
chmod +x/-w/+rwx/-wx A.txt
2、给指定组用户修改权限
chmod u+x A.txt
chmod o+rwx A.txt
a :所有用户(all)
u :所有者(user)
g :同组用户(group)
o :其他用户(other)
2、方式2(通过数字方式修改)
chmod 644 A.txt :rw-r--r--
chmod 666 A.txt :rw-rw-rw-
r :4
w :2
x :1
chmod 777 A.txt :rwxrwxrwx
3、练习
1、在用户主目录下创建文件 :密函.txt
touch 密函.txt
2、用 vi 在文件中写入:
我的密函
回眸一笑百媚生,六宫粉黛无颜色
春宵苦短日高起,从此君王不早朝
3、查看 密函.txt 权限
ls -l 密函.txt
4、将文件权限设置为自己可读可写可执行,其他人任何权限没有
chmod 700 密函.txt
5、在4的基础上将权限设置为同组用户只读
chmod 740 密函.txt
chmod g+r 密函.txt
6、将文件的可执行权限给去掉
chmod -x 密函.txt
7、将 密函.txt 复制到用户主目录下的AID09中
cp 密函.txt AID09/
1、sudo :获取root用户的权限执行Linux命令
cd /
touch A :提示权限不够
sudo touch A
## 只要提示权限不够你就去加sudo ##
2、df -h :查看磁盘使用情况
/dev/sda1 216G 16G 189G 8% /
3、top :任务管理器,查看%CPU
4、ps -aux :查看某个应用程序的PID号
ps -aux | grep "firefox"
cat 福永小姐姐.doc | grep "hello"
5、kill -9 PID号
1、Python简介
1、应用领域
1、系统运维
2、网络编程
3、人工智能、机器人
4、Web开发
5、云计算、大数据
6、爬虫、游戏、图像 ... ...
2、优点
1、面向对象
2、开源、可移植
3、简单易学易用、开发效率高
3、缺点
执行效率低
2、版本
1、Python2(2020年停止维护)
Python2.7
2、Python3
Python3.5(教学环境)
Python3.8(最新)
1、文件 :hello.py
功能 :在终端输出 hello world
2、运行 :python3 hello.py
1、多行注释/取消注释 :Ctrl + /
2、保存 :Ctrl + s
3、回退 :Ctrl + z
4、同时选中多个光标 :Ctrl + 鼠标左键单击
1、进入 :python3
2、退出 :exit() 、quit() 、Ctrl + d
1、数字类型
1、分类
1、整型int :100 5 20
2、浮点型float :6.66 8.88 3.0
2、整型的表示方式
1、十进制
35 3*10**1 + 5*10**0= 35 50 666
2、二进制(0b开头)
0b0000 # 0
0b0001 # 1
0b0010 # 2
0b01001000 # 1*2**6 + 1*2**3 = 72
3、十六进制(以0x开头)
0 1 2 3 4 5 6 7 8 9 a b c d e f
0x11 # 1*16**1 + 1*16**0 = 17
0xFF # 15*16**1 + 15*16**0 = 255
0xA0 # 10*16**1 + 0*16**0 = 160
4、八进制(以0o开头)
0o177 # 1*8**2 + 7*8**1 + 7 = 127
0o11 # 1*8**1 + 1 = 9
2、字符串
3、列表、元组 ... ...
4、布尔类型bool :True 、False
5、空值 :None
1、分类
+ - * /
% :取余数
** :幂运算
// :地板除,只要整数
2、优先级(加()控制)
**
* / % //
+ -
3、示例
同学们毕业薪资是10000.00元,每年涨20%,十年后你的薪资是多少钱?
4、练习
超市的西瓜7元1个,你有100元,能买几个西瓜,找零多少?
% //
1、格式化字符串 % 变量名
格式化字符串 % (变量1,变量2)
2、%s 占位 :字符串
%d 占位 :整数
%f 占位 :浮点数 %.2f(保留2位小数)
3、练习
1、定义2个变量,computer you,值分别为:石头、布,终端输出:
电脑出拳:石头 你出拳:布 恭喜,你赢了!
2、定义3个变量,name,gongsi,salary,终端输出:
...入职...公司,薪资为...元
3、一个圆的半径为3厘米,计算圆的周长和面积
pi :3.14
半径为3厘米的圆的周长为:?厘米
半径为3厘米的圆的面积为:?平方厘米
周长 :2 * 3.14 * 3
面积 :3.14 * 3 ** 2
4、超市的苹果9元一斤,你有100元,能买几斤苹果,还剩多少钱?(占位符)
5、假如你现在23周岁,每年365天,计算你大概过了多少个星期天?(占位符)
6、从凌晨0:0:0计时,到现在过了66666秒,请问现在是几点几分几秒(占位符)
10、作业
1、在终端输出图形
*
***
*****
***
*
2、中国古代的秤是16两1斤,请问现在的216两是古代的几斤几两,写程序打印出来
3、温度转换
摄氏温度 = 5.0/9.0*(华氏温度-32)
开氏温度 = 摄氏温度 + 273.15
请问:100华氏温度转为摄氏温度是多少度?
转为开氏温度为多少度?
python_day01回顾
命令:
cp / cp -r 复制文件/文件夹
mv 移动文件/文件夹(改名字)
cat 显示文本文件的内容
tar 打包并压缩 $ tar -czvf 文件夹
解包并压缩 $ tar -xzvf a.tar.gz
mkdir 创建文件夹
rmdir 删除文件夹
touch 创建文件/更新文件的修改时间
chmod 修改文件权限
(读/写/执行)
rwx rwx rwx
sudo 获取root用户权限, 用权限来执行命令
df 查看磁盘
top 任务管理器
ps 查看pid 进程
python
应用领域
python版本
python V3
python V2
python的执行:
$ python3 xxxxx.py
$ python3 <回车> # 交互模式
>>>
>>> exit() / quit() / ctrl + d
python的数据类型:
字符串,数字, 列表....
数字类型:
整型数 int
十进制 : -100 0 99 9999999 11
十六进制: 0x1234 0xABCD 0xabcd 0x11
八进制 : 0o12345670 0o11
二进制 : 0b11
浮点型数 float
3.14 .14 0.14 3. 3.0
314e-2 0.314e1 3.14E0
复数 complex
(1 + 2j)
布尔型数 bool
True/False
1 / 0
字符串:
'' ""
算术运算符:
+ - * / // % **
% 字符串的格式化
vscode (Visual Studio Code / Microsoft)
缩放 ctrl + + / ctrl + -
注释 ctrl + /
保存 ctrl + s (重要)
启动 vscode 的命令:
$ code <回车>
$ code 文件名<回车>
$ code 文件夹名<回车>
什么是变量:
变量是关联一个对象的标识符
变量可以绑定一个对象,并可以通过变量名使用这个对象
标识符的命名方法:
以字母或下划线开头,后跟字母下划线或数字
说明:
标识符区分大小写
示例:
a A a1 bbbb set_age _ _abcd __abcde
a1b2
不合法的标识符:
1a 123 $ABC
python的关键字不能用作变量名:
True, False, None, is, del, if,......
符号 =
语法:
变量名 = 表达式
或
变量名1 = 变量名2 = 表达式
或
变量名1, 变量名2, ... = 序列
作用:
创建一个变量并绑定数据对象
改变一个变量的绑定的数据对象
示例:
a = 10
b = 20
c = a + b # c 绑定 30
a = b = c = 10000 # 同时改变三个变量的绑定关系
# 同时绑定在10000上
x, y = 100, 200 # 用x绑定100, 用y绑定200
练习:
指定一个长方形长边长 6(厘米)
短边长 4(厘米)
打印出这个长方形的周长和面积
赋值语句说明:
1. 当变量不存在时,赋值语句会创建该变量,同时将变量
绑定在赋值运算符右侧的对象上
2. 当变量存在时,改变此变量的绑定关系
3. 一个变量只能绑定一个对象
4. 多个变量可以同时绑定在一个对象上
如:
a = 100
b = a # b也同时绑定在a绑定的那个100上
作用:
用于删除变量,同时解除与对象的关联关系,如果可能则
释放对象
语法:
del 变量名1, 变量名2, ...
在交互模式下查看当前作用域内的所有变量:
>>> help('__main__')
示例:
a = 100
b = 200
x, y = 123, 456
del a
del b, x, y # 同时删除3个变量
自动化内存管理和引用计数:每个对象都会记录有几个变量引用(绑定)自身,当引用的数量为0时,则此对象被销毁,此种自动化内存管理的方式叫"引用计数"
作用:
判断两个对象是否是同一个对象,当是同一个对象时
返回True,否则返回False
is not 与 is 的返回值相反
语法:
x is y
x is not y
作用:
返回一个对象在内存中的地址
说明:
is运算符是根据id来进行判断的
格式:
id(对象)
CPython中,整数-5至 256 永远存在于小整数对象池中不会释放,并可重复使用
运算符 说明
y += x 等同于 y = y + x
y -= x 等同于 y = y - x
y *= x 等同于 y = y * x
y /= x 等同于 y = y / x
y //= x 等同于 y = y // x
y %= x 等同于 y = y % x
y **= x 等同于 y = y ** x
< 小于
<= 小于等于
> 大于
>= 大于等于
== 等于
!= 不等于
语法:
左表达式 < 右表达式
说明:
比较运算符返回布尔类型的值
示例:
100 < 200
1 + 5 == 2 + 4
0 <= 60 <= 100
数值对象的构造函数(创建) 函数
float(obj) 用字符串或数字转换为浮点数,如果
不给出参数,返回0.0
int(x, base=10) 或 int(x=0) 用数字或字符串转
换为整数。如果不给出参数,返回0
complex(r=0.0, i=0.0) 用数字创建一个复数(
实部为r, 虚部为i)
bool(x) 用x创建一个布尔值(True/False)
函数调用的语法:
函数名(传参列表)
说明:
函数调用是一个表达式,一定会返回一个对象的引
用关系(或者返回None)
值 说明
None 空值
False 布尔假值
0 0.0 0j 数字0
------- 以下后面才学------
'' 字符串
[] 空列表
() 空元组
{
} 空字典
....
练习:
将数字 3.14 用变量 pi 绑定
将 pi 变量转为整数 用变量 i 绑定
将 pi 变量与 i 变量相减,结果用变量 f 绑定
1. 判断f是否等于 0.14
2. 删除所有的变量
(用交互模式来做)
abs(x) 取x的绝对值
round(number[, ndigit]) 对数值进行"四舍五入",
ndigit是小数向右取整的位数,负数表示向左
取整
pow(x, y, z=None) 相当于 x**y 或 x**y%z
示例:
abs(-100) # 100
round(1234.56789) # 1235
round(1234.56789, 2) # 1234.57
round(1234.56789, 4) # 1234.5679
round(1234.56789, -2) # 1200.0
pow(5, 2) # 25
pow(5, 2, 10) # 5
>>> help(函数名) # 查看相应函数的帮助
语句由一些表达式组成,通常一条语句可以独立的执行来
完成一部分事情并形成结果
多条语句写在一行内要用分号(;) 分开
示例见:
code/statement.py
当语句太长时,一行无法摆放,用 \(反斜杠)进行显式折行
示例见:
statement2.py
所有的括号的内容换行,称为隐式折行
能用于隐式折行的括号有:
() [] {
}
基本输入函数 input
作用:
从一个标准输入设置上读取一个字符串(不包含换行符)
格式:
input('提示字符串')
说明:
返回用户输入的字符串
'提示字符串'可以为空
示例见:
input.py
基本输出函数 print
格式:
print(value, ..., sep=' ', end='\n',
file=sys.stdout, flush=False)
将一系列的值以字符串形式输出到标准输出设备
上(默认为终端)
参数选项:
sep: 两个值之间的分隔符(默认为一个空格' ')
end: 输出完毕后在末尾自动追加一个字符串(默认
为换行符'\n')
file: 流对象(默认为sys.stdout)
flush: 是否立即将流进行输出
练习:
1. 输入两个整数,分别用变量x,y绑定
1) 计算这两个数的和,并打印结果
2) 计算这两个数的积,并打印结果
3) 计算 x 的 y 次方是多少?并打印
2. 分三次输入当前时间的小时,分钟,秒数
再计算出距离凌晨0:0:0过了多少秒
3. 计算三险一金:
已知社保的缴费比率是:
项目 个人缴费比例 单位缴费比例
养老保险 8% 19%
工伤保险 0% 0.5%
医疗保险 2%+3元 10%
住房公积金 12% 12%
输入您在北京的社保基数(如: 5000)
打印您和公司的个项缴费明细、个人总缴费金额、
单位缴费金额及国家拿到的钱是多少?
day02回顾
python的版本
python V2
python V3
python的运行:
1. 在命令行提示符下
$ python3 xxxx.py
2. 在交互模式下执行:
$ python3 <回车>
>>>
>>> quit() / exit() / ctrl+d # 退出
python的注释:
以 # 开头,直至行尾
python常用的数据类型:
数字类型:
int
0, 999999999, -2, 0b1001, 0o11, 0x9
float
3.14, 0.314e1 314.0e-2
complex
1+2j
bool
True, False
字符串
列表
....
空值对象
None, 代表不存在(啥也没有)
运算符:
算术运算符:
+ - * / //(地板除) % (求余) **(幂运算)
比较运算符:
< <= > >= ==(等于) !=(不等于)
赋值语句:
变量 = 表达式
变量1 = 变量2 = 变量3 = 表达式
变量1, 变量2, 变量3 = 序列
作用是创建变量用来绑定表达式执行的结果
del语句
del 变量名
作用是删除变量
is,is not 运算符
判断两个对象的id是否相同
复合赋值算术运算符:
+= -= *= /= //= %= **=
y +=x 效果等同于 y = y + x
函数:
类型转换函数:
float(obj)
int(x, base=10), int(x=0)
complex(r=0.0, i=0.0)
bool(x)
函数调用的语法规则
函数名(传参列表)
函数调用是表达式,一定会返回一个结果(结果可能是None)
数值型函数:
abs(x) 取x的绝对值
round(number[,ndigit]) 取number的近似值
pow(x, y, z=None) # 求x的y次方或x的y次方对z求余
查看帮助的函数:
>>> help('字符串')
>>> help(函数名)
基本输入输出函数:
input("提示字符串") # 获取用户输入的字符串
print(value1, value2,..., sep=' ', end='\n'))
作用是把数字形成字符串后打印在屏幕终端上
if 语句
问题:
有两条语句:
print("这个数是偶数")
print("这个数是奇数")
如何只让其中的一条执行???
if语句的作用:
让程序根据条件选择性的执行某条语句或某些语句
语法:
if 真值表达式1:
语句块1...
elif 真值表达式2:
语句块2...
elif 真值表达式3:
语句块3....
...
else:
语句块4
说明:
elif 子句可以有0个,1个或多个
else 子句可以有0个或1个,且只能放在if语句的最后
示例见:
if.py
练习:
任意输入一个整数
1) 判断这个数是否大于100
2) 判断这个数是否小于0
3) 判断这个数是否在50~150之间
(建议每一步用一个if语句来实现)
if-elif-else示例见:
if_elif.py
练习:
1.输入一个季度1 ~ 4 输出这个季度有哪儿几个月份.
如果输入的不是1~4的整数,提示用户您输错了
2. 输入一年中的月份(1~12),输出这个月在哪儿个季度。
如果输入的是其它的数,则提示您输错了
if 语句嵌套
if语句本身是由多条子句组成的一条复合语句
if语句可以作为语句嵌套到另一个复合语句的内部
示例见:
if_embed.py
条件表达式
语法:
表达式1 if 真值表达式 else 表达式2
作用:
根据真值表达式的取值(True/False) 来决定执行表达式1
或者表达式2并返回结果
示例见:
if_express.py
练习:
1. 写一个程序,输入一个数,用if语句计算出这个数的
绝对值并打印出来
2. 写一个程序,输入一个数,用条件表达式计算出这个数
的绝对值并打印出结果
pass 语句
作用:
通常用来填充语法空白
pass 又名空语句
语法:
pass
示例见:
pass.py
布尔运算:
运算符:
not and or
非 与 或
1.布尔非操作 not
语法
not x
作用:
对x进行布尔取非,如bool(x) 为True,则返回False,
否则为True
示例:
2.布尔与操作 and
语法:
x and y
注: x,y 代表表达式
作用:
优先返回假值对象,当x的布尔值为False时,返回x
否则返回y
示例:
True and True # True
True and False # False
False and True # False
False and False # False
100 and 0.0 # 0.0
0 and 0.0 # 0
3.布尔或操作 or
语法:
x or y
作用:
优先返回真值对象,当x为True时返回x,否则返回y
示例:
True or True # True
True or False # True
False or True # True
False or False # False
3.14 or 100 # 3.14
0 or 0.0 # 0.0
正负号运算符
+(正号) -负号
注: 一元运算符(一个元素参加运算)
语法:
+ 表达式
- 表达式
示例:
a = 5
b = -a # -负号
c = +a # 正号
print(a, b, c) # 5 -5 5
字符串 str
作用:
用来记录文字(文本)信息
表示方法:
在非注释中凡是用引号括起来的部分都是字符串
' 单引号
" 双引号
''' 三单引号
""" 三双引号
空字符串的字面值表达方法
'' "" '''''' """"""
非空字符串的字面值的表达方法
'hello' "hello" '''hello''' """hello"""
单引号内的双引号不算结束符
双引号内的单引号不算结束符
示例见:
str.py
三引号字符串可以包含单引号和双引号
三引号字符串中的换行会自动转换为换行符'\n'
示例见:
str2.py
隐式字符串字面值拼接
示例:
s = "I'm a teacher" 'my name is "Tarena"'
print(s) #
用转义序列代表特殊字符
字符串字面值中用字符反斜杠 \ 后跟一些字符代表
特殊的一个字符,如:
转字格式 含义
\' 代表一个单引号
\" 代表一个双引号
\\ 代表一个反斜杠
\n 换行
\r 返回光标至行首
\f 换页
\t 水平制表符
\v 垂直制表符
\b 倒退
\0 空字符(字符值为0)
\0oo oo为两位八进制表示的字符
\xXX XX为两位十六进制表示的字符
\uXXXX 四位十六进制表示的Unicode 16字符
\UXXXXXXXX 八位十六进制表示的Unicode 32字符
ASCII编码表
$ man ascii<回车>
常用的ASCII编码
字符 十进制 十六进制
'0' 48 0x30
'A' 65 0x41
'a' 97 0x61
序列的概念
字符串是序列(有序排列)
所有的序列都能用len(x) 函数求其长度
len(x) 函数
返回字符串中字符的个数
练习:
用交互模式验证如下字符串有几个字符
1. '1234abcd' # 8个
2. '5\'4"' # 4个
3. '\"A\x34\056'# 4个
4. '\a\bc\td\n' # 6个
raw 字符串(原始字符串)
格式:
r'字符串内容'
r"字符串内容"
r'''字符串内容'''
r"""字符串内容"""
作用:
让转义符号反斜杠 \ 无效
示例:
a = 'C:\newfile\test.py'
print(a)
print(len(a))
a = r'C:\newfile\test.py'
print(a)
print(len(a))
字符串的运算:
运算符:
+ += * *=
+ 加号运算符用于拼接字符串
x = "ABCD"
y = "123"
z = x + y
print(z) # ABCD123
+= 用于原字符串和右侧字符串拼接,再用变量绑定新的
字符串
x = 'ABC'
y = '123'
x += y
print(x) # ABC123
* 运算符生成重复的字符串
x = "ABC" * 3
print(x) # ABCABCABC
注: 字符串只能和整数相乘
*= 生成重复的字符串,再用原变量绑定
x = '123'
x *= 2
print(x) # 123123
字符串的比较运算
运算符:
< <= > >= == !=
比较规则:
依次按编码值进行两两字符比较,一但不同,则比较结束
并返回比较结果,当编码值和长度完全相同时,两个字符
串相同
示例:
'A' < 'B' # True
'ABC' > 'ABB' # True
'ADC' < 'ABC' # False
'ABC' >= '123' # True
'AB' < 'ABC' # True
'abc' == 'ABC' # False
in, not in 运算符
作用:
in 用于序列,字典,集合中,用于判断某个值是否存
在于容器中,如果存在则返回True,则返回False
not in 与 in 运算符的返回结果相反
格式:
对象 in 序列
示例:
x = 'welcome to tarena!'
'to' in x # True
'hello' in x # False
'e t' in x # True
'abc' not in x # True
练习:
练习:
1. 北京出租车计价器:
收费标准:
3公里以内收费 13元
基本单价 2.3元/公里(超出3公里以外)
空驶费: 超过15公里后,每公里加收单价的50%的
空驶费(3.45元/公里)
要求: 输入公里数,打印出费用金额
2. 输入一个学生的三科成绩:
1) 打印出最高分是多少分?
2) 打印出最低分是多少分?
3) 打印出平均分是多少分?
3. 计算 BMI指数(Body Mass Index) 又称身体质量指数
计算公式:
BMI = 体重(公斤)/身高的平方(米)
如:一个69公斤的人,身高173公分,则
BMI = 69 / 1.73 ** 2 # 得23.05
标准表:
BMI < 18.5 体重过轻
18.5 <= BMI < 24 体重正常
BMI >= 24 体重过重
要求: 输入身高和体重,打印BMI的值,并打印体重状况
4. 写一个程序.打印一个高度为4行的矩形方框
要示方输入一个整数,此整数代表矩形的宽度,输入此矩形
如:
请输入矩形宽度: 10
打印如下:
##########
# #
# #
##########
如果输入的数字越大,则此矩形会越宽
day03回顾:
if语句
根据条件选择性的执行某条或某些语句
语法:
if 真值表达式:
语句块1
elif 真值表达式2:
....
elif ....:
....
else:
语句块
第一条复合语句
if语句的嵌套
if xxx:
if yyy:
if zzzz:
...
else:
....
else:
....
pass 语句
填充语法空白
条件表达式
x + 1 if y > x else x + 2
布尔运算:
and or not
一元运算符:
+(正号) -(负号)
-100
字符串 str
"hello" 'ABC中文' 'A B C' '\n\t'
' " ''' """ 开头和结尾
空字符串的布尔值为False
转义字符:
'\n' '\r' '\\' '\'' '\"' '\t'
'\xXX' '\uXXXX' '\UXXXXXXXX'
ascii 编码
len(x) 求字符串长度
原始字符串
r'abc'
r"ab\n\rcd"
r'''abc'''
r"""abc"""
r'''ab
cd''' # 等同于'ab\ncd'
字符串的运算:
+ 拼接 * 重复n次 += *=
< <= > >= == !=
"ABC" == "ABC"
"ABC" == "CBA" # False
in , not in
索引 index
python字符串是不可以改变的字符序列
索引取值语法:
字符串[整数表达式]
说明:
python的序列都可以用索引(index) 来访问序列中的对象
python序列的正向索引是从0开始的,第二个索引为1,最后
一个索引为len(s)-1
python序列的反向索引是从-1开始的,-1代表最后一个,
-2代表倒数第二个,以此类推。第一个是-len(s)
示例:
s = "ABCDE"
print(s[1]) # B
print(s[4]) # E
print(s[-1]) # E
print(s[-5]) # A
print(s[100]) # IndexError 越界
练习:
写程序输入一个字符串,打印字符串中的如下内容
1. 打印这个字符串的第一个字符
2. 打印这个字符串的最后一个字符
3. 如果这个字符串的长度是奇数,打印中间这个字符
注:
求字符串长度的函数是 len(s)
切片 slice
作用:
从字符串序列中取出相应的元素重新组成一个新的字符串
语法:
字符串[(开始索引b):(结束索引e)(:(步长s))]
注:
小括号() 括起来的部分代表可省略
说明:
开始索引是切片开始切下的位置,0代表第一个元素,1代表
第二个元素,-1代表最后一个....
结束索引是切片的终止索引(但不包含终止点)
步长是切片每次获取完当前元素后移动的方向和偏移量
1. 没有步长,相当于步长为1(默认为1)
2. 当步长为正整数时,取正向切片:
开始索引默认为0,结束索引默认是最后一个元素的
下一个位置
3. 当步长为负整数时取反向切片:
反向切片时,默认的起始位置为最后一个元素,终止
位置是第一个元素的前一个位置
示例:
s = "ABCDE"
a = s[1:4] # a---> "BCD"
a = s[:4] # 'ABCD'
a = s[1:] # 'BCDE' # 等同于s[1:5]
a = s[:] # 'ABCDE' # 等同于s[0:5]
a = s[1:1] # '' 空字符串
a = s[4:2] # '' 空
a = s[0:5:2] # 'ACE'
a = s[4:0:-2] # 'EC'
a = s[4::-2] # 'ECA'
a = s[::-1] # 'EDCBA'
练习:
1. 写一个程序,输入一个字符串,把字符串的第一个字符和
最后一个字符去掉后,打印出处理后的字符串
2. 写程序,输入任意一个字符串,判断这个字符串是否是回文
回文是指中心对称的文字,如:
上海自来水来自海上
ABCCBA
文档参见:
python_base_docs_html/Python运算符优先级.html
文档参见:
python_base_docs_html/Python运算符优先级.html
python3中能用于字符串的函数:
len(x) 返回字符串长度
max(x) 返回字符串编码值最大的字符
min(x) 返回字符串中编码值最小的字符
字符串的编码转换函数:
ord(c) 返回一个字符c的unicode编码值
chr(i) 返回i这个值所对应的字符
示例:
x = ord('A') # x = 65
c = chr(66) # c = 'B'
练习:
1. 写一个程序,输入一段字符串,如果字符串不为空,则把第
一个字符的编码值打印出来
2. 写一个程序,输入一个整数(0~65535),打印这个数值所
对应的字符
整数转换为字符串的函数:
bin(i) 将整数转换为二进制字符串
oct(i) 将整数转换为八进制字符串
hex(i) 将整数转换为十六进制字符串
字符串构造(创建)函数:
str(obj) 将对象转换为字符串
示例:
'123' + 456 # 出错
'123' + str(456) # 结果 '123456'
python3中常用的字符串方法(method)
方法的调用语法:
对象.方法名(方法传参)
示例:
'abc'.isalpha() # 返回True
'123'.isalpha() # 返回False
123.isalpha() # 出错
方法见文档:
python_base_docs_html/str.html python_base_docs_html/str.html
练习:
输入一个字符串:
1. 判断您输入的字符有几个空格
2. 将原字符串的左右空白字符去掉,打印出有效的字符
个数
3. 判断您输入的是否是数字,
如果是数字,判断用户输入的数字是否大于100
1.字符串格式化表达式
作用:
生成一定格式的字符串
运算符:
%
语法格式:
格式化字符串 % 参数值
格式化字符串 % (参数值1, 参数值2, 参数值3, ...)
说明:
格式化字符串中以%开头的字符为占位符,占位符的位置将
用参数值替换
示例:
fmt = "name: %s, age: %d"
s2 = fmt % ("Tarena", 15)
fmt2 = "年龄: %d"
s3 = fmt2 % 35
2.格式化字符串中的占位符类型码
占位符和类型码 含义
%s 字符串,使用str(x) 函数转换
%r 字符串,使用repr(x) 函数转换
%c 整数转为单个字符
%d 十进制整数
%o 八进制整数
%x 十六进制整数(字符a-f小写)
%X 十六进制整数(字符A-F大写)
%e 指数形浮点数(e小写) 如: 2.9e8
%E 指数形浮点数(E大写) 如: 2.9E8
%f,%F 浮点十进制数
%g,%G 十进制形式浮点或指数浮点自动转换
%% 等同于一个%字符
3.占位符和类型码之间的格式语法
% [ - + 0 宽度.精度 ] 类型码
- 左对齐(默认是右对齐)
+ 显示正号
0 左侧空白位置补零
宽度 整个数据输入的宽度
精度 保留小数点后多少位(默认为6位)
示例:
"%10d" % 123 # ' 123'
"%-10d" % 123 # '123 '
"%10s" % "abc" # ' abc'
'%-5s' % 'abc' # 'abc '
'%05d' % 123 # '00123'
'%+05d' % 123 # '+0123'
'%7.3f' % 3.1415926535 # ' 3.142'
练习:
输入三行文字,让这三行文字依次以20个字符的宽度右对齐
显示
如:
请输入第1行: hello world
请输入第2行: abcd
请输入第3行: aaaaaaa
打印结果如下:
hello world
abcd
aaaaaaa
做完上题后再思考:
能否以最长的字符串的长度进行右对齐显示(左侧填充
空格)
循环语句:
while 语句
for 语句
问题:
输入一个整数n,写程序打印如下n行文字:
这是第1行
这是第2行
这是第3行
...
这是第n行
while语句:
作用:
根据一定条件,重复执行一条语句或多条语句
语法:
while 真值表达式:
语句块1(此部分语句可能会重复执行多次)
else:
语句块2
说明:
1. 先执行真值表达式,得到布尔值为True或False
2. 如果真值表达式的值为True,则执行语句块1,然后再
次返回到第1步,重复进行测试真值表达式的值
3. 如果真值表达式的值为False,则执行else子句部分
的语句块2,然后结束此while语句的执行
注: else子句部分可以省略(同if语句类似)
示例见:
while.py
练习:
1. 输入三行文字,让这三行文字在一个方框 内居中显示
如输入:
hello!
I'm studing python!
I like python!
显示如下:
+---------------------+
| hello! |
| I'm studing python! |
| I like python! |
+---------------------+
2. 用while循环打印 1 ~ 20 的整数(可以打印多行)
3. 用while循环打印 1 ~ 20 的整数,打印在一行显示
每个数字之间用一个空格分隔
1 2 3 4 5 6 .... 18 19 20
4. 用while循环打印 1 ~ 20的整数,每行打印5个,
打印4行,如:
1 2 3 4 5
6 7 8 9 10
...
5. 输入一个整数n,打印一个宽度和高度都为n个字符的长方形
如:
请输入: 4
打印:
####
# #
# #
####
如:
请输入: 6
打印:
######
# #
# #
# #
# #
######
day04回顾:
字符串的 索引,切片
索引
取出一个字符
切片:
取出一些字符重新组成字符串
索引的语法:
字符串[整数表达式]
切片的语法:
字符串[开始索引:结束索引:步长]
函数:
chr(整数) # 转为字符串(只包含一个字符)
ord(一个字符) # 转为整数编码值
bin(i)
oct(i)
hex(i)
str(obj) 将对象转为字符串
字符串常用的方法:
S.isdigit()
S.isalpha()
S.islower()
S.isupper()
S.isspace()
S.center(width, fill=' ')
S.count(sub, start, end)
S.find(...)
S.strip([char]) / S.lstrip() S.rstrip()
S.upper() / S.lower()
S.replace(old, new)
S.startswith(字符串) / S.endswith(字符串)
>>> help(str)
字符串的格式化表达式
"姓名: %s, 姓别:%s, 年龄:%d" % ("小张", "男",20)
常用的占位符和类型码:
%s
%d
%f %7.2f %-7.2f %+7.2f %07.2f
while 语句 (循环语句)
语法:
while 真值表达式:
可能重复执行的语句块
else:
语句块2
练习:
1. 输入一个整数n代表结束的数值,求下列表达式的和
1 + 2 + 3 + 4 + .... + (n-1) + n的和
如:
请输入: 100
打印:
5050
while语句的注意事项:
1. 要控制循环的真值表达式的值来防止死循环
2. 通常用真值表达式内的循环变量来控制循环条件
3. 通常在语句内部改变循环变量
1. 要控制循环的真值表达式的值来防止死循环
2. 通常用真值表达式内的循环变量来控制循环条件
3. 通常在语句内部改变循环变量
while 语句嵌套:
while 语句本身就是语句,和其它语句一样,可以嵌套到
任何的复合语句中
示意:
while 真值表达式:
....
while 真值表达式2:
....
else:
...
...
else:
...
示例见:
while_embed.py
练习:
输入一个整数n,打印指定宽度的正方形
如:
请输入: 5
打印:
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
如:
请输入: 3
打印:
1 2 3
1 2 3
1 2 3
break 语句
问题:
如果在循环过程中不想再继续循环语句的执行了,怎么办?
作用:
用于循环语句(while,for语句)中,用来终止当前循环语句
的执行.
说明:
当break语句执行后,此循环语句break之后的语句将不再执行
break 语句通常和if语句组合使用
break 语句终止循环时,循环语句的else子句的语句不会执行
break 语句只能终止当前循环语句的执行,如果有循环嵌套
时,不会跳出嵌套的外重循环
break语句只能在循环语句(while,for语句)的内部使用
示例见:
break.py
死循环
死循环是指循环条件一直成立的循环
死循环能通常用break语句来终止循环
死循环的else子句永远不会执行
让用户任意输入一些整数,当输入负数时结束输入
当输入完成后,打印您输入的这些数的和
如:
请输入: 1
请输入: 2
请输入: 3
请输入: 4
请输入: -1
打印: 10
循环语句:
while语句
for语句
for语句
作用:
用来遍历可迭代对象的数据元素
可迭代对象是指能依次获取数据元素的对象
如:
字符串,列表,元组,range函数返回的对象等
语法:
for 变量列表 in 可迭代对象:
语句块1(此处是可能重复执行的语句块)
else:
语句块2
说明:
当在循环体内用break终止循环时,else子句部分的语
句不会执行
else子句部分可以省略
示例见:
for.py
练习:
练习:
任意输入一段字符串
1) 计算出字符串中空格的个数
2) 计算出字符串中中文字符的个数
(注: 中文 字符的编码值一定大于128,可用ord判断)
range() 函数:
range(stop) 用来生成0~stop区间内的整数,直到stop为
止(不包含stop)
range(start, stop[,step]) 用来生成start~stop区
间内的整数,直到stop为止(不包含stop),
每个整数间隔step
格式详见:
>>> help(range)
作用:
用来创建一个生成一系列整数的可迭代对象(也叫整数序列
生成器)
示意:
range(4) 生成 0, 1, 2, 3
range(3, 6) 生成 3, 4, 5
range(1, 10, 2) 生成 1, 3, 5, 7, 9
range(5, 0, -1) 生成 5, 4, 3, 2, 1
range(5, 0, -2) 生成 5, 3, 1
range(4, 0) 生成 空
示例见:
range.py
练习:
1. 打印 1 ~ 20的整数,打印在一行(用for语句实现)
2. 计算 1 + 2 + 3 + 4 + ..... + 99 + 100的和
(用for和range实现)
3. 计算 1 + 3 + 5 + 7 + .... + 97 + 99的和
(用for语句实现)
for语句嵌套:
示例:
for x in "ABC":
for y in "123":
print(x + y)
continue 语句
问题:
如何让程序不再向下执行,重新开始一次新的循环?
作用:
用于循环语句(while,for)中,不再执行本次循环内
continue之后的语句,重新开始一次新的循环
说明:
1. 在while语句中执行continue语句,将会直接跳转到
while语句的真值表达式处,重新判断循环条件
2. 在for语句中执行continue语句,将会从可迭代对象
中取下一个数据绑定变量后再次进行循环
示例见:
continue.py
练习:
求:1 ~ 100之间所有不能被 2, 3, 5, 7整除的数的和
循环总结:
while 语句
for 语句
字符串str
range() 函数返回的对象
break 语句
continue 语句
问题:
容器
如何将计算机运算的数据临时存入一个地方,同时又
方便添加,删除,修改,查看等操作
列表 list
列表是一种容器
列表是可以被改变的序列容器
创建空列表的字面值
L = [] # L 绑定一个新创建的空列表
创建非空列表的字面值:
L = [1, 2, 3, 4]
L = ["北京", "上海", "深圳"]
L = [1, "二", 3.14, "Four"]
L = [1, 2, [3.1, 3.2, 3.3], 4]
列表的构造(创建)函数 list
list() 创建一个空的列表,等同于[]
list(iterable) 用可迭代对象创建一个列表
示例:
L = list() # L绑定空列表
L = list("hello") #L绑定['h','e','l','l','o']
L = list(range(10)) # L绑定[0,1,2,3...9]
列表的运算:
算术运算符
+ += * *=
示例:
+ 加号用于拼接列表
x = [1, 2, 3]
y = [4, 5, 6]
z = x + y # z = [1, 2, 3, 4, 5, 6]
+= 用于原列表与右侧可迭代对象进行拼接,用变量绑定列表
语法:
x += 可迭代对象
如:
x = [1, 2, 3]
y = [4, 5, 6]
x += y # x绑定[1, 2, 3, 4, 5, 6]
x =
* 生成重复的列表
*= 让原列表重复n次再用原变量绑定
x = [1, 2] * 3 # x =[1, 2, 1, 2, 1, 2]
x = [1, 2]
x *= 2 # x = [1, 2, 1, 2]
练习:
1.输入一个整数n,此整数代表三角形的直角边长
根据整数n打印如下四种三角形
请输入: 3
打印如下:
1)
*
**
***
2)
*
**
***
3)
***
**
*
4)
***
**
*
2. 写一个程序,任意输入一个整数,判断这个整数是否是素数(prime)
素数(也叫质数), 只能被1和自身整除的正整数
如: 2 3 5 7 11 13 17 19
提示:
用排除法,当判断x是否为素数时,只要让x分别除以
2, 3, 4, ... x-1 ,只要有一个能整除,则x不是
素数,否则x是素数
3. 输入一个正整数代表正方形的宽和高,打印如下正方形
如
请输入: 5
打印:
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
5 6 7 8 9
如
请输入: 3
打印:
1 2 3
2 3 4
3 4 5
day05回顾
循环语句
while 语句
for 语句
while 语法:
while 真值表达式:
语句块1
else:
语句块2
for 语法
for 变量名 in 可迭代对象:
语句块1
else:
语句块2
可迭代对象:
str
range() 返回的对象
list 列表
range(开始整数,结束整数,步长)
range(开始整数,结束整数)
range(结束整数)
break 语句
终止当前循环
break执行后,循环语句的else子句里的语句不会执行
continue语句
重新开始一次新的循环
对于while和 for 语句跳转位置不同
列表 list
创建列表的方式
[]
[1, 2, 3, 4]
[1, 2, [3, [4, 5]], 6]
构造函数
list()
list(可迭代对象)
列表的运算:
+ += * *=
+= 运算符等同于在原列表的末尾追加数据
L = [1, 2]
print(id(L))
L += [3] # 不等同于 L = L + [3]
print(id(L)) # id不变
列表的比较运算:
运算符:
< <= > >= == !=
说明:
列表的比较规则与字符串的比较规则相同
列表要求每两个元素能依次进行比较,否则会出现类型错误
示例:
[1, 2, 3] < [1, 2, 4] # True
[1, 2, 3] != [1, 2, 4] # True
["One", "Two"] < ["1", "2"] # False
[1, 'Two'] > ['Two', 1] # TypeError
[1, "二", 3.14] < [2, "2", 1] # True
列表的in / not in 运算符
判断一个值是否存在于列表中,如果存在则返回True,
否则返回False
同字符串的 in 运算符类似
示例:
x = [1, 'Two', 3, "四"]
3 in x # True
"3" in x # False
10 not in x # True
列表的索引操作:
1.索引取值
语法:
x = 列表[整数表达式]
用法:
等同于字符串的索引(同样分为正向索引和反向索引)
2.索引赋值
列表是可变的序列,可以通过索引赋值改变列表中的元素
语法:
列表[整数表达式] = 表达式
示例:
x = [1, 2, 3, 4]
x[2] = 1 + 2.14 # 改变了第三个元素的值
print(x)
列表的切片操作
1.切片取值
列表[起始索引:终止索引:步长]
列表的切片取值是从原列表中取出想要的元素再次组成一个
新的列表
示例:
L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
y = L[1:10:2] # y = [1, 3, 5, 7, 9]
2.切片的赋值操作
作用:
可以改变原列表的排列,可以插入,和修改数据
语法:
列表[切片] = 可迭代对象
说明:
切片赋值的赋值运算符(=)的右侧必须是一个可迭代对象
示例:
L = [2, 3, 4]
L[0:1] = [1.1, 2.2] # L=[1.1, 2.2, 3, 4]
L[0:2] = [2] # L = [2, 3, 4]
L[1:2] = [3.1, 3.2] # L = [2, 3.1, 3.2, 4]
L = [2, 3, 4]
L[1:1] = [2.1, 2.2] # L = [2, 2.1, 2.2, 3, 4]
L[0:0] = [0, 1] # L = [0, 1, 2, 2.1 ....]
L = [2, 3, 4]
L[3:3] = [5, 6] # L = [2, 3, 4, 5, 6]
L = [2, 3, 4]
L[1:2] = "AB" # L = [2, 'A', 'B', 4]
L[1:3] = range(7, 10) # L = [2, 7, 8, 9, 4]
3.切片的注意事项:
对于步长不等于1的切片赋值,赋值运算符的右侧的可迭代对象
提供的元素的个数,一定要等于切片切出的段数
L = [1, 2, 3, 4, 5, 6]
L[::2] = "ABC" # 对的
L[::2] = "abcd" # 错的
del 语句
可以用于删除列表的元素
语法:
del 列表[整数表达式]
del 列表[切片]
示例:
L = [1, 2, 3, 4, 5, 6, 7, 8]
del L[-1] # L = [1, 2, 3, 4, 5, 6, 7]
del L[1::2] # L = [1, 3, 5, 7]
练习:
已经有列表:
L = [3, 5]
用索引和切片操作,将原列表改变为:
L = [1, 2, 3, 4, 5, 6]
将列表反转,结果如下:
L = [6, 5, 4, 3, 2, 1]
然后删除最后一个元素,结果如下 :
L = [6, 5, 4, 3, 2]
练习:
练习:
写一个程序.让用户输入很多个正整数,当输入负数时结束输入
将用户输入的数字存储于列表中
1. 打印存有数字的列表
2. 求出这些数字中的平均数
3. 求出这个数字中的最大数
如:
请输入: 1
请输入: 2
请输入: 99
请输入: 100
请输入: -1
打印如下 :
列表是: [1, 2, 99, 100]
平均值是: 55.5
最大数是: 100
len(x) 返回序列的长度
max(x) 返回序列的最大值元素
min(x) 返回序列中最小值元素
sum(x) 返回序列中所有元素的和(元素必须是数字类型)
any(x) 真值测试.如果列表中的一个值为真值则返回True
all(x) 真值测试.如果列表中所有的值为真值则返回True
示例:
L = ["Beijing", 1, 123]
print(len(L)) # 3
L = [8, 3, 6, 2]
print(max(L)) # 8
print(min(L)) # 2
print(sum(L)) # 19
文档参见:
python_base_docs_html/list.html
>>> help(list)
练习:
写一个程序,让用户输入很多个正整数,当输入小于零的数时
结束输入
1) 打印这些数中最大的数
2) 打印这些数中第二大的数
3) 删除最小的一个数
浅拷贝
浅拷贝是指在复制过程中,只复制一层变量,不会复制深层
变量绑定的对象的复制过程
如:
L = [3.1, 3.2]
L1 = [1, 2, L]
L2 = L1.copy() # 浅拷贝
print(L1) # [1, 2, [3.1, 3.2]]
print(L2) # [1, 2, [3.1, 3.2]]
L2[2][0] = 3.14
print(L1) # [1, 2, [3.14, 3.2]]
print(L2) # [1, 2, [3.14, 3.2]]
深拷贝 deep copy
如:
import copy # 导入复制模块
L = [3.1, 3.2]
L1 = [1, 2, L]
L2 = copy.deepcopy(L1) # 深拷贝
print(L1) # [1, 2, [3.1, 3.2]]
print(L2) # [1, 2, [3.1, 3.2]]
L2[2][0] = 3.14
print(L1) # [1, 2, [3.1, 3.2]]
print(L2) # [1, 2, [3.14, 3.2]]
1.浅拷贝只复制指向某个对象的引用地址,而不复制对象本身,新旧对象还是共享同一块内存。
2.但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
浅复制只复制一层对象的属性,而深复制则递归复制了所有层级。
import copy as cp
L=[1,[2,3]]
L1=cp.copy(L) #浅拷贝: 只是引用,并不会开辟新的内存空间,
L1与L指向同一片内存空间。L改变,L1也会锁着改变。
L2=cp.deepcopy(L) #深拷贝:会为数据重新开辟一片内存空间,L的变化不会影响L2。
列表与字符串比较:
1. 列表和字符串都是序列,元素之间有先后顺序关系
2. 列表和字符串有相同的操作: + += * *= < > in ...
3. 字符串是不可变化的序列,列表是可变的序列
4. 字符串的每个元素只能存储字符,而列表可以存储任意类型
的元素
5. 列表和字符串都是可迭代对象
字符串的文本解析方法 split 和join
S.split(sep=None) 将字符串使用sep作为分隔符分割s
字符串,返回分割后的字符串列表;当不给定参
数时,用空白字符作为分隔符
S.join(iterable) 用可迭代对象中的字符串生成一个中
间用S进行分隔的字符串
示例:
s = 'Beijing is Capital'
L = s.split(' ') # L = ['Beijing', 'is', 'Capital']
s2 = "##".join(L) # s2 = "Beijing##is##Capital"
练习:
有字符串 "hello"
生成新的字符串:
'h e l l o' 和 'h-e-l-l-o'
s1 = ' '.join('hello')
s2 = '-'.join('hello')
1.列表推导式 list comprehesion
列表推导式是用可迭代对象创建列表的表达式
作用:
创建列表
语法:
[ 表达式 for 变量 in 可迭代对象]
或
[ 表达式 for 变量 in 可迭代对象 if 真值表达式]
示例:
生成一个数值为1~9的平方的列表
L = [x**2 for x in range(1, 10)]
# L = [1, 4, 9, 16 .... 64, 81]
# 生成一个数值1~9的平方的列表(只要其中奇数的平方)
L = [x**2 for x in range(1, 10) if x % 2 == 1]
# L = [1, 9, 25, 49, 81]
# 以上列表推导式可以改写为:
L = []
for x in range(1, 10):
if x % 2 == 1:
L.append(x**2)
2.列表推导式的嵌套语法:
[ 表达式
for 变量1 in 可迭代对象1 if 真值表达式1
for 变量2 in 可迭代对象2 if 真值表达式2
.....]
如:
L = [x + y for x in "ABC" for y in "123"]
# L = ['A1', 'A2', 'A3', 'B1', 'B2', 'B3',
'C1', 'C2', 'C3']
练习:
1. 有一些数存于列表中,如:
L = [1, 3, 2, 1, 6, 4, 2, ..... 98, 82]
1) 将列表中出现的数字存入到另一个列表L2中
要求:
重复出现多次的数字只能在L2中保留一份(去重)
2) 将列表中出现两次的数字存于L3列表中,在L3列表中
只保留一份
2.生成一个列表,求 x 的平方+1的列表,跳过结果能被5整除的
数, (注: 0 <= x <= 100)
3. 把 0 ~ 100 之 间的所有素数存于一个列表中
即: L = [2, 3, 5, 7, 11, ..... 97]
day06回顾:
列表 list
列表的创建方式:
字面值
[], [1,2,3,4]
构造函数:
list() list("ABCD")
推导式:
[x**2+1 for x in range(10)]
列表的运算:
+ += * *=
< <= > >= == !=
in, not in
索引取值 和 切片取值 规则等同于字符串的规则
索引赋值 和 切片赋值
列表[整数表达式] = 表达式
列表[切片] = 可迭代对象
L[1:2] = range(10)
序列相关的函数:
len(x) --> len(可迭代对象)
max(x) --> max(可迭代对象), max(数值1,数值2,...)
min(x)
sum(x) --> sum(可迭代对象)
any(x) --> any(可迭代对象)
all(x) --> all(可迭代对象)
列表常用的方法:
L.append(x) 追加
L.insert(索引, 数据对象)
L.extend(可迭代对象)
L.remove(数据对象)
L.pop([整数索引])
L.clear()
L.count(数据对象)
L.index(数据对象) 返回第一次出现的位置
L.sort(reverse=False) 排序
L.reverse() 反转
字符串解析方法:
S.split(sep=None)
S.join(可迭代对象)
列表推导式:
[x**2 for x in range(10)]
[x**2 for x in range(10) if x > 5]
[x*y+2 for x in range(10) for y in range(20)]
深拷贝 和 浅拷贝
L = [1, 2, 3, [4, 5, 6]]
L2 = L # 不拷贝,把L的引用给L2
L3 = L.copy() # 浅拷贝
import copy
L4 = copy.deepcopy(L) # 深拷贝
元组 tuple
元组是不可变的序列,同list一样,元组是可以存储任意类型
的数据的容器
元组的表式方法:
用小括号() 括起来,单个元素括起来后加逗号(,)区分单个
对象还是元组
创建空元组的字面值:
t = () # 创建一个空元组用t绑定
创建非空元组的字面值
t = 200, # 创建一个只有一个数字200的元组用绑定
t = (20,)
t = (1, 2, 3)
t = 100, 200, 300
创建的元组的错误示例:
t = (20) t绑定整数20,不是元组
x, y, z = (100, 200, 300) # 序列赋值
x, y, z = 100, 200, 300
x, y, z = [100, 200, 300]
x, y, z = "ABC" # 序列赋值,不是元组
x, y = y, x # 交换两个变量的绑定关系
type(x) 函数返回x的类型
元组的构造函数 tuple
tuple() 生成一个空的元组,等同于()
tuple(iterable) 用可迭代对象生成一个新的元组
示例:
t = tuple()
t = tuple("ABC")
t = tuple(range(1, 10, 3))
元组的运算:
+ += * *=
t = (1, 2, 3) + (4, 5, 6) # t=(1,2,3,4,5,6)
t = (1,2,3)
t += (4,5,6) # t = (1,2,3,4,5,6)
t = (1,2) * 3 # t =(1,2,1,2,1,2)
t = (1,2)
t *= 3
比较运算:
< <= > >= == !=
比较规则与列表的比较规则完全相同
in / not in运算符
等同于列表的 in / not in 运算符
索引 和 切片
索引取值和切片取值的规则与列表完全相同
注: 元组不支持 索引赋值和切片赋值
元组的方法
参见文档:
python_base_docs_html/tuple.html
序列相关的函数也能用于元组中
len(x), max(x), min(x),
sum(x), any(x), all(x)
字典 dict
什么是字典
1. 字典是一种可变的容器,可以存储任意类型的数据
2. 字典中的每个数据都是用"键"(key) 进行索引的,而不
像序列(str,list,tuple)可以用整数进行索引
3. 字典中的数据没有先后顺序关系,字典的存储是无序的
4. 字典中的数据以键(key)-值(value)对形式进行存储
5. 字典的键不能重复,且只能用不可变类型作为字典的键
创建字典的字面值方式:
字典的表示方式以{
} 括起来,以冒号(:) 分隔键值对,各键
值对之间用逗号分隔开
创建空字典:
d = {
}
创建非空字典:
d = {
"姓名": "tarena", "年龄": 15}
d = {
"one": 1, "two": 2}
d = {
1: "One", 2: "二", 3: [1,2,3]}
d = {
"a": list(range(10))}
d = {
"a": {
"b": 100, "c":[1, 2, 3]}}
创建字典的构造函数 dict:
dict() # 生成一个空的字典 等同于 {}
dict(iterable) 用可迭代对象创建一个列表
dict(**kwargs) 关键字传参形式生成一个字典
示例:
d = dict()
L = [ (1, 2), [3, 4], "AB" ]
d = dict(L) # {1: 2, 3: 4, 'A': 'B'}
d = dict(name="tarena", age=15)
# d = {'age': 15, 'name': 'tarena'}
字典的键必须为不可变类型的值
可变的类型有四种:
list(列表), dict(字典), set(集合),
bytearray(字节数组)
(除上述四种其它为不可变类型)
字典基本操作
1.字典的键索引
语法:
字典[键]
作用:
用键获取字典的键对应的值
示例:
d = {
'name': 'tarena', 'age': 16}
print(d['name'], "的年龄是", d['age'])
2.添加和修改字典的元素
语法:
字典[键] = 值
说明:
键不存在时,创建键,并让键绑定对应的值
键存在,修改键绑定的值
示例:
d = {
}
d['name'] = "小张" # 添加一个键值对
d['年龄'] = 20 # 添加一个键值对
d['年龄'] += 1 # 修改'年龄' 这个键对应的值
练习:
写一个程序,让用户分两次输入一个人的信息:
信息包含: 姓名 和 电话号码
让用户多个人的信息,当输入姓名为空时结束输入
把用户输入的数据存于字典中
姓名作为键, 电话号码作为值
最后打印存储数据的字典
如:
请输入姓名: 小张
请输入电话: 13888888888
请输入姓名: 小李
请输入电话: 13999999999
请输入姓名: <回车>
打印:
{
"小张": 13888888888, "小李": 13999999999}
3.删除字典元素
del 语句
语法:
del 字典[键]
示例:
d = dict(name="小张", age=20)
del d['age']
print(d) # {'name': '小张'}
4.字典的键判断 in , not in运算符
可以用 in 运算符判断一个键是否存在于字典中,如果存在
则返回True, 否则返回False
not in 返回值与 in 相反
例如:
d = {
'name' : 'tarena', 'age': 15}
'name' in d # True
15 in d # False
'age' not in d # False
练习:
写程序,实现以下需求:
1. 将如下数据形成一个字典 seasons
键 值
1 ====> '春季有1,2,3月'
2 ====> '夏季有4,5,6月'
3 ====> '秋季有7,8,9月'
4 ====> '冬季有10,11,12月'
2. 让用户输入一个整数代表这个季度,打印这个季度对应的
信息,如果用户输入的信息不存在于字典内,则提示用户
'信息不存在'
字典的迭代访问
字典是可迭代对象,字典只能对键进行迭代访问
示例:
d = {
0:'零', 5:'伍', 1:'壹', 2:'贰'}
for n in d:
print(n) # 0, 1, 2, 5
可以用于字典的函数:
len(x) 返回字典的键值对的个数
max(x) 返回字典的键的最大值
min(x) 返回字典的键的最小值
sum(x) 返回字典的所有键的和
any(x) 真值测试,只对键进行测试,只要有一个键为真值
结果就为True
all(x) 真值测试,所有键的真值结果才为True
示例:
d = {
0:'零', 5:'伍', 1:'壹', 2:'贰'}
len(x)
...
字典的方法
文档参见:
python_base_docs_html/dict.html
示例:
d = {
0:'零', 5:'伍', 1:'壹', 2:'贰'}
for t in d.items():
print(t) # (0, '零'), (1, '壹'), (2, '贰'), (5, '伍')
for k, v in d.items():
print("键是", k, '值是', v)
练习:
输入一段字符串,打印出这个字符串中出现过的字符及出现过
的次数
如:
输入: abcdabcaba
打印如下:
a: 4次
b: 3次
d: 1次
c: 2次
注: 不要求打印顺序
字典推导式
字典推导式是用可迭代对象来创建字典的表达式
语法:
{
键表达式: 值表达式 for 变量 in 可迭代对象
[if 真值表达式]}
注: []的内容代表可省略
示例:
生成一个字典: 键为数字0~9, 值为键的平方
如生成 {
0: 0, 1:1, 2:4, 3: 9, ... 9:81}
d = {
x: x**2 for x in range(10)}
print(d)
字典推导式的嵌套
语法同列表推导式嵌套
练习:
已知有如下字符串的列表:
L = ['Tarena', 'XiaoZhang', 'xiaowang']
生成如下字典:
d = {
'Tarena':6, 'XiaoZhang':9,
'xiaowang':8}
练习:
Nos = [1001, 1002, 1005, 1006]
names = ['Tom', 'Jerry', 'Spike', 'Tyke']
试生成如下字典:
d = {
1001: 'Tom', 1002: 'Jerry',
1005: 'Spike', 1006: 'Tyke'}
答案:
d = {
Nos[i]: names[i] for i in range(4)}
字典 VS 列表
1. 都是可变的容器
2. 索引方式不同,列表用整数索引,字典用键索引
3. 列表的存储是有序的,字典的存储是无序的
4. 字典的插入,删除,修改的速度可能会快于列表(重要)
问题:
L = [1, 3, 5, 8, 10]
for x in L:
L.remove(x)
print(L) # [3, 8]
练习:
1. 生成前40个斐波那契数 (Fibonacci 数列)
1 1 2 3 5 8 13 21 ....
要求: 将这些数存入在列表中
最后打印出这些数
2. 有一只小猴子,摘了很多桃,
第一天吃了全部的桃子的一半,感觉不饱又吃了一个
第二天吃了剩下的一半,感觉不饱又吃了一个
以此类推...
到第10天,发现只剩下一个了
问: 第一天摘了多少桃子?
3. 打印九九乘法表:
1x1=1
1x2=2 2x2=4
1x3=3 2x3=6 3x3=9
....
......................9x9=81
4. 任意输入很多个学生的姓名,年龄,成绩,每个学生的信息
存入到字典中,然入再放在列表内.
每个学生的信息需要手动输入:
如:
请输入姓名: tarena
请输入年龄: 15
请输入成绩: 99
请输入姓名: china
请输入年龄: 70
请输入成绩: 98
请输入姓名: <回车> 结束输入
内部存储格式如下:
infos = [{
'name':'tarena', 'age':15, 'score':99},
{
'name':'china', 'age':70, 'score':98}]
1. 打印以上的列表
2. 按如下表格打印学生信息
+---------------+-----------+----------+
| 姓名 | 年龄 | 成绩 |
+---------------+-----------+----------+
| tarena | 15 | 99 |
| china | 70 | 98 |
+---------------+-----------+----------+
day07回顾
两个容器类
元组 tuple
字典 dict
元组
可以理解成不可变的列表(序列容器)
字面值的创建方法
() 20, (20,) 100,200,300 (1,2,3)
构造函数的创建方法:
tuple() , tuple(可迭代对象)
元组的运算:
+ += * *=
< <= > >= == !=
in / not in 运算符
索引/切片 取值(不支持赋值)
字典 dict
可变的, 可以存储任意类型的,无序的容器
键-值对(key-value)
字典的键不可改变且不可重复
创建字面值的创建方式
{
} {
1:"一"} {
1:"一", 2:'二'}
推导式方式:
{
键表达式 : 值表达式 for 变量 in 可迭代对象 if...}
构造函数方式:
dict() dict(可迭代对象) dict(关键字传参)
dict(iterable) dict(**kwargs)
运算:
变量 = 字典[键] # 取值
字典[键] = 表达式 # 添加/修改键所对应的值
del 语句 用来删除字典的键值对
del 字典[键]
in , not in 运算符
字典中的方法
D.clear()
D.pop(key) 移除
D.get()
D.copy
D.keys()
D.values()
D.items()
...
集合 set
集合是可变的容器
集合内的数据对象都是唯一的(不能重复多次的)
集合是无序的存储结构,集合中的数据没有先后关系
集合内的元素必须是不可变对象
集合是可迭代的(可以用for语句遍历)
集合是相当于只有键没有值的字典(键则是集合的数据)
创建集合的构造函数
set() 创建一个空的集合对象(不能用{
}来创建空集合)
set(iterable) 用可迭代对象来创建新的集合对象
示例:
s = set() # s绑定空集合set()
s = set(range(1, 5)) # s = {1, 2, 3, 4}
s = set("hello") # s = {'e', 'o', 'h', 'l'}
注:
非空集合用 {
} 括起来,内部的各个元素用逗号(,)分隔开
字面值方式来创建非空集合
s = {
1, 2, 3, 4}
s = set("ABCCBA")
s = set({
1:"一", 3:"三", 8:"八"})
s = set([1, 3.14, "ABC"])
s = {
True, None, "ABC", (1, 2, 3)}
s = {
True, None, "ABC", [1, 2, 3]} # 出错
集合的运算:
交集 & 并集| 补集- 对称补集^ 子集< 超集>
1. & 生成两个集合的交集
s1 = {
1, 2, 3}
s2 = {
2, 3, 4}
s3 = s1 & s2 # s3 = {2, 3}
2. | 生成两个集合的并集
s1 = {
1, 2, 3}
s2 = {
2, 3, 4}
s3 = s1 | s2 # s3 = {1, 2, 3, 4}
3. - 生成两个集合的补集
s1 = {
1, 2, 3}
s2 = {
2, 3, 4}
# 生成属性s1但不属于s2的所有元素的集合
s3 = s1 - s2 # s3 = {1}
s3 = s2 - s1 # s3 = {4}
4. ^ 生成两个集合的对称补集
s1 = {
1, 2, 3}
s2 = {
2, 3, 4}
s3 = s1 ^ s2 # {1, 4}
5. < 判断一个集合是另一个集合的子集
> 判断一个集合是另一个集合的超集
s1 = {
1, 2, 3}
s2 = {
2, 3}
s2 < s1 # True
s1 > s2 # True
s3 = {
3, 4, 5}
s1 > s3 # False
s1 < s3 # False
s1 == s3 # False
6. == != 判断集合相同或不同
{
1, 2, 3} != {
3, 2, 1} # False
7. >= <=
8. in , not in 运算符
等同于列表的in 运算符
s1 = {
1, 2, 3}
3 in s1 # True
集合和字典的优点:
in / not in 运算符的运算速度比较快
能用于集合的内建(built-in)函数:
len(x)
max(x)
min(x)
sum(x)
any(x)
all(x)
练习:
经理有: 曹操, 刘备, 孙权
技术员有: 曹操,孙权,张飞,关羽
用集合求:
1. 即是经理也是技术员的有谁?
2. 是经理,但不是技术员的人都有谁?
3. 是技术员,但不是经理的人都有谁?
4. 张飞是经理吗?
5. 身兼一职的人都有谁?
6. 经理和技术人员共有几个人?
python3中常用的集合方法:
文档参见:
python_base_docs_html/set.html
集合是可迭代对象
集合推导式
集合推导式是用可迭代对象创建集合的表达式
语法:
{
表达式 for 变量 in 可迭代对象 [if 真值表达式]}
注:[] 代表其中的内容可省略
示例:
L = [1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 7]
s = {
x ** 2 for x in L}
集合推导式的嵌套等同于列表推导式的嵌套
固定集合 frozenset
固定集合是不可变的,无序的,含有唯一元素的集合
作用:
固定集合可以作为字典的键,还可以作为集合的值
固定集合的构造函数 frozenset
frozenset() 创建一个空的固定集合
frozenset(iterable) 用可迭代对象创建一个新的固定
集合
示例:
fz = frozenset()
fz = frozenset("hello")
fz = frozenset([1,2,3,4,3,4,5])
固定集合的运算:
交集 & 并集 | 补集 - 对称补集 ^
in / not 运算符
< <= > >= == !=
(以上运算符用法等同于set中的用法)
固定集合的方法,相当于集合的全部方法去掉修改集合的方法
阶段性总结:
数据类型
不可变的数据类型
bool, int, float, complex, str, tuple
frozenset, bytes(字节串,后面再学)
可变的数据类型
list, dict, set, bytearray(字节数组,以后再讲)
值:
None, False, True
运算符:
+ - * / // % **
> >= < <= == !=
in / not in
is / is not
not and or
& | ^
+(正号) -(负号)
[] # 索引和切片
表达式:
1
True
1 + 2 * 3
print("hello") # 函数调用
L.pop(2) # 方法调用也是表达式
sum([1, 2, 5, 10])
条件表达式: x if x > y else y
全部的推导式: 列表,字典,集合推导式(三种)
语句:
表达式语句(表达式单独在一行可以形成表达式语句)
print("hello")
"这是一段文字"
赋值语句:
a = 100
a = b = c = 200
x, y, z = 1, 2, 3
del 语句
if 语句
while 语句
for 语句
break 语句
continue 语句
pass 语句
内建函数:
len(x)
max(x)
min(x)
sum(x)
any(x)
all(x)
--------- 构造函数 -------
bool(x)
int(x)
float(x)
complex(x)
str(x)
list(x)
tuple(x)
dict(x)
set(x)
frozenset(x)
-------------------
abs(x)
round(x, y)
pow(x, y, z=None)
--------------------
bin(x)
oct(x)
hex(x)
chr(x)
ord(x)
--------------------
range(start, stop, step)
----基本输入输出函数--
input(x)
print(....)
--------------------
id(x) 返回内存地址
type(x) 返回类型
1.函数 function
什么是函数
函数是可以重复执行的语句块,可以重复调用并执行
函数是面向过程编程的最小单位
作用:
用于封装语句块,提高代码的重用性
定义用户级别的函数
提高代码的可读性和易维护性
2.def 语句:
语法:
def 函数名(形参列表):
语句块
作用:
创建一个函数,将语句块打包,用函数名绑定,用来调用
说明:
1. 函数名的命名规则与变量名的规则相同(必须为标识符)
2. 函数名是一个变量,它用来绑定函数
3. 函数有自己的名字空间,在函数外部不可以访问函数内
部的变量,在函数内部可以访问函数外部的变量,但不能对
外部的变量赋值
4. 语句部分不能为空.如果为空需要填允pass语句
5. 函数如果不需要传入参数,形参列表可以为空
3.函数调用:
语法:
函数名(实际调用传递参数)
说明:
函数调用是一个表达式
如果函数内部没有return语句,函数执行完毕后返回None
对象的引用
示例见:
def.py
mymax.py
练习:
1. 写一个函数myadd, 此函数中的参数列表里有两个参
数x, y此函数功能是打印 x + y 的和
def myadd(...):
...
myadd(100, 200) # 300
myadd("ABC", "123") # ABC123
2. 写一个函数print_even,传入一个参数n代表终止整数
打印 2 4 6 8 .... n 之间的所有偶数(包含n)
函数定义如下:
def print_even(n):
.... # 此处自己实现
print_even(8)
# 打印:
2
4
6
8
return 语句
语法:
return [表达式]
注: [] 代表其中的内容可省略
作用:
用于函数中,结束当前函数的执行,返回到调用该函数的
地方,同时返回一个对象的引用关系
说明:
1. return 语句后跟的表达式可以省略,省略后相当
于return None
2. 函数内部没有return语句,则函数执行完最后一条
语句后返回None(相当于在最后加了一条return None
语句)
示例见:
return.py
练习:
1. 写一个函数 mymax, 实现返回三个数的最大值:
如:
def mymax(a, b, c):
...
print(mymax(100, 200, 300)) # 300
print(mymax("ABC", 'abc', '123')) # abc
2. 写一个函数myadd()实现给出两个数,返回这两个数的和
如:
def myadd(x, y):
....
a = int(input("请输入第一个数: "))
b = int(input("请输入第二个数: "))
print("您输入的两个数的和是:", myadd(x, y))
3. 写一个函数input_number
def input_number():
.... # 此处自己实现
此函数用来获取用户循环输入的整数,当输入负数时结束输入
将用户输入的数字以列表的形式返回,再用内建函数max,min,
sum 求出用户输入的数的最大值,最小值及和,如:
L = input_number()
print("最大数是:", max(L))
print("最小数是:", min(L))
print("和是:", sum(L))
练习:
1. 创建两个函数
def sum3(a, b, c):
# 用于返回三个数的和
....
def pow3(x):
# 用于返回x的三次方
...
用以上两个函数计算:
1. 计算1的立方 + 2的立方 + 3的立方 的和
2. 计算1+2+3的和的立方
即: 1**3 + 2**3 + 3 ** 3 和 (1+2+3)**3
2. 改写之前的学生信息管理程序,封装为两个函数:
def input_student():
# 此函数用于返回所有用户输入的学生信息的列表
...
def output_studentn(L):
# 此函数以表格形式打印学生信息
...
以下是调用(功能和打印效果与之前相同):
infos = input_student()
print(infos)
output_studentn(infos)
3. 编写函数,计算下列多项式的和:
Sn = 1/(1*2) + 1/(2*3) + 1/(3*4) + ...
... + 1/(n*(n+1))
def Sn(n):
...
print(Sn(3)) # 0.75
print(Sn(1000)) # ???
day08回顾
两个容器类
集合 set, 固定集合frozenset
集合的创建
set()
set(可迭代对象)
{
1, 2, 3, 4}
集合推导式: {
表达式 for 变量列表 in 可迭代对象 if ...}
固定集合的创建
frozenset()
frozenset(可迭代对象)
集合的特点:
无序, 不可重复,只能存放不可变对象
集合的运算:
& | - ^ < > <= >= == !=
in, not in, is, is not(判断的是id)
集合方法:
S.add(x) 添加:
S.remove(x)
S.discard(x)
S.clear()
S.pop()
两条语句
def 语句
创建一个函数,用函数变量来绑定函数,目的是以后可
以重复调用
return 语句
语法:
return 表达式
函数的传参(把数据给函数)
函数的形参(接收函数调用传过来的数据)
python 函数的参数传递
传递方式:
1. 位置传参
1.1 序列传参
2. 关键字传参
2.1 字典关键字传参
位置传参:
实际参数(实参) 的对应关系与形式参数(形参)的对应关系是
按位置来依次对应的.
示例见:
position_give_args.py
说明:
实参和形参通过位置进行传递和匹配
实参的个数必须与形参的个数相同
序列传参:
序列传参是指在函数调用过程中,用*(星号) 将序列拆解后
按位置进行传递的传参方式
说明:
序列传参时,序列拆解的位置将与形参一一对应
示例见:
sequence_give_args.py
关键字传参:
关键字传参是指传参时,按着形参名称给形参赋值
实参和形参按名称进行匹配
说明:
可以不按位置进行匹配
示例见:
keywords_give_args.py
字典关键字传参:
是指实参为字典,将字典用** 拆解后进行关键字传参的传
递方式
说明:
字典的键名和形参名必须一致
字典的键名必须为符合标识符命名规则的字符串
字典的键名要在形参中存在
示例见:
dict_keyword_give_args.py
函数的综合传参:
1. 函数的传参方式在能确定形参能唯一匹配到相应实参的情
况下可以任意组合
2. 函数的位置传参要先于关键字传参
示例:
def myfun(a, b, c):
pass
myfun(100, *[200, 300])
myfun(100, *"BC")
myfun(*"AB", 300)
myfun(*[100], 200, *[300])
myfun(100, c=300,b=200)
myfun(a=100, 200, c=300) # 错误的
myfun(100, **{
'c':300, 'b':200})
myfun(100, **{
'c':300}, b=200)
myfun(100, b=200, **{
'c':300})
练习:
写一个函数minmax,传入三个参数,返回这三个参数中的最大值和最
小值元素,结果要求,形成元组最小值在前,最大值在后返回
给调用者
如:
def minmax(a, b, c):
....
调用结果如下:
t = minmax(300, 100, 200)
print(t) # (100, 300)
函数的缺省参数
语法:
def 函数名(形参名1=默认实参1, 形参名2=默认实参2,
形参名3=默认实参3, .....)
作用:
让函数的调用者少传递参数来调用函数
示例见:
default_args.py
说明:
1. 缺省参数必须自右至左依次存在,如果一个参数有缺省
参数, 则其右侧的所有参数都必须有缺省参数
2. 缺省参数可以有0个,1个或多个,甚至全部都有缺省参数
如:
def fn(a, b=10, c): # 错误
pass
def fn(a=0, b=None, c=False): # 是这对的
pass
练习:
写一个函数,myadd,此函数可以传入二个,三个或四个实参
此函数功能是计算所有实参的和
如:
def myadd(...):
....
print(myadd(10, 20)) # 30
print(myadd(100, 200, 300)) # 600
print(myadd(1, 2, 3, 4)) # 10
函数的可变实参和不可变实参的传递
示例见:
variable_args.py
variable_args2.py
说明:
当一个可变对象通过函数实参传入函数内时,在函数内
可以通过局部变量来操作可变对象(列表,字典,集合...)
面试题:
试运行以下程序的结果是什么, 为什么?
L = [1, 2]
def fn(a, lst=[]):
lst.append(a)
print(lst)
fn(3, L) # [1, 2, 3]
fn(4, L) # [1, 2, 3, 4]
fn(5) # [5]
fn(6) # [5, 6]
fn(7) # [5, 6, 7]
函数形参的定义方式
位置形参
星号元组形参
命名关键字形参
双星号字典形参
位置形参:
语法:
def 函数名(形参变量1, 形参变量2, ....):
语句块
星号元组形参
语法:
def 函数名(*元组形参名):
语句块
作用:
收集多余的位置传参
说明:
元组形参名一般命名为'args'
*元组形参一个函数只能有一个
示例见:
star_tuple_args.py
练习:
写一个程序,mysum 可以传入任意个实参的参数,
此函数的功能是返回所有实参的和
def mysum(*args):
....
print(mysum(1,2,3,4)) # 10
print(mysum(1,2,3)) # 6
命名关键字形参
语法
def 函数名(*,命名关键字形参1, 命名关键字形参2,..):
语句块
或
def 函数名(*args,命名关键字形参1, 命名关键字形参2,..):
语句块
作用:
强制所有的命名关键字形参都必须用关键字传参或字典关
键字传参
示例见:
named_keywords_args.py
思考:
print() 函数的形参列表是如何定义的
练习:
已知内建函数 max 的绑助文档为:
max(...)
max(iterable)---> value
max(args1, arg2, *args) --> value
仿造max函数,写一个与max功能完全一样的mymax函数
(要求: 不允许调用内键的max函数)
如:
def mymax(...):
...
print(mymax([6, 8, 3, 5])) # 8
print(mymax(100, 200)) # 200
print(mymax(1, 3, 5, 9, 7)) # 9
print(mymax()) # 报错
双星号字典形参
语法:
def 函数名(**字典形参名):
语句块
作用:
收集多余的关键字传参
说明:
字典形参名一般命名为'kwargs'
一个函数内字典形参最多只有一个
示例见:
dict_kwargs.py
1.函数的形参说明:
位置形参,缺省参数,星号元组形参,双星号字典形参可以混
合使用
2.函数形参自左至右的定义顺序为:
位置形参
星号元组形参
命名关键字形参
双星号字典形参
示例:
def fn(a, b, *args, c, **kwargs):
pass
fn(1, 2, 3, 4, c=30, d=40, e=50)
3.函数的不定长参数:
有两种: 星号元组形参,双星号字典形参
用不定长参数可以接收任意的传参
如:
def fn(*args, **kwargs):
print(args, kwargs)
全局变量和局部变量
1.局部变量
1. 定义在函数内部的变量称为局部变量(函数的形参也是
局部变量)
2. 局部变量只能在函数内部使用
3. 局部变量在函数调用时才能创建,在函数调用之后会
自动销毁
2.全局变量
1. 定义在函数外部,模块内部的变量称为全局变量
2. 全局变量所有的函数都可以直接访问(但函数内部不能将
其直接赋值)
说明:
函数内部赋值语句不会对全局变量造成影响
练习:
1. 写一个函数 get_chinese_char_count(s),此函数的
功能是给定一个字符串,返回这个字符串中中文字符的个数
如:
def get_chinese_char_count(s):
...
s = input("请输入中文英混合的字符串:")
print('您输入的中文个数是',
get_chinese_char_count(s))
注: 中文字符的编码在 0x4E00-0x9FA5 之间
2. 写一个函数isprime(x) 判断x是否为素数.如果为素数
返回True,否则返回False
如:
print(isprime(3)) # True
print(isprime(4)) # False
3. 写一个函数prime_m2n(m, n) 返回从m开始,到n结束
范围内的全部素数的列表,并打印对应的列表 (不包含n)
如:
def prime_m2n(m, n):
...
L = prime_m2n(10, 20)
print(L) # [11, 13, 17, 19]
4. 写一个函数primes(n) 返回指定范围内的全部素数
(不包含n)的列表,打印印这些素数的列表, 如:
def primes(n):
...
L = primes(10)
print(L) # [2, 3, 5, 7]
1) 打印 100以内的素数
2) 打印 200以内全部素数的和
5. 写一个myrange函数,参数可以传1~3个,实际含义
与range函数规则相同,此函数返回符合range函数规则
的列表
如:
L = myrange(4)
print(L) # [0, 1, 2, 3]
L = myrange(4, 6)
print(L) # [4, 5]
L = myrange(1, 10, 3)
print(L) # [1, 4, 7]
day09回顾
传参(实参), 把数据给函数(给)
形参,从函数调用的地方接收实参(拿)
传参方式:
位置传参
序列传参 函数名(*序列)
关键字传参
字典关键字传参 函数名(**字典)
传参时,可变对象和不可变对象的区别
不可变对象不会在函数内部被修改
函数的形参:
缺省参数:
def f1(a=1, b=2):
pass
f1()
f1(100)
f1(100, 200)
函数的形参的定义方式
位置形参
*元组形参
命名关键字形参
** 字典形参
全局变量和局部变量
globals() 函数 和 locals 函数
globals() 返回当前全局作用域内变量的字典
locals() 返回当前局部作用域内变量的字典
示例见:
globals_local.py
函数变量
函数名是变量,它在创建函数时绑定一个函数
示例见:
function_variable.py
function_variable2.py
一个函数可以作用另一个函数的实参传递
可以把一个函数给另一个函数,另一个函数的形参变量将
绑定实参函数
示例见:
func_give_func.py
func_give_func2.py
#看懂如下代码,判断结果
def myinput(fn):
L = [1, 3, 9, 5, 7]
return fn(L)
print(myinput(max)) # 9
print(myinput(min)) # 1
print(myinput(sum)) # 25
#函数可以作用另一个函数的返回值
示例见:
return_function.py
练习:
写一个计算公式的解释执行器
已知有如下函数:
def myadd(x, y):
return x + y
def mysub(x, y):
return x - y
def mymul(x, y):
return x * y
...
有一个返回函数的函数
def get_func(s):
'''此函数功能是,传入一个字符串用s绑定,根据s的
值返回上面相应的函数, 如s == '+'或 s=='加' 返回
myadd
'''
.... 自己实现此函数
在主函数中程序如下:
def main():
while True:
s = input("请输入计算公式: ") # 1 加 2
L = s.split() # L = ['1', '加', '2']
a = int(L[0])
b = int(L[2])
fn = get_func(L[1])
print("结果是:", fn(a, b)) # 结果是:3
main() # 调用主函数
函数的嵌套定义
函数嵌套定义是指一个函数里用def语句来创建其它函数的情况
示例见:
function_embed_define.py
1.python的作用域
作用域也叫名字空间,是访问变量时查找变量的名范围空间
2.python中的四个作用域 LEGB 见下表:
示例见:namespace.py
作用域 | 英文解释 | 英文缩写 |
---|---|---|
局部作用域 | Local(function) | L |
外部嵌套函数作用域 | Enclosing Fucntion local | E |
函数定义所在模块(文件)的作用域 | Global(module) | G |
Python内建模块的作用域 | Builtin(python) |
变量名的查找规则
L ---> E ---> G ----> B
注:
在默认的情况下,变量名赋值会创建或改变当前作用域
内变量的绑定关系
global 语句
作用:
1. 告诉解释执行器,global语句声明的一个或多个变量,这
些变量的作用域为模块级的作用域,也称作全局变量
2. 全局声明(global) 将赋值语句的变量映射到模块文
件内部的作用域
语法:
global 变量名1, 变量名2, ....
示例见:
global.py
说明:
1. 全局变量如果要在函数内部被赋值,则必须经过全局声明
(否则会被认为是局部变量)
2. 全局变量在函数内部不经过声明就可以直接访问(取值)
3. 不能先创建局部变量,再用global声明为全局变量,此
种做法不符合规则
4. global变量列表里的变量名不能出现在函数的形参列
表里
nonlocal 语句
作用:
告诉解释器, nonlocal声明的变量不是局部变量,也不是
全局变量,而是外部嵌套函数内的变量
语法:
nonlocal 变量名1, 变量名2, ....
示例见:
nonlocal.py
说明:
1. nonlocal 语句只能在被嵌套函数内部进行使用
2. 对nonlocal变量进行赋值将对外部嵌套函数作用域
内的变量进行操作
3. 当有两层或两层以上函数嵌套时,访问nonlocal变量
只对最近的一层变量进行操作
4. nonlocal 语句的变量列表里的变量名不能出现在此
函数的形参列表中
练习:
用全局变量记录一个函数hello 被调用的次数
部分代码如下:
count = 0
def hello(name):
print("你好", name)
... # 此处自己实现
hello("小张")
hello("小李)
print("hello函数共被调用", count, "次") # 2
def 语句的作用是创建函数
lambda 表达式(又称匿名函数)
作用:
创建一个匿名函数对象
同def 类似,但不提供函数名
语法:
lambda [函数形参列表]: 表达式
示例见:
lambda.py
说明:
1. lambda 表达式创建的函数只能包含一条表达式
2. lambda 比函数简单,且可以随时创建和销毁,有利于
降低程序的偶合度
练习:
1. 写一个lambda表达式
fx = lambda n: .....
此表达式创建的函数判断n这个数的平方+1 能否被5整除,
如果能整除则返回True,否则返回False
print(fx(3)) # True
print(fx(4)) # False
2. 写一个lambda 表达式来创建函数,此函数返回两个参
数的最大值
def mymax(x, y):
....
mymax = lambda .....
print(mymax(100, 200)) # 200
3. 看懂下面的程序在做什么?结果是什么 ?
def fx(f, x, y):
print(f(x, y))
fx((lambda a, b: a + b), 100, 200)
fx((lambda x, y: x**y), 3, 4)
eval函数和exec() 函数
eval(source, global=None, local=None), 把一个
字符串source 当成一个表达式来执行,返回表达式执
行后的结果
exec(source, global=None, local=None) 把一个
字符串source当成程序来执行
示例见:
eval.py
exec.py
eval2.py
练习:
1. 给出一个数n,写一个函数mysum来计算
1 + 2 + 3 + .... + n 的和
要求用函数来做
如:
print(mysum(100)) # 5050
2. 给出一个数n,写一个函数myfac来计算n!(n的阶乘)
n! = 1 * 2 * 3 * ... * n
print(myfac(5)) # 120
3. 给出一个数n,写一个函数计算:
1 + 2**2 + 3**3 + .... + n**n的和
4. 实现带界面的学生信息管理程序
界面如下:
+----------------------+
| 1) 添加学生信息 |
| 2) 查看学生信息 |
| 3) 删除学生信息 |
| 4) 修改学生成绩 |
| q) 退出 |
+----------------------+
请选择:1
请输入学生姓名: xiaozhang
请输入学生年龄: 20
要求每个功能写一个函数与之相对应(复用之前的学生信息
管理程序)
day10回顾
局部变量 全局变量
locals() globals()
def fa(a, b):
pass
一个函数可以作为参数传入另一个函数
def fx(fn):
pass
fx(max) # 传入一个函数
函数可以作为另一个函数的返回值
def fx():
return max
m = fx() # 此函数调用返回一个max函数
def fy():
def hello():
print("hello")
return hello
h = fy()
h() # 此
函数嵌套定义
python 四个作用域:
局部作用域
外部嵌套函数作用域
全局作用域
内建模块的作用域
global 语句
nonlocal 语句
def 语句创建函数
lambda 表达式
myadd = lambda x, y: x + y
eval(s) 函数
... 表达式 ...
exec(s) 函数
... 语句(程序) ...
1.函数式编程
函数式编程是指用一系列函数解决问题
好处:
1. 用每一个函数完成细小的功能,一系列函数的任意组合可以完成大问题
2. 函数仅接受输入并产生输入,不包含任何能影响输出的内部状态
2.函数的可重入性
如果一个函数的输入参数一定,则返回结果必须一定的函数称为可重入函数
示例:
# 可重入函数,传入参数一定.结果必然一定
def myadd(x, y):
return x + y
# 不可重入函数:
y = 200
def myadd2(x):
return x + y
print(myadd2(10)) # 210
y = 300
print(myadd2(10)) # 310
3.函数式编程的要求:
def 创建的函数最好不要访问局部作用域以外的变量,这样可以保证返回结果的唯一性(可重入性)
高阶函数 High Order Function
什么是高阶函数:
满足下列条件之一的即为高阶函数
1. 函数接受一个或多个函数作为参数传入
2. 函数返回一个函数
python内建的高阶函数:
map, filter, sorted
详见:
python_base_docs_html/内建函数(builtins).html
map函数:
格式:
map(func, *iterables)
示例见:
map.py
练习:
1. 用map函数求:
1**3 + 2**3 + 3 ** 3 + .... 9**3 的和
2. 用map函数求:
1**4 + 2**4 + 3 ** 4 + .... 20**4 的和
提示: sum(map(.....))
filter 函数:
filter(function, iterable)
filter示例见:
filter.py
练习:
1. 将 1 ~ 20 的偶数用filter生成可迭代对象后将可迭代对象生成的数放入到列表L中
2. 写一个函数is_prime(x) 判断x是否是素数
用filter函数打印出: 20 ~ 30之间的全部素数
sorted 函数:
作用:
将原可迭代对象的数据进行排序,生成排序后的列表
格式:
sorted(iterable, key=None, reverse=False)
说明:
iterable 可迭代对象
key 函数是用来提供一个值,这个值将做为排序的依据
reverse 标志用来设置是否降序排序
示例见:
sorted.py
练习:
names = ['Tom', 'Jerry', 'Spike', 'Tyke']
排序的依据为字符串的反序:
'moT' yrreJ ekipS ekyT
结果:
['Spike', 'Tyke', 'Tom', 'Jerry']
1.递归函数 recursion: 函数直接或间接的调用自身
递归示例:
# 函数直接调用自己
def f():
f() # 调用自己
f()
# 函数间接的调用自己
def fa():
fb()
def fb():
fa()
fa()
2.递归说明:
递归一定要控制递归的层数,当符合一定条件时要终止递归
几乎所有的递归都能用while循环来代替
3.递归的优缺点:
优点:
递归把问题简单化,让思路更为清晰,代码更简洁
缺点:
递归因系统环境影响大,当递归深度太大时,可能会得到不可预知的结果
4.递归的两个阶段
递推阶段: 从原问题出发,按递归公式递推从末知到已经,最终达到递归的终止条件
回归阶段: 按递归终止条件求出结果,逆向逐步代入递归公式.回归到原问题求解
示例见: recursion.py
recursion_fac.py
练习:
写函数 mysum(n)用递归方式实现求和
def mysum(n):
# 用递归方式求和
...
print(mysum(100)) # 5050
思考题:
已知五位朋友在一起
第五位朋友比第四位朋友大2岁
第四位朋友比第三位朋友大2岁
第三位朋友比第二位朋友大2岁
第二位朋友比第一位朋友大2岁
第一位朋友说它10岁
闭包 closure
1.什么是闭包:
闭包是指引用了此函数外部的变量的函数
说明:
在本质上,闭包是将内部嵌套函数和函数外部的执行环境绑定在一起的对象
2.闭包必须满足三个条件:
1. 必须有一个内嵌函数
2. 内嵌函数必须引用外部函数中的变量
3. 外部函数返回值必须是内嵌函数
示例见:
closure.py
# 闭包的应用见:
closure2.py
练习:
1. 已知五位朋友在一起
第五位朋友比第四位朋友大2岁
第四位朋友比第三位朋友大2岁
第三位朋友比第二位朋友大2岁
第二位朋友比第一位朋友大2岁
第一位朋友说它10岁
写程序打印出第五位朋友 和第三位朋友 的年龄
2. 已知有列表:
L = [[3, 5, 8], 10, [[13, 14], 15, 18], 20]
1) 写一个函数print_list(lst) 打印出所有元素
print(L) # 打印 3 5 8 10 13 14 ....
2) 写一个函数sum_list(lst) 返回这个列表中所有元素的和
print(sum_list(L)) # 86
注:
type(x) 可以返回一个变量的类型
如:
>>> type(20) is int # True
>>> type([1, 2, 3]) is list # True
3. 改写之前的学生信息管理程序
要求添加四个功能:
| 5) 按学生成绩高-低显示学生信息 |
| 6) 按学生成绩低-高显示学生信息 |
| 7) 按学生年龄高-低显示学生信息 |
| 8) 按学生年龄低-高显示学生信息 |
day11回顾
高阶函数
map, filter, sorted
递归 recursion
闭包 closure
1.装饰器 decorators(专业提高篇)
装饰器是一个函数,主要作用是用来包装另一个函数或类(后面才讲)
装饰的目的是在不改变原函数名(或类名) 的情况下,改变被包装对象的行为
2.函数装饰器
函数装饰器指装饰器传入的是一个函数,返回的也是一个函数
语法:
def 装饰器函数名(参数):
语句块
return 函数对象
@装饰器函数名<换行>
def 函数名(形参列表):
语句块
示例见:
mydeco1.py
mydeco2.py
mydeco3.py
mydeco4.py
函数的文档字符串
函数内第一次未被赋值给任何变量的字符串是此函数的文档字符串
语法:
def 函数名(参数列表):
'函数文档字符串'
函数语句块
示例:
def myfun(name, x):
'''这是函数的文档字符串
name 表示人名
x 表示钱数
'''
pass
>>> help(myfun)
说明:
1. 文档字符串通常用来说明本函数的功能和使用方法
2. 在交互模式下输入: help(函数名) 可以查看函数的'文档字符串'
3. 函数的文档字符串绑定在函数的 __doc__ 属性上
函数的 __doc__ 属性
用于绑定函数的文档字符串 用于绑定函数的文档字符串
函数定义语句(def 语句) 的完整语法:
[@装饰器1]
[@装饰器2]
[...]
def 函数名([位置形参], [*元组形参], [命名关键字形参], [**字典形参]):
'''文档字符串'''
语句块
注: [] 代表其内部可以省略
模块 Module
什么是模块:
模块是一个包含有一系列数据、函数、类等组成的程序组
模块是一个文件,模块文件名通常以.py结尾.
作用:
让一些相关的数据,函数,类等有逻辑的组织在一起,使逻辑结构更加清晰
模块中的数据,函数,类等可提供给其它模块或程序使用
模块的分类:
内建模块(builtins) 在解析器的内可以直接使用
标准库模块, 安装python时已安装且可以直接使用
第三方模块(通常开源),需要自己安装
用户自己编写的模块(可以作为其它人的第三方模块)
模块的导入语句
import 语句
语法:
import 模块名1 [as 模块新名1], 模块名2 [as 模块新名2], ....
示例:
import math # 导入math模块
import sys, os
作用:
将某模块整体导入到当前模块中
用法:
模块名.属性名
或
模块名.函数属性名(实参传参)
如:
math.factorial(5)
dir(obj) 函数返回所有属性的字符串列表
help(obj) 函数可以查看模块的相关文档字符串
练习:
1. 输入一个圆的半径,打印出这个圆的面积
2. 输入一个圆的面积,打印出这个圆的半径
(要求用math模块内的函数和数据实现)
from import 语句
语法:
from 模块名 import 模块属性名1 [as 属性新名1], 模块属性名2 [as 属性新名2], ....
作用:
将某模块的一个或多个属性导入到当前模块的作用域
示例:
from math import factorial as fac
from math import sin
from math import pi
print(fac(5)) # 120
from import * 语句
语法:
from 模块名 import *
作用:
将某模块的所有属性导入到当前模块
示例:
from math import *
print(sin(pi/2))
print(factorial(5))
dir 函数:
dir([对象]) 返回一个字符串的列表
说明:
如果没有给参数调用,则返回当前作用域内的所有变量的列表
如果给定一个对象为作参数,则返回这个对象的所有变量的列表
1) 对于一个模块,返回这个模块的全部属性
2) 对于一个类,返回这个类的所有变量,并递归基类对象的所有变量
3) 对于其它的对象,返回所有类变量和基类变量
内建 模块
1.math 模块
模块名 math
详见:
python_base_docs_html/数学模块math.html
2. 时间模块 time
模块名: time
详见:
python_base_docs_html/时间模块time.html
练习:
写一个程序,输入你的出生日期,
1) 算出你已经出生多少天?
2) 算出你出生的那天是星期几?
3.系统模块 sys
文档参见:
python_base_docs_html/系统模块sys.html
练习:
1. 请编写函数fun 其功能是计算下列多项式的和:
fn = 1 + 1/1! + 1/2! + 1/3! + 1/4! + .. + 1/n!
(建义用数学模块的factorial实现)
求当n 等于100时,fn的值
看一下fn(100)的值是什么
2. 写一个程序,以电子时钟格式:
HH:MM:SS格式显示时间
要求每隔一秒变化一次
3 写函数f(n)求下多项式的和
fn = 1/1 - 1/3 + 1/5 - 1/7 + 1/9 .... 1/(2*n-1)的和
求当n取值为1000000时,
1) 打印 f(1000000) 的值
2) 打印 f(1000000) * 4的值,看看是什么
day12回顾
装饰器
装饰器函数:
def 装饰函数名(fn):
...
return 函数
如:
def mydeco(fn):
return fn
@mydeco
def fun():
print("fun函数被调用")
fun = mydeco(fun)
示例:
def mydeco(fn):
def fx(a, b):
print("++++++")
fn(a, b)
print('------')
return fx
@mydeco
def fun(x, y):
pass
fun(100, 200)
函数名 和函数调用
def fun():
pass
print(fun) # 打印fun绑定的函数
print(fun()) # 调用fun绑定的函数,打印函数的返回结果
函数的文档字符串
def fx():
'''文档字符串'''
用于help() 帮助函数
函数对象的 __doc__属性 绑定文档字符串
模块的概念
模块是一个包含有一系列的数据,函数,类等组成的程序组
导入 import
导入语句:
import 语句
import math, sys, time
from import 语句
from math import sin,cos, pi
from import * 语句
from math import *
dir() 函数
help() 函数
模块的使用:
math 模块
time 模块
sys 模块
1.自定义模块并导入
要求:
模块文件名后缀名必须以 .py 结尾
模块文件名必须是合法的标识符
避免名称和内建模块名冲突
导入方式:
import 语句
from import 语句
from import * 语句
示例见:
mymod.py
2.import 语句查找模块文件的路径顺序
import 模块名 # 去哪儿找这个 "模块名.py"
1. 搜索内建模块
2. 搜索程序运行时的路径(当前路径)
3. sys.path 提供的路径
sys.path 是一个列表,内部存入的都是模块的搜索路径
>>> import sys
>>> print(sys.path)
3.安装 第三方模块或包
pip3 install 模块名
让import语句能找到自己的模块
1. 把自己的写的模块放到sys.path中的某个文件夹内
2. 修改sys.path列表,在内部添加一个文件夹的字符串
(注:此做法只对当前程序起作用)
如:
import sys
sys.path.append('/home/tarena')
示例见:
test_mymod2.py
模块化编程优点:
1. 有利于多人合作开发
2. 使代码更加易于维护
3. 提高代码的复用率
4. 有利于解决变量名冲突问题(模块内的全局变量的作用域
为模块内全局)
1.模块的加载过程
在模块导入时,模块内的所有语句都会执行
如果一个模块已经导入,则再次导入时不会重新执行模块内的语句
2.模块被导入和执行的过程
1. 先搜索相关路径找到 模块名.py
2. 判断是否有此模块对应的pyc文件.如果.pyc文件比.py
文件新则直接加载.pyc文件
3. 如果.pyc文件比.py文件旧,则用模块名.py 生成 .pyc
文件,并加载执行
3.模块的编译
编译 解释执行
mymod.py -----> mymod.pyc --------> python3
模块的属性
__doc__ 属性
用于绑定模块的文档字符串
模块的文档字符串用于help(模块) 函数提供帮助信息
示例见:
mymod2.py
__file__属性
用于绑定模块的文件路径名
__name__属性
__name__属性用来记录模块自身的名字
作用:
1. 记录模块名
2. 用来判断是否为主模块
说明:
当模块作为主模块(也就是第一个运行的模块)运行时,
__name__属性 绑定 '__main__'
当此模块不是主模块时,__name__属性 绑定模块名
如:
mymod.py 的模块名为 'mymod'
模块的__all__列表
作用:
当用from xxx import *语句导入时,只导入__all__
列表内的属性
说明:
__all__列表是一个用来存放可导出属性的字符串列表
示例见:
mymod3.py
模块的隐藏属性
模块中以'_' 开头的属性,在用 from xxx import * 导
入时将不被导入,通常称这些属性为隐藏属性
示例见:
mymod4.py
随机模块 random
作用:
用于模拟或生成随机输出的模块
文档参见:
python_base_docs_html/随机模块random.py
练习:
用random模块,随机为自己生成一个6位数的数字密码
442260
猜数字游戏:
让程序随机生成一个整数(0~100)之间,用变量x绑定
让用户循环输入整数用y绑定,打印猜数字结果
如果y > x 则提示用户"您猜大了"
如果y < x 则提示用户"您猜小了"
如果y 等于 x 则提求用户"恭喜您猜对了",然后退出
循环输入,并打印用户猜数字的次数
包(模块包) package
包是将模块以文件夹的组织形式进行分组管理的方法
作用:
将一系列模块进行分类管理,有利于防止命名冲突
可以在需要时加载一个或部分模块,而不是全部模块
示例:
mypack/
__init__.py
menu.py
games/
__init__.py
contra.py
supermario.py
tanks.py
office/
__init__.py
excel.py
word.py
包的导入
同模块的导入规则
import 包名 [as 包别名]
import 包名.模块名 [as 模块新名]
import 包名.子包名.模块名 [as 模块新名]
from 包名 import 模块名 [as 模块新名]
from 包名.子包名 import 模块名 [as 模块新名]
from 包名.子包名.模块名 import 属性名 [as 属性新名]
from 包名 import *
from 包名.模块名 import *
1.__init__.py 文件
__init__.py 是常规包内必须存在的文件
__init__.py 会在包加载时被自动调用
作用:
编写此包的内容
在包内填写包的文档字符串
在__init__.py 文件内可以加载此包所依懒的一些其
它模块
2.__init__.py 内的 __all__列表
作用:
用来记录此包中有哪儿些包或模块需要导入
当用from 包 import *语句导入模块时,只查找__all__
中所有的模块或子包
说明:
__all__列表 只在from xxx import * 起作用
示例见:
mypack/games/__init__.py
import 语句搜索包的路径的顺序:
1. 搜索程序运行时的路径(当前工作目录)
2. sys.path提供的路径
包的相对导入
包的相对导入是指包内模块的相互导入
语法:
from 相对路径包或模块 import 属性或模块名
或
from 相对路径包或模块 import *
相对路径:
在from import语句和 from imoprt *语句中可以使
用相对路径
. 代表当前目录
.. 代表上一级目录
... 代表上二级目录
.... 以此类推
注: 相对导入时不能超出包的外部
示例见:
mypack/games/contra.py
练习:
1. 模拟斗地主发牌,牌共54张
黑桃('\u2660'), 梅花('\u2663'), 红桃('\u2666')
方块('\u2665')
A2-10JQK
大王,小王
三个个,每人发17张牌,底牌留三张
输入回车,打印第1个人的17张牌
输入回车,打印第2个人的17张牌
输入回车,打印第3个人的17张牌
输入回车,显示三张底牌
2. 修改原学生信息管理程序,将程序拆分为模块:
要求:
1. 主事件循环while语句放在main.py中
2. show_menu函数放在menu.py中
3. 与学生操作相关的函数放在student_info.py中
3. 打印杨辉三角(只打印6层, 思考题,明天或后天才讲)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
day13回顾
自定义模块
标识符.py 不能是123.py
导入的语句:
import 语句
from import 语句
from import * 语句
搜索模块的路径:
1. 索引内建模块
2. 当前运行时路径
3. 搜索sys.path里提供的路径
mymod.py ---> mymod.pyc ----> python3
模块的预置属性
__doc__属性
__file__属性
__name__属性
主模块 '__main__'
非主模块 绑定 '模块名'
__all__列表
作用是限定在from import *导入时,只导入__all__列表
内的属性
模块的隐藏属性
_下划线开头的属性 在 from import *导入时不会被导入
随机模块
名字: random
函数:
random.random()
random.randint()
random.randrange(...)
random.sample()
random.choice()
....
包 package
包的导入:
import
from import
from import *
示例:
import 包名.xxx.yyy.zzz
from 包名.xxx.yyy.zzz import aaa
from 包名.xxx.yyy.zzz import *
__init__.py
作用:
包的内容:
函数,数据,文档字符串
__init__.py 里的 __all__列表
告诉 from import * 语句导入的内容
__all__ = ['contra', 'tanks']
包的相对导入
只能用于两条语句:
from 相对路径 import 语句
from 相对路径 import *语句
相对路径:
.
..
...
异常 exception (基础)
什么是错误
错误是指由于逻辑或语法等导致程序无法正常执行的问题
特点
无法预知
什么是异常
异常是程序出错时标识的一种状态.当导常发生时,程序不会再
向下执行,而转去调用此函数的地方待处理此错误并恢复为正
常状态
作用:
用作信号通知,通知上层调用者有错误产生需要处理
程序有两种状态:
正常状态/异常状态
try语句 的两种语法
try-except语句
try-finally语句
try-except语句的语法
try:
可能触发异常的语句
except 错误类型1 [as 变量1]:
异常处理语句1
except 错误类型2 [as 变量2]:
异常处理语句2
except (错误类型3, 错误类型4) [as 变量3]:
异常处理语句3
...
except:
异常处理语句other
else:
末发生异常的语句
finally:
最终语句
2.作用:
偿试捕获错误,得到异常通知,将程序由异常状态转换为正常状态并
继续执行
说明:
as 子句是用于绑定错误对象的变量,可以省略
except 子句可以有一个或多个,但至少要有一个
else 子句最多只能有一个.也可以省略
finally子句最多只能有一个.也可以省略
示例见:
try_except.py
练习:
写一个函数 get_score() 来获取学生输入的成绩
信息(0-100)的整数,如果输入出现异常,则此函数返回0,
否则返回用户输入的成绩
def get_score():
.... # 此处自己实现(try语句可以加在函数内部)
score = get_score()
print("学生的成绩是:", score)
python3 中全部的错误类型:
文档参见:
python_base_docs_html/python全部的异常类型.html
try-finally 语句
语法
try:
可能触发异常的语句
finally:
最终语句
说明:
finally子句不可以省略
一定不存在except子句
作用:
通常用try-finally语句来做触发异常时必须要处理的事情
无论异常是否发生,finally子句都会被执行
注:
try-finally语句不会改变程序的(正常/异常)状态
示例:
请问以下语句在做什么事情:
def get_number():
s = input("请输入整数:") or '0'
i = int(s)
return i
print(get_number())
改写上述程序,自己制定规则,让程序不会出崩溃的现象
改写后:
def get_number():
s = input("请输入整数:")
try:
i = int(s)
except:
i = 0
return i
raise 语句
作用:
触发一个错误,让程序进入异常状态
发送错误通知给调用者
语法:
raise 异常类型
或
raise 异常对象
或
raise # 重新触发上一次异常
示例:
raise ValueError #
raise ValueError("???????")
示例见:
raise.py
raise2.py
练习:
写一个函数 get_age() 用来获取一个人的年龄信息
此函数的规定用户只能输入1~140之间的整数,如果用户
输入其它的数据则直接触发ValueError类型的错误通知
如:
def get_age():
....
try:
age = get_age()
print("用户输入的年龄是:", age)
except ValueError as err:
print('用户输入的不是1~140之间的整数'
',获取年龄失败')
assert语句(断言语句)
语法:
assert 真值表达式, 错误数据(通常是字符串)
作用:
当真值表达式为False时,用错误数据创建一个
AssertionError类型的错误,并进入异常状态
通常用来故意制造一个错误
等同于:
if bool(真值表达式) == False:
raise AssertionError(错误数据)
示例见:
assert.py
异常中的语句小结:
try-except 语句
用于捕获(接收)错误通知,把异常状态转为正常状态
try-finally语句
用于执行在任何状态(正常/异常)都必须要执行的语句
raise 语句
触发错误(发送错误通知),让程序进入异常状态
assert 语句
根据条件触发AssertionError类型的错误通知
1.迭代器 Iterator
什么是迭代器
迭代器是访问可迭代对象的工具
迭代器是指iter(obj) 函数返回的对象(实例)
迭代器可以用next(it) 函数获取可迭代对象的数据
2.迭代器函数iter和next
iter(iterable) 从可迭代对象中获取一个迭代器,iterable
必须是能提供一个迭代器的可迭代对象
next(Iterator) 从迭代器iterator中获取下一个记录,如
果无法获取下一条记录,则触发StopIteration异常
说明:
迭代器只能往前取值,不会后退
用iter函数可以返回一个可迭代对象的迭代器
示例:
L = [2, 3, 5, 7]
it = iter(L) # 从L对象中获取一个迭代器
print(next(it)) # 2
print(next(it)) # 3
print(next(it)) # 5
print(next(it)) # 7
print(next(it)) # StopIteration 异常
# 用迭代器访问 range() 函数返回的整数序列生成器
it = iter(range(1, 10, 3))
next(it) # 1
next(it) # 4
next(it) # 7
next(it) # StopIteration
示例见:
iterator.py
练习:
有一个集合
s = {
'唐僧', '悟空', '八戒', '沙僧}
# 用for语句来遍历所有元素如下:
for x in s:
print(x)
else:
print("遍历结束")
# 请将上面的for语句改写为while语句和迭代器实现
练习:
1. 一个球从100米高空下落,每次落地后反弹高度为原高度
的一半,再落下,写程序:
1) 算出皮球在第10次落后反弹多高
2) 算出皮球在第10次反弹后经过多少米路程
2. 分解质因数.输入一个正整数,分解质因数
如 输入: 90 则打印: 90=2*3*3*5
(质因数是指最小能被原数整除的素数(不包括1))
3. 修改原学生信息管理程序,加入异常处理语句,让程序
在任何情况下都能按逻辑正常执行.
如输入成绩,年龄等都不会导致程序崩溃
day14回顾
异常
try-except语句 捕获异常
try-finally 语句 执行必须要执行的语句
raise 语句 触发异常
raise 异常类型
raise 异常类型()
raise
assert 语句 断言语句
try:
可能触发异常的语句
except 异常类型1 as e:
...
except 异常类型2:
...
except (异常类型3, 异常类型4):
....
except:
....
else:
...
finally:
...
迭代器
迭代器
iter(可迭代对象) 返回迭代器
next(迭代器) 取值(当没有值是触发raise StopIteration)
迭代循环
for x in range(10):
...
等同于
it = iter(range(10))
while True:
try:
x = next(it)
...
except StopIteration:
break
1.生成器 Generator
什么是生成器:
生成器是能够动态提供数据的可迭代对象
生成器在程序运行时生成数据,与容器类不同,它通常不会在
内存中保存大量的数据,而是现用现生成
好处:
不占用计算机的内存
生成器有两种:
生成器函数
生成器表达式
生成器函数的定义
含有yield语句的函数是生成器函数,此函数被调用将返回
一个生成器对象
yield 翻译为(产生或生成)
2.yield 语句
语法:
yield 表达式
说明:
yield 只能用于def 函数中,目地是将此函数作为生成器
函数使用
yield 用来生成数据,供迭代器的next(it) 函数使用
示例见:
yield.py
说明:
1. 生成器函数的调用将返回一个生成器对象,生成器对象是
一个可迭代对象
2. 生成器函数用return会触发一个StopIteration异常
(即生成结束)
生成器实用示例见:
myinteger.py
练习:
写一个生成器函数myevent(start, stop) 用来生成从
start 开始,到stop结束(不包含 stop) 区间范围内
的一系列偶数
def myeven(start, stop):
.... # 此处自己实现
evens = list(myeven(10, 20))
print(evens) # [10, 12, 14, 16, 18]
for x in myeven(21, 30):
print(x) # 打印 22 24 26 28
生成器表达式
语法:
(表达式 for 变量 in 可迭代对象 [if 真值表达式])
作用:
用推导式形式创建一个新的生成器
说明:
if 子句可以省略
生成器表达式也可以象列表推导式一样嵌套
示例:
gen = (x**2 for x in range(1, 5))
it = iter(gen) # 拿到迭代器
next(it) # 1
next(it) # 4
next(it) # 9
next(it) # 16
next(it) # StopIteration
练习:
已知有列表:
L = [2, 3, 5, 7]
1) 写一个生成器函数.让此函数能够动态提供数据,提供的数
据为原列表的数字的平方加1
2) 写一个生成器表达式.让此表达式能够动态提供数据,提供
的数据为列表的数字的平方加1
3) 创建一个列表,此列表内的数据为原列表的数字的平方加1
练习:
1.试写一个生成器myfilter函数,此函数与系统内建的
filter函数功能一致
2. 看懂下列函数的输出结果是什么?为什么?
第1个程序
L = [2, 3, 5, 7]
a = [x*10 for x in L]
it = iter(a)
print(next(it)) # ???
L[1] = 333
print(next(it)) # ???
第2个程序
L = [2, 3, 5, 7]
a = (x*10 for x in L)
it = iter(a)
print(next(it)) # ???
L[1] = 333
print(next(it)) # ???
迭代工具函数
迭代工具函数的作用是生成一个符合条件的可迭代对象
zip(iter1[,iter2[, ...]]) 返回一个zip生成器对象
此对象用于生成一个元组,此元组的数据分别来自于
参数中的每个可迭代对象,生成元组的个数由最小的
一个可迭代对象决定
enumerate(iterable, start=0) 返回一个enumerate
生成器对象,此对象生成类型为(索引,值对) 的元组
默认索引从零开始,也可以用start指定
zip示例:
numbers = [10086, 10000, 10010, 95588]
names = ['中国移动', '中国电信', '中国联通']
for t in zip(numbers, names):
print(t)
# 结果
# (10086, '中国移动')
# (10000, '中国电信')
# (10010, '中国联通')
for t in zip(numbers, names, range(1, 10000)):
print(t)
enumerate 示例:
names = ['中国移动', '中国电信', '中国联通']
# for t in zip(range(100000000), names):
# print(t)
for t in enumerate(names):
print(t)
# 打印 (0, '中国移动') (1, '中国电信') (2, '中国联通')
for t in enumerate(names, 101):
print(t)
# 打印 (101, '中国移动') (102, '中国电信') (103, '中国联通')
zip函数的原理示例见:
myzip.py
练习:
写一个程序,读入任意行文字,当输入空行时结束输入,
打印带有行号的输入结果
如:
请输入: hello<回车>
请输入: abc<回车>
请输入: tarena<回车>
请输入: <回车>
打印如下:
第1行: hello
第2行: abc
第3行: tarena
容器
列表,字符串,元组(序列), 字节串,字节数组
字典,集合,固定集合
1.字节串和字节数组
1.字节串(字节序列) bytes
存储以字节为单位的数据
字节串是不可变的字节序列
说明:
字节是0~255之间的整数,用来表示一个字节的取值
1.创建空字节串的字面值方式:
b''
b""
b''''''
b""""""
2.创建非空字节串的字面值
b'ABCD'
b"ABC"
b'''aaaa'''
b"""BBBB"""
2.字节串的构造函数 bytes
bytes() 生成一个空的字节串,等同于b''
bytes(整数可迭代对象) 用可迭代对象始化一个字节串
bytes(整数n) 生成n个值为0的字节串
bytes(字符串, encoding='utf-8') 用字节串转换编
码生成一个字节串
示例:
B = bytes()
B = bytes(range(0x41, 0x61))
B = bytes([65, 66, 67, 68])
B = bytes(10)
B = bytes("Hello", 'utf-8')
B = bytes("中文", 'utf-8')
3.字节串的运算:
+ += * *=
< <= > >= == !=
in / not in
索引和切片
4.函数: len(x), max(x), min(x), sum(x), any(x), all(x)
5.bytes 与 str 的区别:
bytes 存储字节(0~255之间的整数)
str 存储UNICODE字符(0~0x10FFFF) 的字符
6.bytes 与 str 的转换
编码(encode)
str --------------> bytes
b = s.encode(encoding='utf-8')
解码(decode)
bytes ---------------> str
s = b.decode(encoding='utf-8')
示例:
s = "ABC中文"
b = s.encode('utf-8')
s2 = b.decode('utf-8')
print(s, b, s2)
2.字节数组 bytearray: 可变的字节串
1.字节数组的构造函数 bytearray
bytearray()
bytearray(整型可迭代对象)
bytearray(整数n)
bytearray(字符串, encoding='utf-8')
2.运算:
同字节串
+ += * *=
比较: < <= > >= == !=
in / not in
索引/切片
(字节数组可以索引和切片赋值,规则同列表的索引和切
片赋值规则)
3.bytearray 的方法:文档参见: python_base_docs_html/bytearray.html
练习:
1. 写一个生成器函数myxrange([start,]stop[,step])
来生成一系列的整数
要求myxrange功能与range函数功能完全相同
(不允许调用range函数和列表)
用自己写的myxrange,结合生成器表达式求 100以内所
有的奇数的平方和
2. 写一个生成器函数fibonacci, 生成斐波那契数的前n
个数
1 1 2 3 5 8 ....
如:
def fibonacci(n):
...
yield ...
...
1) 打印前20个数:
for x in fibonacci(20):
print(x)
2) 打印前40个斐波那契数的和
print(sum(fibonacci(40)))
3. 思考题:
如何让学生管理系统启动时就能读取文件中的信息来加载
数据? (预习文件操作)
day15回顾
生成器
动态生成数据
生成器分为两种:
生成器函数
生成器表达式
生成器函数:
def myxxxx(....):
...
yield 语句
...
生成器函数的调用只会返回生成器
用next(it) 向迭代器(生成器) 要数据时,生成器函数才会
执行
生成器函数在执行过程中遇到yield会暂停(挂起),会将yield
生成的数据返回给next(it) 函数
def myxrange(...):
...
for x in myxrange(1, 10, 3):
print(x)
生成器表达式:
(x*2 for x in range(10))
[x*2 for x in range(10)]
zip(iterable, *args) 函数
enumerate(iterable, start=0) 函数 (0, "ABC")
字节串bytes 和字节数组 bytearray
字节 byte
是由8个位组所存储单元
字节串: 字面值
b'' b"" b'''''' b""""""
b'ABC' b'123' b'hello'
字节串和字节数组的构造函数
bytes() bytearray()
bytes(可迭代对象) bytearray (可迭代对象)
bytes(整数n) bytearray(整数n)
bytes(字符串, 编码'utf-8') bytearray(...)
运算:
+ += * *=
< > <= >= == !=
in / not in
索引和切片
序列:
str, list, tuple, bytearray, bytes
len(x), max(x) ....
1.文件 File
文件是用于存储数据的基本单位
文件通常用来长期存储数据
文件中数据是以字节为单位进行顺序存储的
2.文件的操作流程
1. 打开文件
2. 读/写文件
3. 关闭文件
注: 任何的操作系统,一个应用程序同时打开文件的数量
有最大数限制
3.文件的打开函数
open(filename, mode='rt') 用于打开一个文件,返回
此用来操作此文件的文件流对象,如果打开失败,
则会触发OSError错误通知
4.文件流对象的关闭方法
F.close() 关闭文件.释放系统资源
示例见:
file_open.py
以十六进制方式显示文件内容的命令:
$ xxd 文件名
python中文本文件的读写操作:
文档参见:
python_base_docs_html/文件file.html
读取文本文件的示例见:
file_read_text1.py
练习:
自己写一个文件"info.txt", 内部存储一些文字信息如下:
张三,20,100
李四,18,98
小王,22,95
写程序将这些数据读取出来,并以如下格式打印在屏幕终端上
张三 今年 20 岁,成绩是: 100
李四 今年 18 岁,成绩是: 98
小王 今年 22 岁,成绩是: 95
文件流对象的readlines方法示例见:
file_read_text2.py
read方法的使用示例见:
file_read_text3.py
python3的文本文件模式
模式字符: 't'
说明:
1. 对文本文件的读写操作需要用字符串(str)进行读写操作
2. 在读写过程中会自动进行编码(encode) 和 解码
(decode)操作
3. 以行为单位分隔,在python内部统一用'\n'作用换行符
进行分隔
各操作系统的换行符:
Linux换行符: '\n'
Windows换行符: '\r\n'
新的Mac OS换行符: '\n'
文本文件的写操作:
方法:
F.write(x)
F.writelines(列表)
模式字符串:
'w'
'x'
'a'
详见文档: python_base_docs_html/文件.html
示例见:
file_write_text.py
练习:
1. 写一个程序,输入很多人的姓名,年龄,成绩存于文件
'infos.txt'中
文件格式自己定义(建议用逗号(,)来分隔各信息)
完成输入后查看文件格式是不是您想要的格式
(用文本文件进行操作)
L = input_student()
def save_to_file(L, filename='infos.txt')
..
save_to_file(L)
二进制文件操作
二进制模式字符: 'b'
默认文件中存储的都是以字节(byte)为单位的数据,通常人
人为的格式
对二进制文件的读写需要用字符串(bytes) 或字节
数组(bytearray)进行操作
对于二进制文件读写方法都 需要用字节为单位进行操作
F.read(n)
F.readline()
F.readlines()
F.write(字节串)
F.writelines(字节串组成的列表)
示例见:
file_read_binary.py
二进制文件的写操作示例见:
file_write_binary.py
F.seek方法
作用:
设置文件的读写位置,返回新的读写位置
格式:
F.seek(偏移量, whence=相对位置)
偏移量
大于0代表向文件末尾方向移动
小于0代表向文件头方向移动
相对位置:
0 代表从文件头开始偏移
1 代表从当前读写位置开始偏移
2. 代表从文件尾开始偏移
示例见:
seek.py
标准输入输出文件:
模块名:
sys
sys.stdin 标准输入文件(默认为键盘)
sys.stdout 标准输出文件(默认为屏幕终端)
sys.stderr 标准错误输出文件(默认为屏幕终端)
注: 标准文件不需要打开即可以使用,也不用手动关闭
示例见:
stdout.py
十个汉字占多少个字节?
汉字编码(只有两种)
国标系列:
GB18030(二字节或四字节编码, 27533个字)
GBK(二字节编码,20013个字)
GB2313(二字节编码,约7千多个字)
(Windows常用)
国际标准:
UNICODE(UNCODE16/UNICODE32) <-> UTF-8
(Linux/Mac OS X/ IOS/ Android 常用)
UTF-8中:
英文ASCII (0x0 - 0x7F) 一字节
(0x80 - 0x3FF) 二字节
(0x400 - 0xFFFF) 三字节(中文在此区)
python 编码字符串:
'gb2312'
'gbk'
'gb18030'
'utf-8'
'ascii'
...
如:
s = "你好"
print(s.encode('gbk'))
print(s.encode('utf-8'))
print(s.encode('ascii'))#出错,"你好"不在ascii内
编码注释:
在源文件中,第一行或第二行写入的如下内容是编码注释
# -*- coding:gbk -*-
或
# -*- coding:utf-8 -*-
练习:
1. 写程序实现复制文件的功能
要求:
1. 要考虑超大文件问题
2. 要能复制二进制文件(如:图片等)
3. 要考虑关闭文件
2.改写原学生信息管理程序,要求加入如下两个功能:
| 9) 从文件中读取数据(si.txt) |
| 10) 保存信息到文件(si.txt) |
day16回顾
文件:
有两种读写方式:
二进制方式: 'b'
字节串/字节数组
文本文件方式: 't'
字符串(默认是'utf-8'编码)
两种操作模式:
读文件 read(INPUT操作)
'r'
写文件 write(OUTPUT操作)
'w','x','a'
流程:
1. 打开文件
2. 读/写文件
3. 关闭文件
open(文件路径名, 模式字符串='rt') 返回文件流对象
F.close()
F.read(n)
F.readline()
F.readlines()
F.write(字节串/字符串)
F.writelines(字节串/字符串 列表)
F.seek(偏移量, 相对位置)
F.tell()
F.flush() 清空缓冲区
汉字编码:
两种:
UNCODE编码 <--> UTF-8
'utf-8'
GB系列的编码
'gb2312'
'gbk'
'gb18030'
ASCII英文编码:
'ascii'
编码注释:
# -*- coding:utf-8 -*-
# -*- coding:gbk -*-
1.面向对象编程 Ojbect-Oriented Programming
两种编程思想: 面向过程编程 --> 最小单位是: 函数 function
面向对象的编程 --> 最小单位是: 类 class
2.什么是对象: 对象是指现实中的物体或实体
3.什么是面向对象: 把一切看成对象(实例) 用各种对象之间的关系来描述事物
4.对象都有什么特征:(1)对象有很多的属性(名词,形容词)-- 姓名, 年龄, 性别, 头发颜色
(2)对象有很多行为(动作,动词) -- 学习,吃饭,睡觉,踢球,工作
1.什么是类
拥有相同属性和行为的对象分为一组,即为一个类
类是用来描述对象的工具,用类可以创建此类的对象(实例)
示意:
车(类) ----> BYD E6(京A.88888) 实例
\
\--> BMW X5(京B.00000) 对象(实例)
狗(类) ----> 小京巴(户籍号: 000001) 对象
\
\---> 导盲犬(户籍号:00002) 对象
int(类) -----> 100 对象
\
\---> 200 对象
2.类的创建语句:
语法:
class 类名(继承列表):
'''类的文档字符串'''
实例方法(类内的函数method)定义
类变量
类方法(@classmethod)
静态方法(@staticmethod)
作用:
创建一个类
类用于描述对象的行为和属性
类用于创建此类的一个或多个对象(实例)
说明:
类名必须是标识符
类名实质是变量,它绑定一个类
示例见:
class.py
3.类的构造函数
格式:
类名([传参列表])
作用:
创建这个类的实例对象,并返回此实例对象的引用关系
示例见:
constructor.py
说明:
对象(实例)可以调用类方法和实例方法
对象(实例) 有自己的作用域和名字空间,可以为该实例添加
实例变量(也叫实例属性)
4.实例方法(instance method)
定义格式:
class 类名(继承列表):
def 实例方法名(self, 参数1, 参数2, ...):
'''方法的文档字符串'''
语句块
作用:
用于描述一个对象的行为,让此类型的全部对象都拥有相同
的行为
说明:
实例方法的实质是函数,是定义在内类的函数
实例方法至少有一个形参,第一个形参绑定调用此方法的实
例,一般命名为'self'
5.实例方法的调用语法:
实例.实例方法名(调用传参)
或
类名.实例方法名(实例, 调用传参)
示例见:
instance_method.py
6.实例属性 attribute (也叫实例变量)
每个实例可以用自己的变量来记录每个对象自己的数据,这个
变量称为实例变量
使用语法:
实例.属性名
赋值规则:
首次为属性赋值则创建此属性
再次为属性赋值则改变此属性的绑定关系
作用:
记录每个对象自身的数据
练习:
定义一个"人" 类
class Human:
def set_info(self, name, age,
address="不详"):
... 此处自己实现
def show_info(self):
'''此处显示人此的信息'''
... 此处自己实现
s1 = Human()
s1.set_info('小张', 20, '北京市东城区')
s2 = Human()
s2.set_info('小李', 18)
s1.show_info() # 小张 今年 20 岁,家住: ...
s1.show_info() # 小李 今年 18 岁,家住: 不详
7.删除属性:
del 语句
del 对象.实例变量名
del 语句总结:
1) 删除变量 del a,b,c
2) 删除列表中的元素 del L[0], L[0:3]
3) 删除字典中的键 del d['name']
4) 删除属性 del obj.name
8.初始化方法
作用:
对新创建的对象添加属性
语法格式:
class 类名(继承列表):
def __init__(self [,形参列表])
语句块
注:[]代表其中的内容可省略
说明:
1. 初始化方法的名必须是 '__init__' 不可改变
2. 初始化方法会在构造函数创建实例后自动调用,且将实
例自身通过第一个参数self传入'__init__' 方法
3. 构造函数的实参将通过__init__方法的参数列表传
入到__init__方法中
4. 初始化方法内如果需要return 返回,则必须返回None
示例见:
init_method.py
练习:
写一个学生类Student类,此类用于描述学生信息,学生
信息有: 姓名,年龄,成绩(默认为0)
1) 为该类添加初始化方法,实现在创建对象时自动设置:
name, age, score 属性
2) 添加set_score方法,能为对象修改成绩信息
3) 添加show_info方法打印学生对象的信息
如:
class Student:
def __init__(....):
....
def set_score(....):
...
def show_info(...)
...
L = []
L.append(Student('小张', 20, 100))
L.append(Student('小李', 18, 95))
L.append(Student('小钱', 19))
L[-1].set_score(70)
for s in L:
s.show_info()
析构方法
格式:
class 类名(继承列表):
def __del__(self):
....
作用:
在此对象销毁前释放此对象所占用的资源
说明:
析构方法在对象被销毁前被自动调用
python语言建议不要在对象销毁时做任何事情,因为销毁
的时间难以确定
示例见:
del_method.py
预置实例属性
__dict__ 属性
__dict__属性绑定一个存储此实例自身变量的字典
示例:
class Dog:
pass
dog1 = Dog()
print(dog1.__dict__) # {}
dog1.color = "白色"
print(dog1.__dict__) # {'color': "白色"}
__class__ 属性
__class__ 属性绑定创建此实例的类
作用:
可以借助于此属性来访问创建此实例的类
示例:
class Dog:
pass
dog1 = Dog()
print(dog1.__class__)
dog2 = dog1.__class__() # Dog()
用于实例对象的函数:
isinstance(obj, class_or_tuple) 返回这个对象obj
是否是某个类的对象,或者某些类中一个类的对象.如果
是则返回True,否则返回False
type(obj) 返回对象的类型
示例:
class Dog:
pass
dog1 = Dog()
isinstance(dog1, Dog) # True
isinstance([1,2,3], Dog) # False
isinstance([1, 2, 3], (int, str)) # False
isinstance([1, 2, 3], (int, str, list))#True
type(dog1) is Dog # True
练习:
有两个人:
第一个人: 姓名:张三, 年龄:35岁
第二个人: 姓名:李四, 年龄:15岁
行为:
1. 教别人学东西 teach
2. 工作赚钱 work
3. 借钱 borrow
4. 显示自己的信息 show_info
事情:
张三 教 李四 学 python
李四 教 张三 学 王者荣耀
张三 上班赚了 1000 元钱
李四 向 张三 借钱 200 元
35 岁的 张三 有钱 800 元,它学会的技能是: 王者荣耀
15 岁的 李四 有钱 200 元,它学会的技能是: python
练习:
1. 完全数:
1 + 2 + 3 = 6 (6为完全数)
1, 2,3为都为6的因数(能被一个数x整除的数y,则y为
x的因数)
1 x 6 = 6
2 x 3 = 6
完全都是指除自身以外的所有因数之和相加等于自身的数
求4 - 5个完全数
答案:
6
28
496
...
2. 将学生信息管理程序,把用于存储学生信息的字典,换成
用Student类型对象来存储学生信息
day17回顾
面向对象:
什么是对象
什么是类
对象的特征:
属性
行业
类 class
类是用于描述对象,创建的对象(实例)
实例方法
class 类名:
def 实例方法名(self, 方法的形参列表):
语句块
调用的语法:
对象.实例方法名(实参)
类名.实例方法名(对象, 实参)
class 类内:
class 类名:
实例方法(self, ...):
...
类变量
类方法
静态方法
构造函数
类名(调用实参) 创建一个实例(对象)
实例变量(实例属性)
记录对象的数据
v = 对象.属性名 # 取值
对象.属性名 = v # 赋值(创建或修改实例变量)
删除实例变量
del 对象.属性名
初始化方法:
def __init__(self, 方法的形参):
....
作用:
创建实例变量(实例属性)
析构方法:
def __del__(self):
...
预置的实例属性:
__dict__ 绑定实例变量(实例属性)的字典
class Dog:
pass
dog1.color = "白色" # 添加实例变量
dog1.__dict__['kinds'] = "京巴" # 添加实例变量
__class__ 绑定创建此实例的类
type(obj) 返回obj.__class__
type(obj) # 返回类型等同于 obj.__class__
isinstance(obj, 类或类的元组)
obj.__class__ is 类
或
obj.__class__ in 元组
1.类
定义方法:
class 类名:
...
类也是对象,它是能创建实例的对象
2.类变量
类变量是类的属性,此属性属于类,不属于此类的实例
作用:
通常用来存储该类创建的对象的共有属性
说明:
类变量可以通过该类直接访问
类变量可以通过类的实例直接访问(取值)
类变量可以通过此类的对象的__class__属性间接访问
示例见:
class_variable.py
实例方法和类方法都是类的变量(类变量)
类的文档字符串:
类内第一个没有赋值给任何变量的字符串为类的文档
字符串
类的文档字符串绑定在类的 __doc__ 属性上
示例:
class Dog:
'''Dog类的文档字符串'''
>>> help(Dog)
>>> print(Dog.__doc__)
类的 __slots__ 列表:
作用:
限定一个类创建的实例只能在固定的属性(实例变量)
不允许对象添加此列表以外的实例属性
访问用户因错写属性名而发生程序错误
说明:
__slots__属性是一个列表,列表的值是字符串
含有__slots__属性的类所创建的实例对象没有
__dict__属性,即此实例不用字典来存储实例属性
示例见:
slots.py
类方法 @classmethod
类方法是用于描述类的行为的方法,类方法属于类,不属于
该类创建的对象
说明:
1. 类方法需要使用@classmethod 装饰器定义
2. 类方法至少有个一个形参,第一个形参用于绑定
类,约定写为'cls'
3. 类和该类的实例都可以调用类方法
4. 类方法不能访问此类创建的对象的实例属性
示例见:
classmethod.py
静态方法 @staticmethod
静态方法是定义在类内的函数,此函数的作用域是类的内部
说明:
1. 静态方法需要使用@staticmethod 装饰器定义
2. 静态方法与普通函数定义相同,不需要传入self
和cls参数
3. 静态方法只能凭借该类或类的实例调用
4. 静态方法不能访问类变量和实例变量
示例见:
staticmethod.py
函数,静态方法, 类方法, 实例方法:
共性:
语句块,实现相应的功能
练习:
1. 用类来描述一个学生的信息(也可以改写之前的
Student类)
2. 学生信息有:
姓名,年龄,成绩
3. 将这些学生对象存于列表中,可以任意添加,和
删除学生信息
1) 打印出学生的个数
2) 打印出所有学生的平均成绩
3) 打印出所有学生的平均年龄
(建议用类变量来记录学生的信息的列表)
1.继承 inheritnce 和 派生 derived
什么是继承/派生
派生就是从一个已有的类中衍生成新类
继承是指在衍生出的新类中的对象会拥有原类的属
性和行为
作用:
用继承派生机制,可以将一些共有功能加在基类中.
实现代码共享
在不改变基类代码的基础上,改变原有类的功能
名词:
基类(base class)/超类(super class)/父
类(father class)
派生类(derived class) / 子类(child class)
2.单继承:
语法:
class 类名(基类名):
语句块
说明:
单继承是指派生类由一个基类衍生出来的类
示例见:
inherit.pyinherit.py
继承说明:
python3中任何类都直接或间接的继承自object类
object类是一切类的超类
3.类的__base__属性
__base__ 属性用来记录此类的基类
python内建类的继承关系见:
>>> help(__builtins__)
覆盖 overridde
覆盖是指在有继承关系的类中.子类中实现了与基类
同名的方法,在子类的实例调用该方法时,实际调用的
是子类的覆盖版本,这种现象叫做覆盖
作用:
实现和父类同名,但功能不同的方法
示例见:
override.py
问题:
当覆盖发生时, 如何调用父类的被覆盖方法?
1.super函数
super(cls, obj) 返回绑定超类的实例(要求obj必须
是cls 类或cls子类的对象)
super() 返回绑定超类的实例,等同于:
super(__class__, 实例方法的第一个参数),
必须用在方法内调用
作用:
借助super() 返回的实例间接调用父类的覆盖方法
示例见:
super.py
2.super的应用
显式调用基类的初始化方法
当子类中实现了__init__方法,基类的__init__方法
将不会被自动调用.如果需要调用,则需要用super显式
调用.
示例见:
super_init.py
练习:
1. 写一个类Bicycle自行车类,有run方法,调用时
显示骑行的里程km
class Bicycle:
def run(self, km):
print("自行车骑行了", km, '公里')
再写一个EBicycle电动自行车类,在Bicycle的基础
上添加了电池电量volume属性,有两个方法:
fill_charge(vol) 用来充电 vol为电量
run(km) 方法,每骑行10km消耗电量1度,同时显
示当前电量,当电量耗尽时则调用Bicycle的run方法
(用脚蹬骑行)
class EBicycle:
....
b = EBicycle(5) 新买的电动车内有5度电
b.run(10) 电动骑行了10km里,还剩4度电
b.run(100) 电动骑行了40km里,还剩0度电,用脚蹬
骑行了60km
b.fill_charge(10) 电动自行车充电10度
b.run(50) 电动骑行了50km里,还剩5度电
day18回顾
类 -> 对象 (实例)
class object(instance)
对象:
实列变量(实例属性)
实列方法
类:
类变量(类属性)
类方法(@classmethod)
@classmethod
def myclassmethod(cls, ....):
....
静态方法(类内的函数)
预置的类属性(类变量)
__docs__ 绑定文档字符串
__base__ 绑定当前类的基类(父类)
__slots__列表
限定一个类只能有固定的实例变量(实例属性)
继承 / 派生
单继承
class 类名(只有一个父类):
pass
覆盖:
有继承关的类的中,子类实现与父类同名的方法,子类调用
该方法实际调用的是子类的覆盖版本
一但覆盖,子类对象没办法去直接调用父类的被覆盖方法
super(类, 对象)
super() # 只能在方法里调用
用super显式调用父类的 __init__ 初始化方法
super().__init__(给父类的初始方法传实参)
用于类的函数:
issubclass(cls, class_or_tuple) 判断一个类是
否继承自某个类 class 或某些类tuple中的
一个类,如果是则返回True,否则返回False
示例:
class A:
pass
class B(A):
pass
class C(B):
pass
issubclass(C, B) # True
issubclass(bool, int) # True
issubclass(str, (A, B, int, float)) # False
issubclass(str, (A, B, int, object)) # True
面向对象编程语言的特征:
继承
封装
多态
封装
封装是指隐藏类的实现细节,让使用者不关心这些细节
封装的目的是让使用者通过尽可能少的方法(或属性)操
作对象
私有属性和方法
python类中以双下划线__开头,不以双下划线结尾的标识
符为私有成员,私有成员只能使用该类的方法进行访问和
修改
示例见:
enclosure.py
1.多态 polymorphic
字面意思: '多种状态'
2.编程语言的状态:
静态(编译时状态) # C/C++
动态(运行时状态) # C++/Java
3.多态原指在有继承关系的类中,调用基类对象的方法,实际能
调用到子类覆盖方法的现象叫多态
说明:
python全部的对象都只有'运行时状态(动态)',没有
C++语言里的编译时状态(静态)
示例见:
poly.py
多继承 multiple inheritance
多继承是指一个子类继承自两个或两个以上的基类
多继承是的语法:
class 类名(基类名1, 基类名2, ...):
语句
说明:
1. 一个子类同时继承自多个父类,父类中的方法可以同
时被继承下来
2. 如果两个父类中有同名的方法,而在子类中又没有覆
盖此方法时,调用结果难以确定
示例见:
multi_inherit.py
多继承的问题(缺陷)
标识符(名字空间) 冲突的问题
要谨慎使用多继承
示例见:
multi_inherit2.py
多继承的MRO(Method Resolution Order) 问题
MRO --> 方法的解决(查找)顺序
类的 __mro__属性
用来记录类的方法的查找顺序
示例见:
mro.py
对象转字符串函数的使用
repr(obj) 返回一个附合python语法规则的字符串,
通常:
eval(repr(obj)) == obj
str(obj) 通过给定的对象返回一个字符串(这个字符
串通常是给人阅读的)
示例见:
repr_str.py
说明:
以上两个函数返回的一定是个字符串
1.函数重写
函数重写是指在自定义的类内添加相应的方法,让自定义
的类创建的实例可以像内建对象一样进行函数操作
2.对象转字符串函数的重写方法
repr(obj) 函数的重写方法:
def __repr__(self):
return '字符串'
str(obj) 函数的重写方法:
def __str__(self):
return '字符串'
示例见:
mynumber.py
student.py
str(obj) 函数调用方法说明:
1. 先调用obj.__str__() 方法取值.
2. 如果obj.__str__()方法不存在,则调
用obj.__repr__() 方法取值
3. 如果再不存在obj.__repr__()方法.则调用object
类的__repr__方法取值.
内建函数重写
方法名 函数名
__abs__(self) abs(obj) 函数
__len__(self) len(obj) 函数
__reversed__(self) reversed(obj)
__round__(self) round(obj)
示例见:
len_overwrite.py
数值转换函数重写
方法名 函数名
__complex__(self) complex(obj)
__int__(self) int(obj)
__float__(self) float(obj)
__bool__(self) bool(obj)
示例见:
mynumber2.py
布尔测试函数bool(obj) 函数重写
作用:
用于bool(obj) 函数取值:
用于if语句的真值表达式中
用于while语句的真值表达式中
说明:
1. 优先调用obj.__bool__() 方法进行取值
2. 当不存在obj.__bool__() 方法时,用
obj.__len__() 的返回值是否为零来测定布尔值
3. 当不存在__len__() 方法时,则直接返回True
示例见:
bool.py
对象的属性管理函数
getattr(obj, name[, default]) 从一个对象得到
对象的属性;getattr(x, 'y') 等同于x.y;
当属性不存在时,如果给出default参数,则返
回default,如果没有给出default 则产生一
个AttributeError错误
hasattr(obj, name) 用给定的name返回对象obj是
否有此属性,此种做法可以避免在
getattr(obj, name)时引发错误
setattr(obj, name, value) 给对象obj的名为
name的属性设置相应的值value,
set(x, 'y', v) 等同于 x.y = v
delattr(obj, name) 删除对象obj中的name属性,
delattr(x, 'y') 等同于 del x.y
1.迭代器(高级)
什么是迭代器
可以能过next(it) 函数取值的对象就是迭代器
迭代器协议:
迭代器协议是指对象能够使用next函数获取下一
项数据,在没有下一项数据时触发一个StopIteration
异常来终止迭代的约定
迭代器协议的实现方法:
__next__(self) 方法来实现迭代器协议
2.什么是可迭代对象:
是指能用iter(obj) 函数返回迭代器的对象(实例)
可迭代对象的内部要定义 __iter__(self) 方法来返回
迭代器对象(实例)
示例见:
mylist_iterable.py
练习:
1. 修改之前的学生信息管理程序
要求将学生的成绩,姓名,年龄属性进行封装,不让
除Student类之外的函数和方法访问和修改
2. 实现一个与系统内建的range类相同功能的类:
class MyRange:
def __init__(self, ....):
...
def __iter__(self):
...
实现如下功能:
L = list(MyRange(5))
print(L) # [0, 1, 2, 3, 4]
print(sum(MyRange(1, 101))) # 5050
L2 = [x**2 for x in MyRange(1, 10, 3)]
print(L2) # [1, 16, 49]
for x in MyRange(10, 0, -3):
print(x) # 10, 7, 4, 1
day19回顾
issubclass(cls, 类或元组)
封装
__ 开头的私有属性和私有方法来实现
多态
动态和静态
继承,封装,多态
多继承
一个子类继承自两个或两个以上的父类
__mro__ Method Resolution Order
super(B, b).xxxx()
函数重写
让自定义的类能够使用内建函数进行操作
repr __repr__
str __str__
len
abs
round
reversed
int
float
complex
bool
四个属性相关的函数
setattr(obj, name, value)
hasattr(obj, name)
getattr(obj, name [,default])
delattr(obj, name)
迭代器
__next__(self) 方法
实现迭代器协议
可迭代对象
__iter__(self) 方法
return 迭代器
异常
异常相关的语句回顾:
try-except
try-finally
raise
assert
环境管理器
类内有 __enter__ 和 __exit__实例方法的类被称为
环境管理器
__enter__将在进入with语句时被调用,并返回由as变量
管理的对象
__exit__将在离开with语句时被调用,且可以用参数来
判断在离开with语句时是否有异常发生,并做出相应的
处理
示例见:
with2.py
运算符重载
什么是运算符重载
让自定义的类生成的对象(实例)能够使用运算
符进行操作
作用:
让自定义的类的实例像内建对象一样使用运算符
让程序简洁易读
对自定义的对象将运算符赋予新的运算规则
算术运算符重载
方法名 运算符和表达式 说明
__add__(self, rhs) self + rhs 加法
__sub__(self, rhs) self - rhs 减法
__mul__(self, rhs) self * rhs 乘法
__truediv__(self, rhs) self / rhs 除法
__floordiv__(self, rhs) self // rhs 地板除
__mod__(self, rhs) self % rhs 求余
__pow__(self, rhs) self ** rhs 幂运算
rhs (right hands side) 右手边
示例见:
mynumber1.py
说明:
运算符重载的方法和参数已经有固定的含义,不建议
改变原有的意义
练习:
实现两个自定义的列表相加
class MyList:
def __init__(self, iterable=()):
...
.....
L1 = MyList(range(1, 4))
L2 = MyList([4, 5, 6])
L3 = L1 + L2
print(L3) # MyList([1, 2, 3, 4, 5, 6])
L4 = L2 + L1
print(L4) # MyList([4, 5, 6, 1, 2, 3])
L5 = L1 * 2
print(L5) # MyList([1, 2, 3, 1, 2, 3])
# 思考:
L6 = 2 * L2 # 可以吗?为什么?
反向算术运算符的重载
当运算符左侧为内建类型,右侧为自定义类型进行算术
运算时,会出现TypeError错误
因无法修改内建类型的代码来实现运算符重载,此时需要
使用反向算术运算符重载来完成重载
方法名 运算符和表达式 说明
__radd__(self, lhs) lhs + self 加法
__rsub__(self, lhs) lhs - self 减法
__rmul__(self, lhs) lhs * self 乘法
__rtruediv__(self, lhs) lhs / self 除法
__rfloordiv__(self, lhs) lhs // self 地板除
__rmod__(self, lhs) lhs % self 求余
__rpow__(self, lhs) lhs ** self 幂运算
示例见:
code/mylist.py
复合赋值算术运算符重载
以复合赋值算术运算符 x += y 为例,此运算符会优先
调用 x.__iadd__(y) 方法.如果没有__iadd__方法
时会将赋合赋值运算符拆解为 x = x + y 然后再调用
x = x.__add__(y) 方法,如果再不存在__add__方法
则会触发TypeError异常
其它复合赋值算术运算符也具有相同的规则
方法名 运算符和表达式 说明
__iadd__(self, rhs) self += rhs 加法
__isub__(self, rhs) self -= rhs 减法
__imul__(self, rhs) self *= rhs 乘法
__itruediv__(self, rhs) self /= rhs 除法
__ifloordiv__(self, rhs) self //= rhs 地板除
__imod__(self, rhs) self %= rhs 求余
__ipow__(self, rhs) self **= rhs 幂运算
示例见:
mylist2.py
问题:
# ---- 程序1用列表实现 -------
L = [1, 2, 3]
def f1(lst):
lst += [4, 5, 6]
f1(L)
print(L) # [1, 2, 3, 4, 5, 6]
# -----程序用元组实现 --------
L = (1, 2, 3)
def f1(lst):
lst += (4, 5, 6)
f1(L)
print(L) # (1, 2, 3)
比较运算符的重载:
方法名 运算符和表达式 说明
__lt__(self, rhs) self < rhs 小于
__le__(self, rhs) self <= rhs 小于等于
__gt__(self, rhs) self > rhs 大于
__ge__(self, rhs) self >= rhs 大于等于
__eq__(self, rhs) self == rhs 等于
__ne__(self, rhs) self != rhs 不等于
位运算符重载:
方法名 运算符和表达式 说明
__and__(self, rhs) self & rhs 位与
__or__(self, rhs) self | rhs 位或
__xor__(self, rhs) self ^ rhs 位异或
__lshift(self, rhs) self << rhs 左移
__rshift(self, rhs) self >> rhs 右移
反向位运算符重载:
方法名 运算符和表达式 说明
__rand__(self, lhs) lhs & self 位与
__ror__(self, lhs) lhs | self 位或
__rxor__(self, lhs) lhs ^ self 位异或
__rlshift(self, lhs) lhs << self 左移
__rrshift(self, lhs) lhs >> self 右移
复合赋值位运算符重载:
方法名 运算符和表达式 说明
__iand__(self, rhs) self &= rhs 位与
__ior__(self, rhs) self |= rhs 位或
__ixor__(self, rhs) self ^= rhs 位异或
__ilshift(self, rhs) self <<= rhs 左移
__irshift(self, rhs) self >>= rhs 右移
一元运算符的重载:
方法名 运算符和表达式 说明
__neg__(self) - self 负号
__pos__(self) + self 正号
__insert__(self) ~ self 取反
语法:
class 类名:
def __xxx__(self):
....
示例见:
mylist4.py
in / not in 运算符重载:
方法名 运算符和表达式
__contains__(self, e) e in self
示例见:
mylist5.py
索引和切片运算符的重载:
L[0]
L[::2]
方法名 运算符和表达式 说明
__getitem__(self, i) x = self[i] 取值
__setitem__(self, i, v) self[i] = v 赋值
__delitem__(self, i) del self[i] 删除索引
示例见:
mylist6.py
slice 构造函数
作用:
用于创建一个slice切片对象,此对象存储一个切片
的起始值,终止值和步长信息,默认都为None
格式:
slice(start=None, stop=None, step=None)
slice对象的属性
s.start 切片的起始值 默认为None
s.stop 切片的终止值,默认为None
s.step 切片的步长,默认为None
示例见:
mylist7.py
特性属性 @property
实现其它语言所拥有的 getter 和 setter 功能
作用:
用来模拟一个属性
通过@property装饰器可以对模拟的属性赋值和取值
加以控制
示例见:
property.py
PEP8编码规范
文档参见:
python_base_docs_html/PEP8编码规范.html
返
回default,如果没有给出default 则产生一
个AttributeError错误
hasattr(obj, name) 用给定的name返回对象obj是
否有此属性,此种做法可以避免在
getattr(obj, name)时引发错误
setattr(obj, name, value) 给对象obj的名为
name的属性设置相应的值value,
set(x, ‘y’, v) 等同于 x.y = v
delattr(obj, name) 删除对象obj中的name属性,
delattr(x, ‘y’) 等同于 del x.y
#### 9.迭代器(高级)
```python
1.迭代器(高级)
什么是迭代器
可以能过next(it) 函数取值的对象就是迭代器
迭代器协议:
迭代器协议是指对象能够使用next函数获取下一
项数据,在没有下一项数据时触发一个StopIteration
异常来终止迭代的约定
迭代器协议的实现方法:
__next__(self) 方法来实现迭代器协议
2.什么是可迭代对象:
是指能用iter(obj) 函数返回迭代器的对象(实例)
可迭代对象的内部要定义 __iter__(self) 方法来返回
迭代器对象(实例)
示例见:
mylist_iterable.py
练习:
1. 修改之前的学生信息管理程序
要求将学生的成绩,姓名,年龄属性进行封装,不让
除Student类之外的函数和方法访问和修改
2. 实现一个与系统内建的range类相同功能的类:
class MyRange:
def __init__(self, ....):
...
def __iter__(self):
...
实现如下功能:
L = list(MyRange(5))
print(L) # [0, 1, 2, 3, 4]
print(sum(MyRange(1, 101))) # 5050
L2 = [x**2 for x in MyRange(1, 10, 3)]
print(L2) # [1, 16, 49]
for x in MyRange(10, 0, -3):
print(x) # 10, 7, 4, 1
day19回顾
issubclass(cls, 类或元组)
封装
__ 开头的私有属性和私有方法来实现
多态
动态和静态
继承,封装,多态
多继承
一个子类继承自两个或两个以上的父类
__mro__ Method Resolution Order
super(B, b).xxxx()
函数重写
让自定义的类能够使用内建函数进行操作
repr __repr__
str __str__
len
abs
round
reversed
int
float
complex
bool
四个属性相关的函数
setattr(obj, name, value)
hasattr(obj, name)
getattr(obj, name [,default])
delattr(obj, name)
迭代器
__next__(self) 方法
实现迭代器协议
可迭代对象
__iter__(self) 方法
return 迭代器
异常
异常相关的语句回顾:
try-except
try-finally
raise
assert
环境管理器
类内有 __enter__ 和 __exit__实例方法的类被称为
环境管理器
__enter__将在进入with语句时被调用,并返回由as变量
管理的对象
__exit__将在离开with语句时被调用,且可以用参数来
判断在离开with语句时是否有异常发生,并做出相应的
处理
示例见:
with2.py
运算符重载
什么是运算符重载
让自定义的类生成的对象(实例)能够使用运算
符进行操作
作用:
让自定义的类的实例像内建对象一样使用运算符
让程序简洁易读
对自定义的对象将运算符赋予新的运算规则
算术运算符重载
方法名 运算符和表达式 说明
__add__(self, rhs) self + rhs 加法
__sub__(self, rhs) self - rhs 减法
__mul__(self, rhs) self * rhs 乘法
__truediv__(self, rhs) self / rhs 除法
__floordiv__(self, rhs) self // rhs 地板除
__mod__(self, rhs) self % rhs 求余
__pow__(self, rhs) self ** rhs 幂运算
rhs (right hands side) 右手边
示例见:
mynumber1.py
说明:
运算符重载的方法和参数已经有固定的含义,不建议
改变原有的意义
练习:
实现两个自定义的列表相加
class MyList:
def __init__(self, iterable=()):
...
.....
L1 = MyList(range(1, 4))
L2 = MyList([4, 5, 6])
L3 = L1 + L2
print(L3) # MyList([1, 2, 3, 4, 5, 6])
L4 = L2 + L1
print(L4) # MyList([4, 5, 6, 1, 2, 3])
L5 = L1 * 2
print(L5) # MyList([1, 2, 3, 1, 2, 3])
# 思考:
L6 = 2 * L2 # 可以吗?为什么?
反向算术运算符的重载
当运算符左侧为内建类型,右侧为自定义类型进行算术
运算时,会出现TypeError错误
因无法修改内建类型的代码来实现运算符重载,此时需要
使用反向算术运算符重载来完成重载
方法名 运算符和表达式 说明
__radd__(self, lhs) lhs + self 加法
__rsub__(self, lhs) lhs - self 减法
__rmul__(self, lhs) lhs * self 乘法
__rtruediv__(self, lhs) lhs / self 除法
__rfloordiv__(self, lhs) lhs // self 地板除
__rmod__(self, lhs) lhs % self 求余
__rpow__(self, lhs) lhs ** self 幂运算
示例见:
code/mylist.py
复合赋值算术运算符重载
以复合赋值算术运算符 x += y 为例,此运算符会优先
调用 x.__iadd__(y) 方法.如果没有__iadd__方法
时会将赋合赋值运算符拆解为 x = x + y 然后再调用
x = x.__add__(y) 方法,如果再不存在__add__方法
则会触发TypeError异常
其它复合赋值算术运算符也具有相同的规则
方法名 运算符和表达式 说明
__iadd__(self, rhs) self += rhs 加法
__isub__(self, rhs) self -= rhs 减法
__imul__(self, rhs) self *= rhs 乘法
__itruediv__(self, rhs) self /= rhs 除法
__ifloordiv__(self, rhs) self //= rhs 地板除
__imod__(self, rhs) self %= rhs 求余
__ipow__(self, rhs) self **= rhs 幂运算
示例见:
mylist2.py
问题:
# ---- 程序1用列表实现 -------
L = [1, 2, 3]
def f1(lst):
lst += [4, 5, 6]
f1(L)
print(L) # [1, 2, 3, 4, 5, 6]
# -----程序用元组实现 --------
L = (1, 2, 3)
def f1(lst):
lst += (4, 5, 6)
f1(L)
print(L) # (1, 2, 3)
比较运算符的重载:
方法名 运算符和表达式 说明
__lt__(self, rhs) self < rhs 小于
__le__(self, rhs) self <= rhs 小于等于
__gt__(self, rhs) self > rhs 大于
__ge__(self, rhs) self >= rhs 大于等于
__eq__(self, rhs) self == rhs 等于
__ne__(self, rhs) self != rhs 不等于
位运算符重载:
方法名 运算符和表达式 说明
__and__(self, rhs) self & rhs 位与
__or__(self, rhs) self | rhs 位或
__xor__(self, rhs) self ^ rhs 位异或
__lshift(self, rhs) self << rhs 左移
__rshift(self, rhs) self >> rhs 右移
反向位运算符重载:
方法名 运算符和表达式 说明
__rand__(self, lhs) lhs & self 位与
__ror__(self, lhs) lhs | self 位或
__rxor__(self, lhs) lhs ^ self 位异或
__rlshift(self, lhs) lhs << self 左移
__rrshift(self, lhs) lhs >> self 右移
复合赋值位运算符重载:
方法名 运算符和表达式 说明
__iand__(self, rhs) self &= rhs 位与
__ior__(self, rhs) self |= rhs 位或
__ixor__(self, rhs) self ^= rhs 位异或
__ilshift(self, rhs) self <<= rhs 左移
__irshift(self, rhs) self >>= rhs 右移
一元运算符的重载:
方法名 运算符和表达式 说明
__neg__(self) - self 负号
__pos__(self) + self 正号
__insert__(self) ~ self 取反
语法:
class 类名:
def __xxx__(self):
....
示例见:
mylist4.py
in / not in 运算符重载:
方法名 运算符和表达式
__contains__(self, e) e in self
示例见:
mylist5.py
索引和切片运算符的重载:
L[0]
L[::2]
方法名 运算符和表达式 说明
__getitem__(self, i) x = self[i] 取值
__setitem__(self, i, v) self[i] = v 赋值
__delitem__(self, i) del self[i] 删除索引
示例见:
mylist6.py
slice 构造函数
作用:
用于创建一个slice切片对象,此对象存储一个切片
的起始值,终止值和步长信息,默认都为None
格式:
slice(start=None, stop=None, step=None)
slice对象的属性
s.start 切片的起始值 默认为None
s.stop 切片的终止值,默认为None
s.step 切片的步长,默认为None
示例见:
mylist7.py
特性属性 @property
实现其它语言所拥有的 getter 和 setter 功能
作用:
用来模拟一个属性
通过@property装饰器可以对模拟的属性赋值和取值
加以控制
示例见:
property.py
PEP8编码规范
文档参见:
python_base_docs_html/PEP8编码规范.html