python教程学习
一、 ubuntu基本使用
1.简介
励志公式:
1.01^365 = 37.8
0.99^365 = 0.03
1.01^3 * 0.99 ^2 <1.01 三天打鱼两天晒网43
Python 终端验证
- python
- 1.01 ** 365 将会输出 37.783
- 0.99 ** 365 将会输出 0.0255
1.1. 目录
Ubuntu 系统没有盘符的概念,只有目录
/
/ -> /etc /lib /bin /usr /home
/home -> /mayun /laowang /lvbu
/mayun -> /Desktop /python …
1.2. 常用命令基本使用
序号 | 命令 | 对应英文 | 作用 |
---|---|---|---|
01 | ls | list | 查看当前文件下的内容 |
02 | pwd | print work directory | 查看当前文件夹 |
03 | cd [目录名] | change directory | 切换文件夹 |
04 | touch | touch | 如果文件不存在则新建文件 |
05 | mkdir [目录名] | make directory | 创建目录 |
06 | rm [目录名] | remove | 删除指定文件 |
07 | clear | clear | 清屏 |
小技巧
- ctrl + shift + = 放大终端中的字体显示
- ctrl + - 缩小终端窗口的字体显示
自动补全
在敲出 文件/目录/命令 的前几个字母后,按下tab键
文件输入没有奇异,系统会自动补全
1.3 终端命令
command [-options] [parameter]
说明
- command:命令名,相应的英文单词或者缩写
- [-options]:选项,用来对命令进行控制,也可以省略
- parameter :传给命令的参数,可以时零个、一个、或者多个
[] 代表可选
1.4 查阅命令帮助信息
–help
command --help
- 显示 command 命令的帮助信息
man
man command
- 查阅command 命令的使用手册
- man 是 manual 的缩写,Linux 提供的一个手册,包含绝大部分的命令、函数的歇息使用说明
2. 文件目录相关
2.1 通配符的使用
一些特殊的符号可以代替其他的字符
- . 任意个数个字符
- ? 代表任意一个字符,至少一个
- [] 表示可以匹配字符组中的任意一个
- [abc] 匹配a、b、c中任意一个
- [a-f] 匹配从a到f范围内的任意一个
2.2查看 ls
- -a 显示指定目录下所有目录与文件,包括隐藏文件
- -l 以列表方式显示文件的详细信息
- -h 配合-l 以人性化的方式显示文件大小
2.3切换 cd
- cd 切换当前用户的主目录(/home)
- cd ~ 切换当前目录的主目录
- cd . 保持在当前目录不变
- cd … 切换到上一级目录
- cd - 可以在最近两次工作目录中切换
绝对、相对目录 最前面是否 /或者~ 开头的目录
2.4创建和删除 touch rm mkdir
touch 文件不存在创建,存在修改创建时间
mkdir -p 递归创建目录
rm 使用rm命令要小心,文件删除后不能恢复
- -f 强制删除,忽略不存在的文件,无任何提示
- -r 递归删除目录下的内容,删除文件夹必须加此参数
2.5拷贝和移动文件 cp mv
cp拷贝
- cp -f 已存在文件直接覆盖,不会提示
- cp -i 覆盖文件前提醒
- cp -r 目录文件赋值,递归赋值
mv move的缩写,移动文件+重命名
- mv 源文件 目标文件
- mv -i 覆盖时会有一个提示
2.6 文件内容相关cat more grep
cat 文件名,查看文件内容,创建文件,合并文件,追加文件内容等功能
- 会一次显示所有的内容,适合 查看内容缺少的文本文件
- cat -b 对非空输出行编号
- cat -n 对输出所有行编号
- Linux中还有 nl 的命令 和 cat -b 的效果等价
more 文件名,分屏显示文件内容,每次只显示一页内容
- 适合于查看内容较多 的文本文件
- more的更多操作键:
- 空格键 显示手册页的下一屏
- Enter键 一次滚动手册页的一行
- b 回滚一屏
- f 前滚一屏
- q 退出
- /word 搜索world 字符串
grep 搜索文本 文件名,搜索文本文件内容
- -n 显示匹配行及行号
- -v 显示不包含匹配文件的所有行(想当于求反)
- -i 忽略大小写
2.7.其他: echo 重定向>和>> 管道
echo 一般跟重定向一起使用
- Linux 允许将命令执行结果 重定向到一个文件
- 将文本显示在终端的内容 输出/追加 到指定文件中
其中:
1.> 表示输出,会覆盖文件原有的内容
2. >>表示追加,会将内容追加到已有 文件的末尾
3. ls -lh > a 将当前目录的文本信息写到a文件中(重定向的一个例子)
管道 |
- Linux 允许将 一个命令的输出 可以通过管道 作为 另一个命令的输入
- 可以理解为显示生活中的管子,管子的一头塞进东西进去,另一头取出来,这里 | 的左右分为两端,左端塞东西(写),右端取东西(读)
管道的常用管道命令有:
more:分屏显示内容
grep:在命令执行结果的基础上查询指定的文本
例如: ls -lha | grep Do
tree命令
sudo apt-get install tree
tree [目录]
树型显示文件夹形式
3. 远程管理常用命令
3.1关机/重启
基本语法
序号 | 命令 | 对应英文 | 作用 |
---|---|---|---|
01 | shutdown 选项 时间 | shutdown | 关机/重启选项 |
shutdown
- shutdown 命令可以安全关闭 或者 重新启动系统
-r 重新启动
提示:
- 不指定选项和参数;默认1分钟之后关闭电脑
- 远程维护服务器时,最好不要关闭系统,而应该重启系统
常用命令
# 重启操作系统,其中now表示现在
$ shutdown -r now
# 立即关机,其中now表示现在
$ shutdown now
# 系统在今天20:25关机
$ shutdown 20:25
# 系统在十分钟后关机
$ shutdown +10
# 取消之前指定的关机计划
$ shutdown -c
3.2. 查看或配置网卡信息
序号 | 命令 | 对应英文 | 作用 |
---|---|---|---|
01 | ifconfig | configure a network interface | 查看/配置计算机当前的网卡配置信息 |
02 | ping ip地址 | ping | 检测到目标ip地址 的链接时否正常 |
网卡和ip
网卡
- 网卡是一个专门负责网络通讯的硬件设备
- IP 地址是设置在网卡上的地址信息
我们可以把 电脑 比作 电话,网卡 相当于 SIM 卡,IP 地址 相当于 电话号码。IP 地址
- 每台电脑上都有 IP 地址,是保证电脑之间正常通讯的重要设置
注:每台电脑的IP 不能相同,否则会出现IP地址冲突,并且没办法保证正常通讯
ifconfig
可以查看/配置计算机当前的网卡配置信息
例如: ifconfig 查看网卡配置信息
ifconfig | grep inet 查看网卡对应的 IP 地址
提示:一个电脑可能有一个物理网卡和多个虚拟网卡,在Linux中物理网卡的名字通常以 ensXX表示
ping
ping IP地址 检测到目标主机是否连接正常
ping 127.0.0.1 检测本地网卡工作正常
ping 一般用于检测当前计算机到目标计算机之间的网络 是否畅通,数值越大,速度越慢
- ping 的工作原理与潜水艇的声納很相似,ping 这个命令曲子 声納的声音
- 网络管理员也常将ping 用作动词, --ping 一下计算机X,看他是否开着
提示:在Linux中,想要终止一个终端,绝大多数都可以使用 ctrl+c
3.3 远程登录和赋值文件
序号 | 命令 | 对应英文 | 作用 |
---|---|---|---|
01 | ssh 用户名@ip | secure shell | 关机/重新启动 |
02 | scp 用户名@ip:文件名或路径 用户名@ip:文件名或路径 | secure copy | 远程复制文件 |
ssh 基础(重点)
- Linux 中SSH 是非常常用的公式,通过SSH客户端我们可以连接运行SSH服务器 的远程机器上
数据是 加密 压缩 的,保证安全和高速。
域名和端口号
域名:
- 由一串 用点分割 的名族组成 www.itcase.cn
- 是IP的别名,方便用户记忆
端口号:
1.IP地址:通过 IP地址 找到网络上的 计算机
2.端口号:通过 端口号 可以找到 计算机上运行的应用程序
3.常用服务端口号列表:
序号 | 服务 | 端口号 |
---|---|---|
01 | SSH 服务器 | 22 |
02 | Web服务器 | 80 |
03 | HTTPS | 443 |
04 | FTP服务器 | 21 |
提示:有关端号 的详细内容。
SSH 客户端简单使用
- ssh [-p port] user@remote
user:远程机器上的用户名,如果不指定的话 默认 当前用户名
remote:远程机器的地址,可以是IP/域名,或者是后面提到的别名
prot:是SSH Server 接听的端口,如果不指定,就是默认22
提示:使用 exit 退出当前用户的登录
注:
ssh 这个终端命令只能在Linux或者UNIX系统使用
如果在Windows系统中,可以用PuTTY,或者XShell 客户端软件即可
在工作中,SSH服务器的端口号可能不是22,需要-p指定,否则无法正确链接。
scp
Linux远程拷贝文件的命令
他的地址格式与ssh基本相同,需要注意的是,指定端口时是大学的P -P
例如:
- 把本地01.py复制到远程桌面下
scp -P port 01.py user@remote:Desktop/01.py- 把远程 家目录下的 Desktop/01.py 文件 复制到 本地当前目录下的 01.py
scp -P user@remote:Desktop/01.py 01.py
-r 若给出的源文件是目录文件,则scp 将递归复制该目录下的所有子目录和文件,文件必须是一个目录名
-P 若远程端口号不是22,则需要使用大些字母 -P 选项指定端口。
SSH高级
免密码登录
配置别名
提示:有关SSH配置信息都保存在用户家目录下的.ssh目录下
免密码登录:
配置公钥
- 执行 ssh-keygeb 即可生成钥匙,一路回车即可
上传公钥到服务器 - 执行ssh-copy-id -p port user@remote,可以让远程服务器记录我们的公钥
配置别名
每次输入 ssh -p port user@remote,时间久了会觉得麻烦
配置别名可以让我们进一步偷懒,譬如用:ssh mac来代替上面这么一长串,那么就在 ~/.ssh/config 里面追加一下内容:
Host mac
HostName ip地址
User user
Port 22
保存之后即可使用。
3.4 用户权限基本概念
基本概念
- 用户是Linux 系统工作中重要的一环,用户管理包括 用户 与 组 管理。
- 在Linux系统中,不论是本地还是远程登录系统,每个系统都有一个账号,并且对于不同的系统拥有不同的使用权限
- 在Linux中可以指定 每一个用户 针对 不同文件或目录 的不同权限。
- 对文件的权限包括
序号 | 权限 | 英文 | 缩写 | 数字代号 |
---|---|---|---|---|
01 | 读 | read | r | 4 |
02 | 写 | write | w | 2 |
03 | 执行 | excute | x | 1 |
组
为了方便管理用户,提出组的概念
在实际应用中,可以预先针对 组 设置好权限,然后 将不同用户添加到对应的组中,从而不用依次为每个瀛湖设置权限
chmod
chmod 可以修改 用户 /组 对 文件/目录 的权限
chmod +/-rwx 文件名|目录
eg:chmod +x 01.py
目录如果没有可执行权限,将不能执行终端命令,例如ls cd 等。
3.4.1超级用户
- Linux系统中root账号通常 用于系统的维护和管理,对象系统的所有资源具有所有访问权限
- 在大多数版本的Linux中,都不推荐 直接使用root账号登录系统。
- 在Linux安装过程中,系统会自动创建一个用户账号,而这个默认的用户就是标准用户。
sudo
su 是substitute user的缩写,表示 使用另一个用户的身份。
sudo 命令用来以其他身份来执行命令,预设的身份为root
用户使用sudo时,必须先输入密码,之后5分钟的有效期限,超过期限时必须重新输入密码。 - 若其未经过授权的用户企图使用sudo,则会发出警告邮件给管理员。
组管理 终端令
- 提示,创建/删除组的终端命令都是需要通过sudo执行
序号 | 命令 | 作用 |
---|---|---|
01 | groupadd 组名 | 添加组 |
02 | groupdel 组名 | 删除组 |
03 | cat /etc/group | 确认组信息 |
04 | chgrp 组名 文件/目录名 | 修改文件/目录的所属组 |
提示:
- 组信息保存在/etc/group 文件中
- /etc 目录是专门用来保存系统配置信息的目录
- 在实际应用中,可以预先针对组设置好权限,然后将不同的用户添加到对应的组中,从而不用依次为每一个用户设置权限
mkdir Python学习 #创建 Python学习 目录
sudo groupadd dev #创建组dev
cat /etc/group #查看确定组是否被创建
sudo chgrp -R dev Python学习 #将 目录的组修改为 dev。
用户管理 终端令
提示:创建用户/删除用户/修改其他用户的密码的中断命令都需要通过sudo执行。
创建用户/设置密码/删除用户
序号 | 命令 | 作用 | 说明 |
---|---|---|---|
01 | usered -m -g 组 新建用户名 | 添加新用户 | -m 自动创建用户家目录 -g指定用户所在的组,否则会创建一个和同名的组 |
02 | passwd 用户名 | 设置用户密码 | 如果是普通用户,直接用passwd可以修改自己的账号密码 |
03 | userdel -r 用户名 | 删除用户 | -r 选项会自动删除用户的家目录 |
04 | cat /etc/passwd | grep 用户名 | 确认用户信息 | 新建用户后,用户信息会保存在/etc/passwd 文件中 |
提示:
- 创建用户时,如果忘记添加 -m 选项指定新用户的家目录–最简单的方法是删除用户,重新创建
- 创建用户时,默认会创建一个和用户名同名的组名
- 用户信息保存在/etc/passwd文件中
查看用户id
序号 | 命令 | 作用 |
---|---|---|
01 | id [用户名] | 查看用户UID和GID信息 |
02 | who | 查看当前所有登录的用户列表 |
03 | whoami | 查看当前登录用户的账户名 |
paswd文件
- /etc/passwd 文件存放的是用户的信息,由6个分号组成的7个信息,分别是:
- 用户名
- 密码(x,表示加密的密码)
- UID(用户标识)
- GID(组表示)
- 用户全名或者本地账号
- 家目录
- 登录使用的shell,就是登录之后,使用的终端命令,ubuntu默认 dash
usermod
- usermod 可以用来设置用户的主组/附加组和登录shell,命令合适如下:
- 主组:通常在创建用户时指定,在 /etc/passwd的第4列GID对应的组
- 附加组:在etc/group中最后一列表示该组的用户列表,用于指定用户的附加权限
提示:设置了用户的附加组之后,需要重新登录才能生效!
# 修改用户的主组 (passwd中的GID)
usermod -g 组 用户名
# 修改用户的附加组
usermod -G 组 用户名
# 修改用户登录 Shell
usermod -s /bin/bash
**注意:**默认使用useradd添加的用户是没有全线使用sudo以root身份执行命令的,可以使用一下命令,将用户添加到sudo附加组中
usermod -G sudo 用户名
etc 目录是专门用来保存与系统相关的目录。
which(重要)
- etc/passwd 是用于保存用户信息的文件
- /user/bin/passwd 是用于修改用户密码的程序
- which命令可以查看执行命令所在的位置,例如:
which ls
# 输出
# /bin/ls
which useradd
# 输出
# /user/sbin/useradd
bin和sbin
- 在Linux中,绝大多数可执行文件都保存在/bin、/sbin、/usr/bin、/usr/sbin
- /bin(binary)是二进制执行文件目录,主要用于具体应用
- /sbin(system binary)是系统管理员专用的二进制代码存放目录,主要用于系统管理
- /usr/bin 后期安装的一些软件
- /usr/sbin 超级用户的一些管理程序
提示:cd 这个终端命令是内置在系统内核中的,没有独立文件,which无法找
切换用户
序号 | 命令 | 作用 | 说明 |
---|---|---|---|
01 | su - 用户名 | 切换用户,并且切换目录 | -可以切换到用户家目录,否则保持位置不变 |
02 | exit | 退出当前登录账号 |
注su 不接用户,可以切换到root,但不推荐使用,因为不安全
修改文件权限
序号 | 命令 | 作用 |
---|---|---|
01 | chown | 修改拥有者 |
02 | chgrp | 修改组 |
03 | chmod | 修改权限 |
命令格式
# 修改文件|目录的拥有者
chown 用户名 文件名|目录名
# 递归修改文件|目录的组
chgrp -R 组名 文件名|目录名
# 递归修改文件权限
chmod -R 755 文件名|目录名
chmod在设置权限时,可以简单地使用三个数字分别对应拥有者/组和其他用户的权限
权限 拥有者,组,其他
4.系统信息相关命令
系统日期和时间,磁盘占用情况,程序执行情况。
#时间和日期
date cal
#磁盘和目录空间
df du
#进程信息
ps top kill
4.1时间和日期
序号 | 命令 | 作用 |
---|---|---|
01 | cal | 查看日历,-y选项可以查看一年的日历 |
02 | date | 查看系统时间 |
4.2磁盘信息
序号 | 命令 | 作用 |
---|---|---|
01 | df -h | disk free 显示磁盘剩余空间 |
02 | du -h [目录名] | disk usage 显示目录下的文件大小 |
选项说明:参数-h,以人性化的方式显示文件大小
4.3进程信息
所谓进程,通俗地说就是当前正在执行的一个程序
序号 | 命令 | 作用 |
---|---|---|
01 | ps aux | process status 查看进程的详细状况 |
02 | top | 动态显示运行中的进程并且排序 |
03 | kill [-9] 进程代号 | 终止指定代号的进行,-9代表强制终止 |
注意: ps 默认只会显示当前用户通过终端启动的应用程序
选项 | 含义 |
---|---|
a | 显示终端上的所有进程,包括其他用户的进程 |
u | 显示进程的详细信息状态 |
x | 显示没有控制终端的进程 |
提示: 使用kill命令时,最好只终止由当前用户开启的进程,而不要终止root身份开启的进程,否则可能导致系统崩溃。
- top显示 :进程代号,启动命令代号,cpu,内存占用率,时间,命令
- 要退出 top 可以直接输入q
- top -H -p 进程id 查看各进程 占有率
4.4 其他命令
- 查找文件 find
- 软连接 ln
- 打包和压缩 tar
- 软件安装 apt-get
查找文件
find 命令是功能非常强大,通常用来在特定的目录下 所搜符合条件的文件
- find [路径] -name “.py” 查找指定路径下扩展名为.py的文件,包括子目录
- 如果省略路径,则在当前文件中查找
- 之前学习的通配符,在使用find命令时同时可用(* ? 等)
软链接
- ln -s 被链接的源文件,链接文件
注意:
- 没有 -s 选项建立的是一个硬链接文件
没有文件占用相同大小的硬盘空间,工作中几乎不会建立文件的硬链接 - 源文件要使用绝对路径,不能使用相对路径,这样可以方便移动链接文件后,仍然可以使用。
文件软硬链接的示意图
在Linux中,文件名和文件数据是分开存储的。
删除文件名后,软链接不能访问数据,硬链接可以。
1.在Linux中,只有文件的 硬链接数==0 才会被删除
2.使用ls -l 可以查看一个文件的硬链接的数量
3.在日常工作中,几乎不会建立文件的硬链接
打包压缩
在不同的操作系统中,打包压缩的方式是不同的
- windows 常用 rar
- Mac 常用 zip
- Linux 常用 tar.gz
打包/解包
tar 是Linux 中最常用的备份工具,此命令可以把一系列文件打包到一个大文件中,也可以把一个打包的大文件恢复成一系列文件
tar的命令格式如下:
# 打包文件
tar -cvf 打包文件.tar 被打包的文件/路径...
# 解包文件
tar -xvf 打包文件.tar
tar选项说明:
选项 | 含义 |
---|---|
c | 生成档案文件,创建打包文件 |
x | 解开档案文件 |
v | 列出归档接档的详细过程,显示进度 |
f | 指定档案文件名称,f后面一定是 .tar 文件,所以必须放选项后面 |
注意:f 选项必须放在后面,其他选项顺序可以随意
压缩/解压缩
gzip
tar 与 gzip 命令结合可以实现文件打包和压缩
tar只负责打包,但不负责压缩
用gzip压缩tar打包后的文件,其扩展名为 xxx.tar.gz
在Linux中,最常见的压缩文件格式就是 xxx.tar.gz
命令格式如下:
# 压缩文件
tar -zcvf 打包文件.tar.gz 被压缩的文件/路径...
# 解压缩文件
tar -zxvf 打包文件.tar.gz
# 解压缩到指定路径
tar -zxvf 打包文件.tar.gz -C 目标路径
选项 | 含义 |
---|---|
-C | 解压缩到指定目标,注意:要解压缩的目录必须存在 |
bzip2(two)
- tar与bzip2命令结合可以使用实现文件打包和压缩(用法和gzip一样)
tar只负责打包文件,但不压缩
用bzip2压缩tar打包后的文件,其扩展名一般用 xxx.tar.bz2
- 在tar命令中有一个选项-j可以调用bzip2,从而可以方便的实现压缩和解压缩的功能
# 压缩文件
tar -jcvf 打包文件.tar.bz2 被压缩的文件/路径...
#解压缩文件
tar -jxvf 打包文件.tar.bz2
软件安装
通过apt安装/卸载文件
- apt是 Advanced Packaging Tool,是Linux下的一款安装包管理工具
- 可以在终端中方便地安装/卸载/更新软件包
# 1.安装软件
sudo apt install 软件包
# 2.卸载软件
sudo apt remove 软件包
# 3.更新已安装的包
sudo apt upgrade
例如:
sudo apt install sl #一个小火车提示
二、Python 简介
1.Python 科普
- python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。
- Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构。
- Python 是一种解释型语言: 这意味着开发过程中没有了编译这个环节。类似于PHP和Perl语言。
- Python 是交互式语言: 这意味着,您可以在一个 Python 提示符 >>> 后直接执行代码。
- Python 是面向对象语言: 这意味着Python支持面向对象的风格或代码封装在对象的编程技术。
- Python 是初学者的语言:Python 对初级程序员而言,是一种伟大的语言,它支持广泛的应用程序开发,从简单的文字处理到 WWW 浏览器再到游戏。
解释型语言
- 编译型语言->编译器->最终可执行文件-》操作系统
解释型语言->解释器-》操作系统 - 编译型语言:程序在执行之前需要一个专门的编译过程,把程序编译成为机器语言的文件,运行时不需要重新翻译,直接使用编译的结果就行了。程序执行效率高,依赖编译器,跨平台性差,如C,c++。
解释型语言:编写时不进行预先编译,以文本方式存储程序代码,会将代码一句一句直接运行。在发布程序时,看起来省了编译工作,但运行程序的时候,必须先解释在运行。 - 速度:编译型语言块
跨平台:解释型语言跨平台好
Python 设计目标
简单直观的语言,开源,像纯英语那样容易理解,适用于短期开发的日常任务。
Python 设计哲学
优雅,明确,简单
用一种方法,最好是只有一种来做一件事
明确没有或者很少有歧义的语法
为什么使用Python
代码量比较少
Python 特点
面向对象的思维方式
Python是完全面向对象的语言
- 函数、模块、数字、字符串都是对象,在Python中一切皆对象
- 完全支持继承、重载、多重继承
- 支持重载运算符,也支持泛型设计
Python拥有一个强大的标准库,Python语言的核心只包含数字、字符串、列表、字典等常见类型和函数,而且由Python标准库提供了系统管理、网络通讯、文本处理、数据库接口、图形系统、XML处理等额外的功能。
Python社区提供了大量的第三方模块,使用方式与标准库类似,他们的功能是覆盖科学计算、人工智能、机器人学习、Web开发、图形系统等多个领域。
优缺点
- 简单 ,易学,免费开源,高层语言,可移植性,解释性,面向对象,可扩展性,丰富的库,规范的代码。
可扩展性:不公开打吗可以用c,c++实现,然后在Python程序中使用他们。
缺点:运行速度,国内视场小,中文资料少,有速度要求改C++,架构选择少。
2.第一个Python 程序
执行Python的三种方式:
- 解释器–Python/Python3
- 交互式–ipython
- 集成开发环境–Pycharm
2.1第一个helloPython程序
Python源程序就是一个特殊格式的文本文件,可以使用任意文本编译软件做Python的开发
Python程序的文件扩展名通常用 .py
1.新建 01-helloPython.py文件
2.用gedit编辑,并输入
print("hello python")
print("hello world")
3.执行
python 01-helloPython.py
说明: print是的作用是把”“内部的内容输出到屏幕上
bug:程序不能执行,执行结果不是我们期望的
常见错误:
1.手误 print 写成printf
报错:NameError :name ‘printf’ is not defined
2.将多条print写到一行
报错:SyntaxError:invalid syntax
每行代码负责完成一个动作
3.缩进错误
报错:IndentationError:unexpected indent
python是一个格式非常严格的程序设计语言
Python 2.x 默认不支持中文
目前市面上只有两个Python的版本并存,分别为Python 2.x 和Python 3.x
Python 2.x 默认不支持中文,
Python 2.x 的解释器名称为 python
Python 3.x 的解释器名称为 python3
ASCII 字符只包含256个字符,不支持中文
Python 3.x 支持中文,终点集中到3.0版本上
Python 中文编码
#!/usr/bin/python
print "你好,世界";
Python中默认的编码格式是 ASCII 格式,在没修改编码格式时无法正确打印汉字,所以在读取中文时会报错。
解决方法为只要在文件开头加入 # -- coding: UTF-8 -- 或者 #coding=utf-8 就行了
注意:#coding=utf-8 的 = 号两边不要空格。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
print("你好,世界");
注意:Python3.X 源码文件默认使用utf-8编码,所以可以正常解析中文,无需指定 UTF-8 编码。如果你使用编辑器,同时需要设置 py 文件存储的格式为 UTF-8,否则会出现类似以下错误信息:
2.2 执行Python程序的三种方式
解释器
Python解释器
# 使用 2.0
python xxx.py
# 使用 3.0
python3 xxx.py
其他解释器
CPython – 官方版本的C语言实现
Jython – 可以运行在java 平台
交互式Python程序
直接在终端中运行解释器,而不输入要执行的文件名
在Python的Shell 中直接输入Python的代阿凯码,会立即蓝岛程序执行的结果
交互式运行Python的优缺点
优:适合学习,验证Python语法或者局部代码
缺:代码不能保存,不适合太大的程序
官方Python 2.x 3.x
打开交互式Python
终端输入 python
退出 官方的解释器
1.直接输入 exit()
2.直接使用快捷键 ctrl+d
IPython
IPython 是一个Python的交互式Shell,比默认的好的多
支持自动补全、自动锁紧、支持bash shell命令、内置了很多有用的功能和函数
ipython、ipython3
退出输入exit()
直接使用热键 ctrl+d
Pycharm
pycharm中出现Process finished with exit code 0代表程序执行完成
- PyCharm 是由 JetBrains 打造的一款 Python IDE,支持 macOS、 Windows、 Linux 系统。
- PyCharm 功能 : 调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制……
- PyCharm 下载地址
- PyCharm 安装地址
特点:
1.图形用户界面
2. 代码编辑器(支持代码补全与缩进)
3. 编辑器/解释器
4. 调试器(断电/单步执行)
…
执行 shift+F10
调试 shift+F9
2.3 Pycharm
在配置界面,可以通过 Editor colors and fonts 选择 编辑器的配色方案
Pycharm的初始设置
pycharm 的配置信息是保存在用户目录下的 .Pycharmxxx.x 目录下的,xxx.x表示当前使用pycharm的版本号
如果要恢复pycharm的初始设置,可以按照以下步骤进行:
- 关闭正在运行的Pycharm
- 在终端中执行一下终端命令,删除Pycharm的配置信息目录
rm -r ~/.Pycharm2016.3 - 重启Pycharm
打开新建一个Python项目
项目简介
- 开发项目就是开发一个专门解决一个复杂业务功能的软件
- 通常每一个项目就是一个独立专属的目录,用于保存所有和项目相关的文件
一个项目通常会包含很多源文件
打开Python项目
- 直接点击open按钮,然后浏览到之前保存Python文件的目录,即可以打开项目
- 打开之后,会在目录下新建一个 .idea 的目录,用于保存项目的相关信息,例如:解释器版本,项目包含的文件等
- 第一次打开项目时,要耐心等待pycharm 对项目进行初始化
- 对.py文件右键,选择执行按钮,即可执行
设置项目使用的解释器版本
1.打开的目录不是有pycharm建立的项目目录,有时候使用的解释器时Python2.x的,需要单独设置解释器的版本
通过file->setting…可以打开设置窗口
设置字体等
通过file->setting->editor … Font可以设置字体的显示
下载安装
- 下载–官网有免费版本
- 安装-- 将解压后的目录移动到/opt目录下,方便其他用户使用
- /opt 目录用户存放给主机额外安装的软件
- 启动–bin 目录下的./pycharm.sh
- 卸载–删除文件和配置
注意:/usr/share/applications/下的桌面快捷方式
设置专业版启动图标
在专业版中,选择菜单Tool/create Desktop Entry …
注:设置图标时,勾选 create the entry for all users
3. Python基础
3.0 Python 基本信息
保留字符
下面的列表显示了在Python中的保留字。这些保留字不能用作常数或变数,或任何其他标识符名称。所有 Python 的关键字只包含小写字母。
and exec not
assert finally or
break for pass
class from print
continue global raise
def if return
del import try
elif in while
else is with
except lambda yield
Python多行语句
Python语句中一般以新行作为语句的结束符。
但是我们可以使用斜杠( \)将一行的语句分为多行显示,如下所示:
total = item_one + \
item_two + \
item_three
语句中包含 [], {} 或 () 括号就不需要使用多行连接符。如下实例:
days = ['Monday', 'Tuesday', 'Wednesday',
'Thursday', 'Friday']
引号
- Python 可以使用引号( ’ )、双引号( " )、三引号( ‘’’ 或 “”" ) 来表示字符串,引号的开始与结束必须的相同类型的。
- 其中三引号可以由多行组成,编写多行文本的快捷语法,常用于文档字符串,在文件的特定地点,被当做注释。
sentence = "这是一个句子。"
paragraph = """这是一个段落。
包含了多个语句"""
Python同一行显示多条语句
Python可以在同一行中使用多条语句,语句之间使用分号(;)分割,以下是一个简单的实例:
#!/usr/bin/python
import sys; x = 'runoob'; sys.stdout.write(x + '\n')
3.1 多个文件
- 在该项目中建立新的Python文件,要想让哪一个Python程序能够执行,必须首先通过鼠标右键的方式执行一下
- 对于初学这而言,一个项目中多个执行文件很方便
- 对于商业项目而言,通常在一个项目中,只有一个可以直接执行的Python源程序
3.2.注释
注释的作用:使用用自己熟悉的语言,在程序中对某些代码进行注释说明,增强代码的可读性
单行注释
- 以 # 开头,#右边的所有东西都被当做说明,而不是真正要执行的程序,只起到辅助说明的作用。
为保证代码的可读性,#后面建议先添加一个空格,然后再编写相应的说文字 - 在代码后面增加单行注释
在程序开发时,同样可以使用#在代码的后面(旁边)增加说明性文字,但是,需要注意的是,为保证代码的可靠性,注释和代码之间至少有两个空格。
多行注释
3. 如果希望编写的注释信息很多,一行无法显示,就可以使用多行注释
4. 要在python程序中使用多行注释,可以用一对连续的三个引号(单引号和双引号都可以)
5. 注释不是越多越好
3.3 算术运算符
算术运算符是运算符的一种
运算符 | 描述 | 实例 |
---|---|---|
+ | 加 | 2+2=4 |
- | 减 | 4-2 =2 |
* | 乘 | 2*2=4 |
/ | 除 | 4/2=2 |
// | 取整除 | 9// 4 =2 |
% | 取余 | 9%2=1 |
** | 幂 | 2 ** 3 =8 |
在Python中 * 运算符还可以用于字符串,计算结果就是字符串重复指定次数的结果
IN: "-" * 10
OUT: ----------
先乘除后加减,从左到右, ()提高优先级
高低顺序为:**,* / % // ,+ -
3.4 计算机中的三大件
- CPU
中央处理器,超大规模的集成电路
负责处理数据/计算 - 内存
临时存储数据,断电后数据会消失
速度块,空间小(单价高) - 硬盘
永久存储数据,速度慢,空间大(价格低)
程序执行原理
- 程序运行前,程序是保存在硬盘中的
- 当要运行一个程序时
操作系统会首先让CPU把程序复制到内存中
CPU执行内存中的程序代码
即:程序执行前,首先要被加载到内存
Python程序的执行原理
- 操作系统首先让CPU把 Python解释器 的程序复制到内存中
- Python解释器 根据语法规则,从上向下让CPU翻译Python程序中的代码
- CPU负责执行翻译完成的代码
3.5 变量的基本使用
程序是用来处理数据的,而变量是用来存储数据的
变量定义
在Python中,每个变量在使用前必须赋值,变量赋值以后才会被创建
等号(=)用来给变量赋值
= 变量左边是一个变量名
= 右边是存储在变量的值
变量 = 值
变量定义之后,后续就可以直接使用了
在交互式方式,如果要查看变量内容,直接输入变量名即可,不需要使用print函数
使用解释器执行,如果要输出变量的内容,必须要使用print函数
- 变量名只有在第一次出现才是定义变量
- 变量名再次出现时,不是定义变量而是直接使用前面使用过的变量
在程序开发中,可以修改之前定义变量中保存的值
变量的类型
在内存中创建一个变量包括:
1.变量的名称
2.变量保存的数据
3.变量存储数据的类型
4.变量的地址(标识)
类型
- int 整形
- bool 布尔
- str 字符串
- float 标识小数类型(浮点数)
- complex 复数型 科学计算
- 列表 [ ]
- 元组 ()
- 字典 {:}
Python不需要指定类型,解释器可以根据=右侧的值,自动推断出变量存储数据的类型
使用type函数可以查看一个变量的类型
变量的计算
python 2.x中,整数根据保存数值的长度还分为:int(整型),long(长整型)
python 3.x中,只有int。
- 字符之间直接计算(bool True 1,False 0,可参与计算)
- 字符串之间 + 拼接生成新的字符串
- 可以和整数使用 * 重复拼接相同的字符串
- 数字型变量和字符串之间 不能进行其他计算
变量的输入
- 所谓的输入,就是用代码获取用户通过键盘输入的信息
- 在Python中,如果要获得用户在键盘上的输入信息,需要用到input函数
关于函数
- 一个提前准备好的功能(别人或自己写的代码),可以直接使用,而不用关心内部的细节
已经涉及到的函数:print(x) ,type(x)
intput 函数实现键盘输入
- 用户输入的任何内容python都认为是一个字符串
- 语法如下:
字符变量 = input(“提示信息:”)
类型转换函数
函数 | 说明 |
---|---|
int(x) | 将x转化为一个整型 |
float(x) | 将x转化为一个浮点数 |
变量的格式化输出
- 在Python中可以使用print函数将信息输出到控制台上
- 如果希望输出文字的同时一起输出数量,就需要使用到格式化操作符
- %被成为格式化操作符,专门用于处理字符串的格式:
- 包含%的字符串,被称为格式化字符串
- %和不同的字符连用,不同类型的数据需要使用不同的格式话字符
格式化字符 | 含义 |
---|---|
%s | 字符串 |
%d | 有符号十进制整数,%06d表示输出整数显示的位数,不足的地方补零 |
%f | 浮点数,%.02f表示小数点后面只显示两位 |
%% | 输出% |
语法格式如下:
print(“格式化字符串” % 变量1)
print(“格式化字符串” % (变量1 变量2))
name = "大名11"
print("我的名字叫 %s,请多多关照"% name)
变量命名
标识符和关键字
标识符
- 标识符:就是程序员定义的变量名,函数名
- 名字需要有见名知意的作用
- 标识符可以有字母,下划线和数字组成
- 不能以数字开头,不能与关键字重名
关键字
- 关键字:就是Python内部已经使用的标识符
- 关键字具有特殊的功能和意义
- 开发者不允许定义和关键字相同名字的标识符
- import 关键字可以导入一个工具包
- 在Python中不同的工具包,提供不同的工具
变量的命名规则
命名规则可以视为一种惯例,并无绝对和强制
目的是为了增加代码的识别和可读性
注意:Python 中区分大小写
- 在定义变量时,为保证代码的格式, = 的左右应该各保留一个空格
- 在Python中,如果变量名需要由两个或者多个单词组成,可以按照下列方式命名
每个单词都使用小写字母
单词之间使用下划线链接 - 还可以使用驼峰命名法
小驼峰:第一个单词以小写字母开始,后续单词的首字母大些
大驼峰:每个单词的首字母都大写
3.51 字典
- 字典是另一种可变容器模型,且可存储任意类型对象。
- 字典的每个键值 key=>value 对用冒号 : 分割,每个对之间用逗号(,)分割,整个字典包括在花括号 {} 中 ,格式如下所示: d = {key1 : value1, key2 : value2, key3 : value3 }
- 键必须是唯一的,但值则不必。
- 值可以取任何数据类型,但键必须是不可变的,如字符串,数字
访问:
#!/usr/bin/python3
dict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
print ("dict['Name']: ", dict['Name'])
print ("dict['Age']: ", dict['Age'])
修改:
#!/usr/bin/python3
dict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
dict['Age'] = 8 # 更新 Age
dict['School'] = "菜鸟教程" # 添加信息
删除:
能删单一的元素也能清空字典,清空只需一项操作。
#!/usr/bin/python3
dict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
del dict['Name'] # 删除键 'Name'
dict.clear() # 清空字典
del dict # 删除字典
其他方法:
len(dict)
str(dict) 输出字典,以可打印的字符串表示。
type(variable) 返回输入的变量类型,如果变量是字典就返回字典类型。
是否在字典里:
key in dict
#!/usr/bin/python3
dict = {'Name': 'Runoob', 'Age': 7}
# 检测键 Age 是否存在
if 'Age' in dict:
print("键 Age 存在")
else :
print("键 Age 不存在")
# not in
# 检测键 Age 是否存在
if 'Age' not in dict:
print("键 Age 不存在")
else :
print("键 Age 存在")
添加元素到字典:
1.、直接添加,给定键值对
2、使用update方法
aa = {'人才':60,'英语':'english','adress':'here'}
print(aa) # {'人才': 60, '英语': 'english', 'adress': 'there'}
#添加方法一:根据键值对添加
aa['价格'] = 100
#添加方法二:使用update方法添加
xx = {'hhh':'gogogo'}
aa.update(xx)
遍历元素:
- 遍历key值
在使用上,for key in a和 for key in a.keys():完全等价。
a = {‘a’: ‘1’, ‘b’: ‘2’, ‘c’: ‘3’}
for key in a:
print(key+’:’+a[key])
out: a:1 b:2 c:3 - 遍历value值
for value in a.values():
print(value)
out: 1 2 3 - 遍历字典项
for kv in a.items():
print(kv)
out:(‘a’, ‘1’) (‘b’, ‘2’) (‘c’, ‘3’) - 遍历字典健值
for key,value in a.items():
print(key+’:’+value)
或:
for key,value in a.items():
print(key+’:’+value)
out: a:1 b:2 c:3
3.52 字符串
截取
- Python 访问子字符串,可以使用方括号 [] 来截取字符串,字符串的截取的语法格式如下:
变量[头下标:尾下标] - 索引值以 0 为开始值,-1 为从末尾的开始位置。
Python转义字符
转义字符 | 描述 | 实例 |
---|---|---|
\在行尾时 | 续行符 | print(“line1 …line3”) |
\\ | 反斜杠符号 | print("\\") |
\b | 退格(Backspace) | print("\\") |
字符串运算符
描述符 | 描述 |
---|---|
+ | 字符串相加 |
* | 重复输出字符串 |
[] | 通过索引获取字符串中字符 |
[:] | 截取,左闭右开 |
in | 成员运算符,字符串中包含指定字符 |
not in | 成员运算符,字符串中不包含指定字符 |
% | 格式字符串 |
3.53 列表
- 列表都可以进行的操作包括索引,切片,加,乘,检查成员。
列表是最常用的 Python 数据类型,它可以作为一个方括号内的逗号分隔值出现。 - [:] 剪切
- [] 取值
- [[],[]] 嵌套列表
操作符
表达式 | 结果 | 描述 |
---|---|---|
len([1, 2, 3]) | 3 | 长度 |
[1,2,3]+[4,5,6] | [1,2,3,4,5,6] | 组合 |
[‘Hi!’] * 4 | [‘Hi!’,‘Hi!’,‘Hi!’,‘Hi!’] | 重复 |
3 in [1, 2, 3] | True | 元素是否存在于列表 |
for x in [1, 2, 3]: print(x, end=" ") | 1 2 3 | 迭代 |
删除列表元素
#!/usr/bin/python3
list = ['Google', 'Runoob', 1997, 2000]
print ("原始列表 : ", list)
del list[2]
print ("删除第三个元素 : ", list)
Python列表函数&方法
函数 | 功能 |
---|---|
list.append(obj) | 在列表末尾添加新的对象 |
list.count(obj) | 统计某个元素在列表中出现的次数 |
list.extend(seq) | 在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表) |
list.index(obj) | 从列表中找出某个值第一个匹配项的索引位置 |
list.insert(index, obj) | 将对象插入列表 |
list.pop([index=-1]) | 移除列表中的一个元素(默认最后一个元素),并且返回该元素的值 |
list.remove(obj) | 移除列表中某个值的第一个匹配项 |
list.reverse() | 反向列表元素 |
list.sort( key=None, reverse=False) | 对原列表进行排序 |
list.clear() | 清空列表 |
list.copy()|复制列表| |
3.6 语句
运算符
比较运算符
比较运算符 | 含义 |
---|---|
== | |
!= | |
> | |
< | |
>= | |
<= |
在Python 2.x中,不等于还可以使用 <> 运算符
逻辑运算符
逻辑运算符可以把多个条件按照逻辑进行连接,变成更复杂的条件
Python中逻辑运算符 与 and/ 或 or/ 非 not 三种
赋值运算符
赋值运算符中间不能有空格
操作符 | 描述 | 实例 |
---|---|---|
= | ||
+= | ||
-= | ||
*= | ||
= | ||
/= | 整除等于 | |
%= | 取余等于 | |
**= | 幂赋值等于 |
Python中计数方法
自然计数法:从1开始
程序计数法:从0开始
除非有特殊要求,一般计数都从0开始
3.61 判断(if)语句
- 判断的定义:
如果条件满足,才做某件事
如果条件不满足,就做另一件事或者什么也不做 - 判断语句又被称为分支语句
Python中,if语句用来进行判断,格式如下:
if 条件1:
条件1成立时,要做的事
....
elif 条件2:
条件2满足时执行
...
else:
条件不满足时,要做的事
...
if 和 else 语句以及各自的缩进部分共同是一个 完成的代码块
注意:代码的缩进为一个tab键,或者4个空格–建议使用空格
在Python中,tab和空格不要混用
3.62 循环
while
- Python 中的循环语句有 for 和 while。
程序的三大流程:
- 顺序–自上而下
- 分之–条件判断
- 循环–让特定代码重复执行
在Python中构造循环结构有两种做法,一种是for-in循环,一种是while循环。
while 语句的基本语法:
初始条件设置–通常是重复执行的计数器
while 条件(判断 计数 是否达到 目标次数):
条件满足时,做事件1
条件满足时,做事件2
....
处理条件(计数器+1)
while语句以及缩进部分是一个完整的代码块
死循环:由于程序员的原因,忘记修改循环的判断条件,导致循环持续执行,无法终止。
例如:
result = 0
i = 0
while i<=3:
print(i)
result += i
i += 1
while循环嵌套
循环嵌套
while 嵌套就是:while里面还有while
while 条件1:
条件满足时,做事件1
条件满足时,作条件2
...
while 条件2:
条件满足时,做事件1
条件满足时,做事件2
...
处理条件2
处理条件1
while 循环使用 else 语句
如果 while 后面的条件语句为 false 时,则执行 else 的语句块。
while <expr>:
<statement(s)>
else:
<additional_statement(s)>
循环 -for-in循环
- Python for 循环可以遍历任何可迭代对象,如一个列表或者一个字符串。
- 如果明确的知道循环执行的次数或者要对一个容器进行迭代(后面会讲到),那么我们推荐使用for-in循环.
例如: 计算1~100求和的结果( ∑ n = 1 100 n \displaystyle \sum \limits_{n=1}^{100}n n=1∑100n)。
sum = 0
for x in range(101):
sum += x
print(sum)
如果你需要遍历数字序列,可以使用内置range()函数。它会生成数列
- 需要说明的是上面代码中的range类型,range可以用来产生一个不变的数值序列,而且这个序列通常都是用在循环中的,例如:
- range(101)可以产生一个0到100的整数序列。
- range(1, 100)可以产生一个1到99的整数序列。
- range(1, 100, 2)可以产生一个1到99的奇数序列,其中的2是步长,即数值序列的增量。
我们可以用下面的代码来实现1~100之间的偶数求和。
sum = 0
for x in range(2, 101, 2):
sum += x
print(sum)
break和continue
break和continue是专门在循环中使用的关键字
break第一条件满足时,退出循环,不在执行后续重复的代码
continue 第一条件满足时,不执行后续重复的代码
break和continue只针对当前所在循环有效
3.7 函数基础
所谓函数,就是把具有独立功能的代码块组织为一个小模块,在需要的时候调用
函数的使用包含两个步骤:
1.定义函数 --封装独立的功能
2.调用函数 --享受封装的成果
函数的作用,在开发程序时,使用函数可以提高编写的效率以及代码的重用
下面为一个简单案例:
# 在hm_01_九九乘法表.py文件中 函数定义
def multiple_table():
...
...
# 另一个.py文件导入
import hm_01_九九乘法表 #导入
hm_01_九九乘法表.multiple_table() #调用
函数的定义
- 一般来说,可以通过定义一个函数来隐藏任何计算的细节。一个函数定义需要一个 名称、一组 参数 和一个 函数体。
函数的定义格式如下:
def 函数名():
函数封装的代码
...
- def是英文define的缩写
- 函数名 应该是能够表达函数封装的代码的功能,方便后续的调用
- 函数名称的命名应该符合 标识符的命名规则
可以由字母,下划线和数字组成
不能以数字开头
不能与关键帧重名
函数的使用
- 调用函数很简单,通过 函数名() 即可完成对函数的调用
- 在使用函数名调用函数之前,必须保证Python已经知道函数的存在
- 定义好函数之后,只表示这个函数封装了一段代码而已
- 如果不主动调用函数,函数是不会执行的
pycharm的调试工具
- F8 Step Over 可以单步执行代码,会把函数调用看做是一行代码直接执行
- F7 Step Into 可以单步执行代码,如果是函数,会进入函数内部
函数的文档注释
在开发中,如果希望给函数添加注释,应该在定义函数的下方使用连续的三队引号
在连续的三对引号之间编写对函数的说明文字
在函数调用位置,使用快捷键CTRL+Q可以查看函数的说明信息
注意:因为函数体相对比较独立,函数定义的上方,应该和其他代码(包括注释)保留两个空行
不要在函数定义的上方增加单行或者多行注释
print("hello")
def sayHello():
"""打招呼"""
print("hello 1")
print("hello 2")
print("hello 3")
函数的参数
函数参数的使用
在函数名的后面的小括号内部填写参数
多个参数之间使用,分割
参数的作用
函数,把具有独立功能的代码块 组织为一个小模块,在需要的时候调用
函数的参数,增加函数的通用性,针对相同的数据处理逻辑,能够适应更多的数据
- 在函数的内部,把参数当做变量使用,进行需要的数据处理
- 函数调用时,按照函数定义的参数顺序,把希望在函数内部出库的数据,通过参数传递
形参和实参*
形参,定义函数时,小括号中的参数,是用来接收参数用的,在函数内部作为变量使用
实参,调用函数时,小括号中的参数,是用来把数据传递到函数内部用的
函数的返回
返回值是函数完成工作就,最后给调用者的一个结果
在函数中使用return关键字可以返回结果
调用函数一方,可以使用变量来接收函数的返回结果
注:return表示返回,后续的代码不会执行
def sum2Num(num1,num2):
"""
对两个数字求和
:param char:啊啊啊
:param times: 啊啊啊
"""
return num1+num2
num1 = 10
num2 = 20
result = sum2Num(num1,num2)
print("%d 加 %d 结果为: %d" % (num1,num2,result))
函数的嵌套调用
一个函数里面,又调用另一个函数,这就是函数的嵌套调用
3.8 使用模块中的函数
模块是Python程序架构的一个核心概念
模块就好比是工具包,要想使用这个工具包中的工具,就需要导入import这个模块
每一个扩展名.py结尾的Python源代码文件都是一个模块
在模块中定义的全局变量,函数都是模块能够提供给外界直接使用的工具
模块可以让曾经编写过的代码方便被复用
模块名也是一个标识符
标识符可以由字母、下划线和数字组成,不能以数字开头,不能与关键字重名
注:如果在给Python文件起名时,以数字开头是无法在pycharm中导入这个模块的
pyc
C是complied 编译过的意思
pyc文件是由Python解释器将模块的源码转换为字节码
Python这样保存字节码是作为一种启动速度的优化
字节码
- Python在解释源程序时是分两个步骤的
1.首先处理源代码,编译生成一个二进制字节码
2.再对字节码进行处理,才会生成CPU能够识别的机器码 - 有了模块的字节码文件之后,下一次运行程序时,如果在上次保存字节码之后没有修改过源代码,Python将会加载.pyc文件并跳过编译这个步骤
- 当Python重编译时,他会自动检查源文件和字节码文件的时间戳
- 如果你又修改了源代码,下次程序运行时,字节码将自动重新创建
3.9 高级变量类型
- python中数据类型可分为数字型和非数字型
数字型
整型 int
浮点型 float
布尔型 bool
复数型 complex(主要用于科学计算,如平面场,波动,电感电容)
非数字型
字符串,列表,元组,字典 - 在python中,所有非数组型变量都支持以下特点:
1.都是一个序列sequence,也可以理解为容器
2.取值[]
3.遍历 for in
4.计算长度,最大/最小值,比较,删除
5.链接+和重复*
6.切片
3.9.1 列表
List(列表)是python中使用最频繁的数据结构,其他语言中叫数组
专门用于存储一串信息
列表用[]定义,数据之间使用,分隔
列表索引从0开始
注意:从列表中取值时,如果超出索引范围,程序会报错
nameList = ["zhangsan","lisi","wangwu"]
列表的常用操作
在ipython3 中定义一个列表,例如:nameList = []
输入nameList,按下tab键,ipython会提示列表所能使用的方法
序号 | 分类 | 关键字/函数/方法 | 说明 |
---|---|---|---|
1 | 增加 | 列表.insert(索引,数据) | 在指定位置插入数据 |
列表.append(数据) | 在末尾追加数据 | ||
列表.extend(列表2) | 将列表2的数据追加到列表 | ||
2 | 修改 | 列表[索引]=数据 | 修改指定索引的数据 |
3 | 删除 | del 列表(索引) | 删除指定索引的数据 |
列表.remove(数据) | 删除第一个出现的指定数据 | ||
列表.pop | 删除末尾数据 | ||
列表.pop(索引) | 删除指定索引数据 | ||
列表.clear | 清空列表 | ||
4 | 统计 | len(列表) | 列表长度 |
列表.count(数据) | |||
5 | 排序 | 列表.sort() | 升序排序 |
列表.sort(reverse=True) | 降序排序 | ||
列表.reverse() | 逆序、反转 |
- 关键字是python内置的、具有特殊意义的标识符,关键字后面不需要使用括号
- 函数方法区别
- 函数封装了独立的功能,可以直接调用 函数名()
- 方法和函数类似,同样封装了独立的功能,方法需要通过对象来调用,表示针对这个对象要做的操作
循环遍历
遍历是从头到尾从列表中获得数据,在循环体内部针对每一个元素,直行相同的操作
在python中为提高列表的遍历效率,专门提供的迭代iteration遍历。
使用for就能够实现迭代
nameList = ["zhangsan","lisi","wangwu"]
for name in nameList:
print("我的名字叫 %s" % name)
数组取最后一个元素 test[-1]
range函数
通常与列表一起讨论的一个常见的Python函数是range函数,range产生一个范围对象,表示一些列的值。通过使用list函数,可以将range对象的值看做一个列表。eg:
>>> range(10)
range(0,10)
>>> list(range(10))
[0,1,2,3,4,5,6,7,8,9]
>>>range(5,10)
range(5,10)
>>>list(range(5,10))
[5,6,7,8,9]
>>>list(range(5,10,2))
[5,7,9]
>>>list(range(10,1,-1))
[10,9,8,7,6,5,4,3,2]
range 对象代表一个整数序列。默认情况下,它将从0开始。常用的参数有三个,在特定的点开始和结束,甚至可以跳过某项。
- 在第一个例子中,(10),序列从0开始,递增到10但不包括10。
- 在第二个例子中,范围(5,10)从5开始,递增到10但不包括10。
- 在第三个例子中,范围(5,10,2)类似的执行,但是跳过2(同样,10不包括在内)。
3.9.2 元组
Tuple(元组)与列表类似,不同之处在于元组的元素不能修改
- 元组表示多个元素组成的序列
- 元组在python开发中,有特定的场景
- 任何元组都不能被改变。
用于存储一串信息,数据之间用,分割
元组用()定义
元组索引从0开始,
info_tuple = ("zhangsan",18,19,1.32)
构建元组 : tuple = ()
注意: 元组只包含一个元素时,需要在元素后面添加逗号
>>> myTuple = (2,True,4.96)
>>> myTuple
(2, True, 4.96)
>>> len(myTuple)
3
>>> myTuple[0]
2
>>> myTuple * 3
(2, True, 4.96, 2, True, 4.96, 2, True, 4.96)
>>> myTuple[0:2]
(2, True)
- 但是,如果试图改变元组中的一个项,将会得到一个错误。注意,错误消息提供了问题的位置和原因。
元组有两个方法:count(元组的个数),index(元素在元组的索引)
元组变量的循环遍历
在python中使用for循环可以遍历所有非数字型类型的遍历
nameList = ("zhangsan","lisi","wangwu")
for name in nameList:
print("我的名字叫 %s" % name)
函数的参数和返回值,接收任意多个参数,返回多个数据
格式字符串,格式化字符串后面的()本质是一个元组
让列表不可以被修改,以保护数据安全
info_tuple = ("小明",21,1.85)
print("%s 年龄是 %d 身高是 %.2f" % info_tuple)
info_str = "%s 年龄是 %d 身高是 %.2f" % info_tuple
print(info_str)
元组列表之间的类型转换
使用list函数可以把元组转换成列表
list(元组)
使用tuple函数可以把列表转换成元组
tuple(列表)
3.9.3 字典
- dictionary(字典)是除列表以外python中灵活的数据类型
- 字典同一可以存储多个数据,通常用于存储描述一个物体的相关信息
- 列表:有序的对象集合
- 字典:是无序的对象集合
- 字典用{}定义
- 字典使用键值对存储数据,健值对之间使用,分割
>>> capitals = {'Iowa':'DesMoines','Wisconsin':'Madison'}
>>> capitals
{'Wisconsin': 'Madison', 'Iowa': 'DesMoines'}
- Python集合是一个无序的结构,称为字典。字典是一组关联项,其中每一项由一个键和一个值组成。这个 键-值 对通常被写成 key:value。字典的键值对以逗号分隔并用花括号括起来。
键 key 是索引
值 value 是数据
键和值 之间使用 : 分隔
键必须是唯一的
值可以取任何数据类型,但键只能使用字符串、数字、元组
xiaoming = {"name",
"gender":True,
"height":1.75}
print(xiaoming["name"])
xiaoming[age] = 20 #新增
xiaoming[name] = "小小明" #修改
xiaoming.pop("name") #删除
print(len(xiaoming)) #统计健值对数量
tmp = {"weight":50,"age":18}
xiaoming.update(tmp) #合并字典 年龄18
print(xiaoming)
字典的常用操作
统计:len(字典) 统计字典中健值对的数量
合并字典:字典.update(字典1),如果被合并的字典中包含健值对,会覆盖原来的健值对
清空字典:字典.clear() 清空所有的健值对
循环
xiaoming = {"name","gender":True,"height":1.75}
for k in xiaoming:
print("%s ;%s" % (k,xiaoming[k]))
可以通过它的键来访问它的值,或者通过添加另一个 键-值 对 来操作字典。取值语法除了使用键值而不是使用项目的索引,看起来很像序列取值,添加新值类似。
>>> capitals = {'Iowa':'DesMoines','Wisconsin':'Madison'}
>>> print(capitals['Iowa'])
DesMoines
>>> capitals['Utah']='SaltLakeCity'
>>> print(capitals)
{'Iowa': 'DesMoines', 'Wisconsin': 'Madison', 'Utah': 'SaltLakeCity'}
>>> capitals['California']='Sacramento'
>>> print(capitals)
{'Iowa': 'DesMoines', 'Wisconsin': 'Madison', 'Utah': 'SaltLakeCity', 'California': 'Sacramento'}
>>> print(len(capitals))
k = 4
>>> for k in capitals:
print(capitals[k]," is the capital of ", k)
#打印输出
DesMoines is the capital of Iowa
Madison is the capital of Wisconsin
SaltLakeCity is the capital of Utah
Sacramento is the capital of California
字典既有方法又有操作符,下面两个表格分别描述了它们:[] , in , del
>>> phoneext={'brad':1137,'david':1410,}
>>> phoneext
{'brad': 1137, 'david': 1410}
>>> phoneext.keys()
dict_keys(['brad', 'david'])
>>> list(phoneext.keys())
['brad', 'david']
>>> phoneext.values()
dict_values([1137, 1410])
>>> list(phoneext.values())
[1137, 1410]
>>> phoneext.items()
dict_items([('brad', 1137), ('david', 1410)])
>>> list(phoneext.items())
[('brad', 1137), ('david', 1410)]
keys、values 和 items 方法都返回包含感兴趣的值的对象。而 get 方法有两种变体,如果字典里没有对应键,get 将返回空。然而,第二个可选参数可以指定一个返回值。
In [0]: phoneext={'david':1410,'brad':1137}
In [1]: phoneext
Out[1]: {'david': 1410, 'brad': 1137}
In [2]: phoneext.get('kent')
# 返回空说明没有对应的键
In [3]: phoneext.get('kent','NO ENTRY')
Out[3]: 'NO ENTRY'
3.9.4 字符串
字符串就是一串字符,是编程语言中表示文本的数据类型、
在python中使用使用一对双引号或者一对单引号定义一个字符串
虽然可以使用 " 或者 ’ 做字符串的转义,但是在实际开发中:
- 如果字符串内部需要使用 " ,可以使用 ’ 定义字符串
- 如果字符串内部需要使用 ’ ,可以使用 " 定义字符串
- 可以使用索引获取一个字符串中指定位置的字符,索引计数从0开始
也可以使用for循环遍历字符串中每一个字符 - len(字符串)
- 字符串.count(字符串1) 小字符串出现的个数
- 字符串.index(字符串1) 小字符串出现的索引
判断数字
space_str = " \t\n\r"
print(space_str.isspace()) #输出True "字符串中仅仅只包含空白字符"
num_str = "1"
# 三个方法都不能判断使用小数
num_str = "一千零一"
print(num_str.isdecimal()) # 只能判断数字 false
print(num_str.isdigit()) # 不仅判断数字,还能判断Unicode字符串 false
print(num_str.isnumeric()) # 判断数字,unicode字符串,还能判断中文数字 true
查找
hello_str = "hello world"
# 1.判断是否已指定字符串开始
print(hello_str.startswith(Hello)) # False 大小写
# 2.判断是否已指定字符串结束
print(hello_str.endswith(world)) #True
# 3.查找指定字符串
# index 同样可以查找指定字符串在大字符串中的索引
print(hello_str.find("llo") # 2 返回索引
print(hello_str.find("abc") # -1 无匹配,则返回-1,不会报错,index会报错
# 4.替换字符串
# replace方法执行完成之后,会返回一个新的字符串
## 注意:不会修改原有字符串的内容
hello_str.replace("world","Python")
字符串文本对齐方法
方法 | 说明 |
---|---|
string.rjust(width) | 返回左对齐字符串 |
string.rjust(width) | 返回右对齐字符串 |
string.center(width) | 返回原字符串居中 |
poem = ["登鹳雀楼",
"王之涣",
"百日依山尽"]
for poem_str in poem:
print(pose_str.center(10))
for poem_str in poem:
print("|%s|" % pose_str.center(10))
for poem_str in poem:
print("|%s|" % pose_str.center(10," "))
去除空白字符
方法 | 说明 |
---|---|
string.lstrip() | 截掉string左边(开始)的空白字符 |
string.rstrip() | 截掉string右边(末尾)的空白字符 |
string.strip() | 截掉string两边的空白字符 |
拆分与连接
方法 | 说明 |
---|---|
string.partition(str) | 把字符串string分成3元素的元组 |
string.split(str="",num) | 以str为分隔符拆分string,如果num有指定值,则仅分隔num+1个子字符串,str默认包含 ‘\r’ '\t\ ‘\n’ 和 空格 |
string.splitlines() | 按照行(’\r’,’\n’,’\r\n’)分隔,返回一个包含各行作为元素的列表 |
string.join(seq) | 以string作为分隔符,将seq中所有的元素(的字符串表示)合并为一个新的字符串 |
# 假设一下内容网上抓取,要求:
# 1.将字符串中的空白字符全部去掉
# 2.再使用“ ”作为分隔符,拼接成一个整齐的字符串
poem_str = "登鹳全楼\t 王之涣\t 白日依山尽\t \n 黄河入海流\t \t"
print(poem_str)
# 1.拆分字符串
poem_list = poem_str.split()
print(poem_list)
# 2.合并字符串
result = " ".join(poem_list)
print(result)
字符串的切片
切片的方法适应于字符串、列表、元组
切片使用索引值来限定范围,从一个大的字符串中切出小的字符串
列表和元组是有序集合,能够通过索引值获得对应的数据
字典是一个无序的集合,是使用键值对来保存数据
字符串[开始索引:结束索引:步长]
注意:
- 指定的区间属于左闭右开
- 从头开始,开始索引数字可以省略,冒号不能省略
- 到末尾结束,结束索引数字可以省略,冒号不能省略
- 步长默认为1,如果连续切片,数组和冒号都可以省略
>>> m = list(range(100))#通过range函数创建一个0-99的数列,组成一个list赋值给m
>>> m
[0, 1, 2, 3, 4, 5, 6, ……,99]
>>> m[:10]#取前十个数
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> m[-10:]#取后十个数
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
>>> m[10:20]#取前11-20个数
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> m[:10:2]#前十个数中,每2个数取一个
[0, 2, 4, 6, 8]
>>> m[5:15:3]#第6-15个数中,每3个数取一个
[5, 8, 11, 14]
>>> m[::10]#所有的数中,每10个数取一个
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> m[:]#什么都不写,可以原样复制一个list
[0, 1, 2, 3, 4, 5, 6, 7,……,99]
3.9.10 集合
- set是一个无序的, 为空或是更多不可变的Python数据对象集合。集合中的值不允许重复,写在大括号中。空集合由 set() 表示。如下所示。
>>> {3,6,"cat",4.5,False}
{False, 4.5, 3, 6, 'cat'}
>>> mySet = {3,6,"cat",4.5,False}
>>> mySet
{False, 4.5, 3, 6, 'cat'}
>>>
尽管集合不被认为是连续的,但是它们确实支持前面提到的一些熟悉的操作。
eg: in,len,|,&,-,<=
>>> mySet
{False, 4.5, 3, 6, 'cat'}
>>> len(mySet)
5
>>> False in mySet
True
>>> "dog" in mySet
False
- 集合支持许多方法,这些方法对于在数学集合中使用它们的人来说应该是熟悉的。 请注意,联合,交集,子集和差分都有可以使用的运算符。
>>> mySet
{False, 4.5, 3, 6, 'cat'}
>>> yourSet = {99,3,100}
>>> mySet.union(yourSet)
{False, 4.5, 3, 100, 6, 'cat', 99}
>>> mySet | yourSet
{False, 4.5, 3, 100, 6, 'cat', 99}
>>> mySet.intersection(yourSet)
{3}
>>> mySet & yourSet
{3}
>>> mySet.difference(yourSet)
{False, 4.5, 6, 'cat'}
>>> mySet - yourSet
{False, 4.5, 6, 'cat'}
>>> {3,100}.issubset(yourSet)
True
>>> {3,100}<=yourSet
True
>>> mySet.add("house")
>>> mySet
{False, 4.5, 3, 6, 'house', 'cat'}
>>> mySet.remove(4.5)
>>> mySet
{False, 3, 6, 'house', 'cat'}
>>> mySet.pop()
False
>>> mySet
{3, 6, 'house', 'cat'}
>>> mySet.clear()
>>> mySet
set()
3.10 公共方法
python内置函数
通过函数名直接调用的函数
python包含了以下内置函数:
函数 | 描述 | 备注 |
---|---|---|
len(item) | 计算容器中元素的个数 | |
del(item) | 删除变量 | del有两种方式 |
max(item) | 返回容器中元素最大值 | 如果是字典,只针对key比较 |
min(item) | 返回容器中元素最小值 | 如果是字典,只针对key比较 |
cmp(item1,item2) | 比较两个值 | python 3.x取消 |
注意:字符串比较符合规则:“0”<“A”<“a”
a = [1,2,3]
del a[1] # 1 1与2结果一样
del(a[1]) # 2
切片
描述 | python表达 | 结果 | 支持的数据类型 |
---|---|---|---|
切片 | “0123456789”[::-2] | “97531” | 字符串、列表、元组 |
切片使用索引值来限定范围,从一个大的字符串中切出小的字符串
列表和元组都是有序的集合,都能够通过索引值获得对应的数据
字典是一个无序的集合,是使用健值对保存数据
运算符
运算符 | python表达式 | 结果 | 描述 | 支持的数据类型 |
---|---|---|---|---|
+ | [1,2]+[3,4] | [1,2,3,4] | 合并 | 字符串,列表,元组 |
* | [“Hi!”]*4 | [“Hi!”,“Hi!”,“Hi!”,“Hi!”] | 重复 | 字符串,列表,元组 |
in | 3 in (1,2,3) | True | 元素是否存在 | 字符串,列表,元组,字典 |
not in | 4 not in (1,3,2) | True | 元素不存在 | 字符串,列表,元组,字典 |
> >= == <= < | (1,2,3)<(2,2,3) | True | 元素比较 | 字符串,列表,元组 |
注意
- 对字典操作时,判断的是字典的键
- in 和 not in 被称为成员运算符
- * 字典不可以,因为字典的健值是唯一的
完整的for循环语法
在python中完整的for循环的语法如下:
for 变量 in 集合:
循环体代码
else:
没有通过break退出循环,循环结束后,会执行的代码
3.11框架搭建
搭建名片管理系统框架结构
- 准备文件,确保文件名,保证能够在需要的位置编写代码
- 编写主运行循环,实现基本的用户输入和判断
文件准备
- 新建cards_main.py保存主程序功能代码
程序的入口
每一次启动名片管理都通过这个main这个文件启动 - 新建cards_tools.py保存所有名片功能函数
将对名片的新增,查询,修改,删除等功能封装在不同的函数中
案例
cards_main.py中
import cards_tool
while True
cards_tool.show_menu()
cards_tool.py中
def show_menu():
"""显示菜单"""
print("*" * 50)
LINUX上的Shebang符号(#!)
- #!这个符号叫 Shebang 或者 Sha-bang
- Shebang 通常在 Unix系统脚本的中 第一行 使用
- 指明执行这个脚本文件的解释程序
使用Shebang的步骤:
- 使用which 查询python3解释器所在路径
which python3
- 修改要运行的主python文件,在第一行增加以下内容
#! /usr/bin/python3
- 修改主python文件的文件权限,增加执行权限
chmod +x cards_main.py
- 在需要时运行程序即可
./cards_main.py
4.变量进阶
4.1 变量的引用
变量和数据都是保存在内存中的
在python中函数的参数传递以及返回值都是靠引用传递的
4.2 引用的概念
- 变量和数据是分开存储的
- 数据保存在内存中的一个位置
- 变量中保存着数据在内存中的地址
- 变量中记录数据的地址,叫做引用
- 使用 id() 函数可以查看变量中保存数据所在的内存地址
注意:如果变量已经被定义,当给一个变量赋值的时候,本质上是修改了数据的引用
变量不再对之前的数据引用
变量改为对新赋值的数据引用
def test(num):
print("在函数内部%d对应的内存地址是%d" % (num,id(num)))
result = "hello"
print("在函数对应的内存地址是%d" % (id(num)))
return result
a = 10
# 数据的地址本质上就是一个数字
print("a 变量保存数据的内存地址是 % d", % id(a))
# python 中传递数值不会将10传递过去,只会将10保存的地址传递过去
# 调用test函数,本质上传递的是实参保存数据的引用,而不是实参保存的数据!
r = test(a)
4.3 可变和不可变类型
不可变类型,内存中的数据不允许被修改
- 数字类型,int,bool,float,complex,log(2.0)
- 字符串 str
- 元组 tuple
可变类型,内存中的数据可以被修改
列表 list
字典 dict 字典中的key 只能使用不可变类型的数据
- 可变类型的数据变化,是通过方法来实现的
- 如果给一个可变类型的变量,赋值一个新的数据,引用会修改
变量不再对之前的数据引用
变量改为对新赋值的数据引用
4.4 局部变量和全局变量
局部变量是在函数内部定义的变量,只能在函数内部使用
- 全局变量是定义在函数外部定义的变量(没定义在某一函数内),所有函数内部都可以使用这个变量
- 局部变量函数体执行后,函数内部的局部变量会被系统收回。作用: 在函数体内使用,临时保存函数内部需要使用的数据
生命周期,从变量被创建到系统回收的过程
注意:函数执行时,需要处理变量时会:
- 首先查找函数内部是否存在指定名称的局部变量,如果有,直接使用。
- 如果没有,查找函数外部是否存在指定名称的全局变量,如果有,直接使用
- 如果没有,程序报错
函数不能直接修改全局变量的引用
- 在其他开发语言中,大多不推荐使用全局变量–可变范围大没导致程序崩溃。
为保证所有的函数都能够正确使用全局变量,应该将全局变量定义在其他函数的上方。 - 在函数内部,可以通过全局变量的引用获取对应的数据
- 但是,不允许直接修改全局变量的引用–使用赋值语句修改全局变量的值
num = 10
def demo():
num =999 #重新定义了一个局部变量num
print(num) #10
调试过程中(debug),变量区域可显示当前调试中输出情况。
如何在函数中修改全局变量呢?
num = 10
def demo():
#global关键字会告诉解释器后面的变量是一个全局变量,在使用赋值语句时,就不会创建局部变量
global num
num =999 #重新定义了一个局部变量num
print(num) #1
- 在开发时,应该把模块中的所有全局变量定义在函数上方,就可以保证所有的函数都能够正常的访问到每一个全局变量了。
代码结构示意图
shebang | import模块 | 全局变量 | 函数定义 | 执行代码 |
---|
全局变量命名建议
- 为了避免变量和全局变量出现混淆,在定义全局变量时,一般在全局变量名前面增加g_或者gl_的前缀
pycharm中修改某一全局变量的全部命名 选中该对象,右键Refector->Rename
5.函数的高级话题
5.1 函数的参数和返回值的作用
当形参如*arg时表示传入数组,当形参如**args时表示传入字典。
def myprint(*commends,**map):
for comm in commends:
print comm
for key in map.keys():
print key,map[key]
函数:功能独立的代码封装,通过函数名调用。
参数:外界希望在函数内部处理数据。
返回值:向外界报告函数的执行结果。
函数的返回值就是当函数执行完成后,最后给调用者一个结果。
return
def measure():
temp =20
wetness = 30
#元组-可以包含多个数据,因此可以使用元组让函数一个返回多个值
#如果函数返回的类型是元组,小括号可以省略
return (temp,wetness)
result = measure()
#可以使用多个变量,一次接受函数的返回结果
# 注意:使用多个变量接受结果时,变量的个数应该和元组中元素的个数保持一致
gl_temp,gl_wetness = measure()
print(result)
print(result[0])
print(result[1])
利用元组可以交换两个数据
a,b = (b,a)
a,b = b,a
#------------------
a = a+b
b = a-b
a= a-b
5.2 不可变参数和可变参数
在函数内部,指针参数使用赋值语句,不会影响调函数时传递的实参变量
- 只要针对参数使用赋值语句,会在函数内部修改局部变量的引用,不会影响到外部变量的引用。
- 如果传递的参数是可变的,在函数内部,使用方法修改了数据的内容,同样会影响到外部的数据。
def demo(num,num_list):
num = 100
# 列表变量使用 += 不会做相加再赋值的操作
#本质上是在再调用列表的extend方法
num_list = [1,2,3]
print(num)
g_num =99
g_num_list = [4,5,6]
demo(g_num,g_num_list)
print(g_num) # 输出 99
print(num_list) # 输出 4,5,6 列表是可变的,但仍然没改变值
+= 在python中,列表变量调用 += 本质上执行列表变量的 extend 方法,不会修改变量的引用
5.3 缺省参数
定义函数时,可以给某个参数指定一个默认值,具有默认值的参数叫做缺省参数
调用函数时,如果没有传入缺省参数,则默认执行默认值。
将常见的值设为缺省值,可简化函数的调用。
g_list = [6,3,9]
g_list.sort() #升序,默认参数
print(g_list)
g_list.sort(reverse=True) #降序,引入参数
- 缺省参数在参数列表的末尾
-
- 缺省参数,需要使用最常见的值作为默认值
-
- 如果一个参数的值不能确定,则不应该设置默认值,具体的数值在调用函数时,由外界传递
- 调用带有多个缺省参数的参数
-
- 在调用函数时,如果有多个缺省参数,需要指定参数名,这样解释器才能够知道参数的对应关系。
def print_info(name,tile="",gender=True):
"""
:param name:班上同学的名字
:param tile:职位
:param gender:True 男生 False 女生
"""
gender_txt = "男生"
if not gender:
gender_test="女生"
print("%s 是 %s" % (name,gender_test))
#假设班上同学男生居多
print_info("小明")
print_info("老王")
print_info("小美",False) # False 直接赋值给第二个
print_info("小美",gender=False)
5.4 多值参数
定义支持多值参数的函数
-
有时可能需要一个函数能够处理的参数格式是不确定的,这个时候,就可以使用多值参数
-
python中有两种多值参数:
参数名前增加一个*可以接受元组
参数明前增加两个*可以接受字典 -
一般在给多值参数命名时,习惯使用一下两个名字:
*args --存放元组参数,前面一个*
kwarg --存放字典**参数,前面两个 ** -
args 是 arguments 的缩写,有变量的含义
-
kw是 keyword 的缩写,kwargs 可以记忆 键值对参数
def demo(num,*nums,**person):
print(num)
print(nums)
print(person)
#demo(1)
demo(1,2,3,4,5,name="小美",age=18)
#打印
#1
#(2,3,4,5)
#{name="小美",age=18}
提示: 多值参数 的应用会经常出现在网络上大牛开发的框架中,知道多值参数,有利于我们读懂大牛的代码
def sum_num(*args):
num = 0
print(args)
for n in args:
num +=n
return num
result = sum_num(1,2,4,5,6)
print(result) # 18
# 不使用* 时,需要多指定一组括号
def sum_num(args):
num = 0
print(args)
for n in args:
num +=n
return num
result = sum_num((1,2,4,5,6))
print(result) # 18
5.5 元组和字典的拆包
- 在调用带有多值参数的函数时,如果希望:
将一个元组变量,直接传递给 args
将一个字典变量,直接传递给 kwargs - 就可使用拆包,简化参数的传递,拆包的方式是:
在元组变量前面,增加一个 *
在字典变量的前面,增加两个 *
def demo(*args,**kwargs):
print(args)
print(kwargs)
#元组变量/字典变量
g_num = (1,2,3)
g_dict = {"name":"小明","age":19}
demo(gl_num,gl_dict)
# ((1,2,3),{'age':18,'name':'小明'})
# {}
demo(*gl_nums,**gl_dict)
# (1,2,3)
# {'age':18,'name':'小明'}
demo(1,2,3,"name":"小明","age":19)
5.6 函数的递归
函数调用自身的编程技巧称为递归
- 特点
一个函数调用自己
函数内部可以调用其他函数,也可以调用自己 - 代码特点
1.函数内部的代码是相同的,只是针对参数不同,处理的结果不同
2.当参数满足一个条件时,函数不再执行。这个非常重要,称为递归的出口,否则出现死循环
三、面向对象(OOP)
- 相比函数,面向对象是更大的封装,根据职责在一个对象中封装多个方法
1.类和对象
- 类 是对一群具有相同特征或行为的事物的一个统称,是抽象的,不能直接使用
- 对象是由类创建出来的一个具体存在,可以直接使用
- 由哪一个类创建出来的对象,就拥有在哪一个类中定义的:属性和方法
1.1类和对象的关系
- 类相当于图纸,对象相当于用图纸制造的飞机
- 类是模板,对象是根据类这个模板创建出来的,应该先有类,再有对象
- 类只有一个,而对象可能有很多个
- 类中定义了什么属性和方法,对象中就有什么属性和方法,不可能多,也不可能少
1.2 类设计
在使用对象开发前,首先应分析需求
- 类名 这类事物的名字,满足大驼峰命名法
- 属性 这类事物具有什么样的特征
- 方法 这类事物具有什么样的行为
2 面向对象基础语法
2.1 dir 内置函数
- 在python中对象几乎是无处不在,变量,数据,函数 都是对象
- 在python中可以使用两个方法验证:
1.在标识符或数据后面输入一个 . ,按下tab键,ipython会提示该对象能够调用的方法列表
2.在内置函数 dir 传入标识符/数据,可查看对象内的所有属性及方法
提示: 方法名 格式的方法 是python提供的 内置方法/属性
__new__ 创建对象是,会自动调用
__int__ 对象被初始化时,自动被调用
__del__ 对象从内存销毁前,会被调用
__str__ 返回对象的描述信息,print函数输出使用
提示:利用 dir() 函数,可查看类的内容
2.2 定义一个简单类
面向对象是更大的封装,在一个类中封装多个方法,这样通过这个可创建出来的对象,就可以直接调用这些方法了。
定义只包含方法的类
python中定义一个只包含方法的类,语法:
class 类名:
def 方法1(self,参数):
pass
def 方法2(self,参数):
pass
注意:类名的命名规则要符合大驼峰命名法
在Python中可以使用class关键字定义类,然后在类中通过之前学习过的函数来定义方法,这样就可以将对象的动态特征描述出来,
class Student(object):
# __init__是一个特殊方法用于在创建对象时进行初始化操作
# 通过这个方法我们可以为学生对象绑定name和age两个属性
def __init__(self, name, age):
self.name = name
self.age = age
def study(self, course_name):
print('%s正在学习%s.' % (self.name, course_name))
# PEP 8要求标识符的名字用全小写多个单词用下划线连接
# 但是部分程序员和公司更倾向于使用驼峰命名法(驼峰标识)
def watch_movie(self):
if self.age < 18:
print('%s只能观看《熊出没》.' % self.name)
else:
print('%s正在观看岛国爱情大电影.' % self.name)
创建对象
当一个类定义完以后,要使用这个类来创建对象,语法:
对象变量 = 类名()
在python 中,使用类创建对象之后,对象变量中 仍然记录的是 对象在内存中的地址
使用print输出对象变量时,输出的是这个变量的引用,是由哪个类创建的对象,以及在内存中的地址(十六进制表示) %d 十进制,%x十六进制
方法中的self 参数
- 在python 中,要给对象设置属性,非常容易,但不推荐
因为:对象属性的封装应该在类的内部 - 只需在类的外部的代码中直接通过 . 设置一个属性即可。
简单,但不推荐使用
2.3 初始化方法
之前代码存在的问题----类的外部给对象增加属性
- 不推荐在类的外部给对象增加属性
如果在运行时,没有找到属性,程序会报错。
对象应该包含哪些属性,应该封装在类内部
- 当使用**类名()**创建对象时,会自动执行下操作
1.为对象在内存中分配空间–创建对象
2.为对象属性初始化–初始化方法(init) - 这个初始化方法,就是__init__ 是对象的内置方法
- __init__(self,param,param):
2.4 内置方法和属性
序号 | 方法名 | 类型 | 作用 |
---|---|---|---|
1 | __del__ | 方法 | 对象在内存中销毁前,会自动调用 |
2 | __str__ | 方法 | 返回对象的描述信息,print函数输出使用 |
- __str__ 默认,会输出这个变量引用的对象是哪一个类创建的对象,以及内存中的地址(十六进制)
- 如果在开发中,希望用print输出对象变量时,能够打印自定义的内容,就可以利用__str__这个内置方法。
- 注意:__str__ 方法必须返回一个字符串
3 面向对象的支柱
面向对象有三大支柱:封装、继承和多态。
3.1 封装
- 把数据和对数据的操作封装起来了,在我们创建了对象之后,只需要给对象发送一个消息(调用方法)就可以执行方法中的代码,也就是说我们只需要知道方法的名字和传入的参数(方法的外部视图),而不需要知道方法内部的实现细节(方法的内部视图)。
简单案例
例如:定义一个类描述数字时钟
from time import sleep
class Clock(object):
"""数字时钟"""
def __init__(self, hour=0, minute=0, second=0):
"""初始化方法
:param hour: 时
:param minute: 分
:param second: 秒
"""
self._hour = hour
self._minute = minute
self._second = second
def run(self):
"""走字"""
self._second += 1
if self._second == 60:
self._second = 0
self._minute += 1
if self._minute == 60:
self._minute = 0
self._hour += 1
if self._hour == 24:
self._hour = 0
def show(self):
"""显示时间"""
return '%02d:%02d:%02d' % \
(self._hour, self._minute, self._second)
def main():
clock = Clock(23, 59, 58)
while True:
print(clock.show())
sleep(1)
clock.run()
if __name__ == '__main__':
main()
对象属性创建另一对象
一个对象的属性可以是另外一个类创建的对象
class Gun:
def __init__(self,model):
self.model = model
self.bullet_cout = 0
def add_bullet(self,cout):
self.bullet_cout +=count
def shoot(self):
if self.bullet_cout >0:
print("fa she zi dan")
self.bullet_cout -=1
print("[%s] 突突突" % (self.model,self.bullet_cout))
else:
print("%s 没有子弹了..." % self.model)
class Soldier:
def __init__(self,name):
self.name = name
self.gun = None
AK47 = Gun("ak47")
xusanduo = Soldier("许三多")
xusanduo.gun = ak47
类参数未设置时,可以直接赋值 None
身份运算符
身份运算符用于比较两个对象的内存地址是否一致,是否是同一对象的引用。
运算符 | 描述 | 实例 |
---|---|---|
is | 判断两个标识符是否是同一个对象 | x is y 类似id(x)==id(y) |
is not | 判断两个标识符是不是引用不同对象 | x is not y 类似id(x) != id(y) |
is 与 == 区别
is 是判断两个变量是否一样
== 判断两个值是否相同
私有属性和私有方法
- 私有属性:对象不希望公开属性
- 私有方法:对象不希望公开方法
定义方式:
- 在定义属性或方法时,在属性名或方法名前增加两个下划线,定义的就是私有属性或方法
class Women:
def __init__(self,name):
self.name = name
self.__age = 18
def __secret(self):
print("我的年龄是 %s" % self.__age)
xiaohua = Women("小花")
伪私有属性和私有方法
提示:在日常开发中不要使用这种方式,访问对象的私有属性或私有方法
python中,没有真正意义的私有:
- 在给属性、方法命名时,实际是对名称做了一些特殊处理,使得外界无法访问到
- 处理方式: 在名称前面加上 _类名 -> __类名__名称
class Women:
def __init__(self,name):
self.name = name
self.__age = 18
def __secret(self):
print("我的年龄是 %s" % self.__age)
xiaohua = Women("小花")
print(xiaohua._age) 直接报错
print(xiaohua._Women__age) 可以,但是不推荐
3.2 继承
单继承
继承的语法:
class 类名(父类名):
pass
- 子类继承自父类,可以直接享受父类中已经封装好的方法
- 子类应该根据职责,封装子类特有的属性和方法
专业术语:
- 子类 父类 类继承
- 派生类 基类 类派生
继承具有传递性
class Animal:
def eat(self):
print("吃")
def drink(self):
print("喝")
def sleep(self):
print("睡")
class Dog(Animal):
def bark(self):
print("汪汪叫")
class XiaoTiabQuan(Dog):
def fly(self):
print("我会飞")
def bark(self):
print("小天")
方法的重写
当父类的方法实现不能满足子类需求时,可以对方法进行重写
重写父类方法的两种情况:
- 覆盖父类的方法
- 对父类方法进行扩展
覆盖父类的方法:
- 在子类中定义跟父类同名的方法,并自己实现
- 重写后,在运行时,只会调用子类中重写的方法,而不会调用父类封装的方法
对父类方法进行扩展
如果开发中,子类的方法实现中子类方法的一部分
就可使用扩展的方式
- 在子类中重写父类的方法
- 在需要的位置使用 super().父类方法 ,来调用父类方法的执行
- 代码其他的位置针对子类的需求,编写子类特有的代码实现
关于super
-在python 中super是一个特殊的类
- super() 就是使用super类创建出来的对象
- 最常使用的场景就是在重写父类方法时,调用在父类中封装的方法实现
class Animal:
def eat(self):
print("吃")
def drink(self):
print("喝")
def sleep(self):
print("睡")
def bark(self):
print("汪汪叫")
class XiaoTiabQuan(Animal):
def fly(self):
print("我会飞")
def bark(self):
print("神一样的叫唤")
super.bark()
# Animal.bark(self) python 2.0
print("小天")
# input
# 神一样的叫唤 汪汪叫 小天
私有公有
多继承
子类可以拥有多个父类,并且具有所有父类的属性和方法
class A:
class B:
class C(A,B):
父类间存在同名的属性或方法时,应该避免多继承
python 中的MRO --方法索索顺序
python针对类提供一个内置属性__mro__可以查看方法搜索顺序
MRO 主要用于 在多继承时判断方法、属性的调用路径
print(C.__mro__)
新式类
object 是 python 为所有对象提供的 基类,提供有一些内置的属性和方法,可以使用dir函数变量
新式类:以object 为基类的类,推荐使用
经典类:不以 object 为基准的类,不推荐使用
- 在python3.x中定义类时,如果没有指定父类,会默认使用object作为该类的基类
新式类和经典类在多继承时–会影响到方法的搜索顺序
今后使用时,如果没有父类,建议统一继承自object
class 类名(object):
pass
3.3多态
面向对象的三大特性:
- 封装
- 继承
实现代码的重用,相同代码不用重复写 - 多态
不同的子类对象调用相同的父类方法,产生不同的结果。
1.多态增加代码的林获悉
2.以继承和重写父类方法为前提
3.是调用方法的技巧,不会影响到类的内部继承
class Dog(object):
def __init(self,name)
self.name = name
def game(self):
print("%s 蹦跳玩耍" % self.name)
class XiaoTianDog(Dog):
def game(self):
print("%s 飞到天上去玩" % self.name)
class Person(object):
def __init__(self,name):
self.name =name
def game_with_dog(self,dog):
print("%s 和 %s 快乐的玩耍" % (self.name,dog.name))
# 让狗玩耍
dog.game()
#1.创建狗对象
一,wangcai = Dog("旺财")
二,wangcai = XiaoTianDog("飞天旺财")
#2.创建小明对象
xiaoming = Person("小明")
#3.让小明调用狗方法
xiaoming.game_with_dog()
#ouput:旺财蹦跳玩耍
#二output: 飞天旺财飞到天上去玩
- 在每个对象都有自己独立的内存空间,保存各自不同的属性。
- 多个对象的方法,在内存中只有一份,在调用方法时,需要把对象的引用传递到方法内部
类是一个特殊的对象
python中一切皆对象:
- class AAA: 定义的类属于 类对象
- objec1 = AAA() 属于 实例对象
在python中,类对象在内存中只有一份,使用一个类可以创建多个对象实例
除了封装实例的属性和方法外,类对象还可以拥有自己的属性和方法
- 类属性
- 类方法
class Tool():
def __init__(self,name):
self.name = name
Tool.cout +=1
Tool1 = Tool("futou")
Tool2 = Tool("chuizi")
Tool3 = Tool("tiechui")
print(Tool.count)
对象名点访问不推荐,可能创建一个新的属性
定义类方法
# 类方法
@clasmethod
def 类方法名(cls):
pass
# 类属性
def __init__(self):
类名.count +=1
也可通过cls. 访问类属性和类方法
静态方法
在开发中,如果需要在类中封装一个方法,这个方法:
- 既不需要访问实例属性或调用实例方法
- 也不需要访问类属性或调用类方法
调用语法
@staticmethod
def 静态方法名():
pass
通过类名. 可以调用静态方法
__new__方法
- 使用 类名() 创建对象时,python解释器首先会调用 __new__ 方法为对象分配空间
- __new__是一个由object基类提供的内置的静态方法,主要作用有:
1.在内存为对象分配空间
2.返回对象的引用 - python的解释器获得对象的引用后,将引用作为第一个参数,传递给__init__ 方法
重写__new__方法的代码非常固定 - 重写__new__方法一定要 return super().__new__(cls)
- 否则python 的解释器得不到分配空间的对象引用,就不会调用对象的初始化方法
- 注意:__new__是一个静态方法,在调用时需要主动传递cls参数
class MusicPlayer(object):
def __new__(cls,*args,**kwargs):
print("创建对象,分配空间")
# 为对象分配空间 2
instance = super().__new__(cls)
# 返回对象的引用 2
return instance
def __init__(self):
print("播放器初始化")
#创建播放器对象
player =MusicPlayer()
print(player)
#为加2 只有1的打印
#创建对象,分配空间 1
#None 1
#增加2 后打印正常
#<__main__.MusicPlayer object at 0x7f9511>
单类设计
单例 – 让 类创建的对象,在系统中只有唯一的一个实例
- 方法
- 定义一个类属性,初始值是None,用于记录单例对象的引用
- 重写__new__方法
- 如果类属性是is None,调用父类方法分配空间,并在类属性中记录结果
- 返回雷属性中记录的对象引用
class MusicPlayer(object):
#记录第一个被创建对象的引用
instance = None
def __new__(cls,*args,**kwargs):
#1.判断类属性是否是空对象
if cls.instance is None:
#2.调用父类的方法,为一个对象分配空间
cls.instace = super().__new__(cls)
#3.返回属性保存的引用对象
return cls.instance
def __init__(self):
print("播放器初始化")
player1 = MusicPlay()
print(player1)
player2 = MusicPlay()
print(player2)
# 输出相同
只初始化一次
- 在每次使用 类名() 创建对象时,python的解释器都会自动调用两个方法
1.__new__分配空间
1.__init__对象初始化 - 在上一节对__new__方法改造后,每次都会得到第一次被创建对象的引用
- 但是:初始化方法还是会被调用多次
需求:
让初始化动作只执行一次
解决办法:
- 定义一个类属性init_flag,标记是否执行初始化动作,初始为False
- 在__init__方法中,判断init_flag,如果为False就执行初始化条件
- 然后将init_flag设置为True
- 这样,再次自动使用__init__方法时,初始化动作就不会被再次执行了。
四、其他
1.异常
1.0 基本异常
异常名称 | 描述 |
---|---|
BaseException | 所有异常的基类 |
SystemExit | 解释器请求退出 |
KeyboardInterrupt | 用户中断执行(通常是输入^C) |
Exception | 常规错误的基类 |
StopIteration | 迭代器没有更多的值 |
GeneratorExit | 生成器(generator)发生异常来通知退出 |
StandardError | 所有的内建标准异常的基类 |
ArithmeticError | 所有数值计算错误的基类 |
FloatingPointError | 浮点计算错误 |
OverflowError | 数值运算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有数据类型) |
AssertionError | 断言语句失败 |
AttributeError | 对象没有这个属性 |
EOFError | 没有内建输入,到达EOF 标记 |
EnvironmentError | 操作系统错误的基类 |
IOError | 输入/输出操作失败 |
OSError | 操作系统错误 |
WindowsError | 系统调用失败 |
ImportError | 导入模块/对象失败 |
LookupError | 无效数据查询的基类 |
IndexError | 序列中没有此索引(index) |
KeyError | 映射中没有这个键 |
MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
NameError | 未声明/初始化对象 (没有属性) |
UnboundLocalError | 访问未初始化的本地变量 |
ReferenceError | 弱引用(Weak reference)试图访问已经垃圾回收了的对象 |
RuntimeError | 一般的运行时错误 |
NotImplementedError | 尚未实现的方法 |
SyntaxError Python | 语法错误 |
IndentationError | 缩进错误 |
TabError | Tab 和空格混用 |
SystemError | 一般的解释器系统错误 |
TypeError | 对类型无效的操作 |
ValueError | 传入无效的参数 |
UnicodeError | Unicode 相关的错误 |
UnicodeDecodeError | Unicode 解码时的错误 |
UnicodeEncodeError | Unicode 编码时错误 |
UnicodeTranslateError | Unicode 转换时错误 |
Warning | 警告的基类 |
DeprecationWarning | 关于被弃用的特征的警告 |
FutureWarning | 关于构造将来语义会有改变的警告 |
OverflowWarning | 旧的关于自动提升为长整型(long)的警告 |
PendingDeprecationWarning | 关于特性将会被废弃的警告 |
RuntimeWarning | 可疑的运行时行为(runtime behavior)的警告 |
SyntaxWarning | 可疑的语法的警告 |
UserWarning | 用户代码生成的警告 |
Eg:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
try:
fh = open("testfile", "w")
fh.write("这是一个测试文件,用于测试异常!!")
except IOError:
print "Error: 没有找到文件或读取文件失败"
else:
print "内容写入文件成功"
fh.close()
1.1.异常概念
- 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。
- 在程序运行时,如果python解释器遇到一个错误,会停止程序的执行,并且提示一些错误信息,这就是异常。
- 程序停止执行并提示错误信息这个动作,我们称为:跑出异常。
- 在程序开发中,很难将所有的特殊情况都处理的面面俱到,通过异常可以针对突发世界作出集中的处理,保证程序的稳定性和健壮性。
#提示用户输入一个整数
num = int(input("输入整数:"))
# 输入非整数时会报错
1.2.异常处理
- 捕捉异常可以使用try/except语句。
- try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。
- 如果你不想在异常发生时结束你的程序,只需在try里捕获它。
以下为简单的try…except…else的语法:
try:
<语句> #运行别的代码
except <名字>:
<语句> #如果在try部份引发了'name'异常
except <名字>,<数据>:
<语句> #如果引发了'name'异常,获得附加的数据
else:
<语句> #如果没有异常发生
try的工作原理是,当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到这里,try子句先执行,接下来会发生什么依赖于执行时是否出现异常。
- 如果当try后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的except子句,异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异常)。
- 如果在try后的语句里发生了异常,却没有匹配的except子句,异常将被递交到上层的try,或者到程序的最上层(这样将结束程序,并打印默认的出错信息)。
- 如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的话),然后控制流通过整个try语句。
Eg: 打开文件是否成功
#!/usr/bin/python
# -*- coding: UTF-8 -*-
try:
fh = open("testfile", "w")
fh.write("这是一个测试文件,用于测试异常!!")
except IOError:
print "Error: 没有找到文件或读取文件失败"
else:
print "内容写入文件成功"
fh.close()
1.3 捕获未知错误:
- 在开发时,要预判断到所有可能出现的错误,还是由一定的难度
- 如果希望程序无论出现任何错误,都不会因为python解释器跑出异常而终止,可以再增加一个except
你可以不带任何异常类型使用except,如下实例:
try:
正常的操作
......................
except:
发生异常,执行这块代码
......................
else:
如果没有异常执行这块代码
例如:
try:
num = int(input("输入整数:"))
result = 8/num
except ValueError:
print("请输入正确的整数")
#输入零时直接凉凉
except Exception as result:
print("请输入正确的整数")
#输入0,输出:未知错误,division by zero
所有错误捕获后,在其后面增加
异常捕获完整语法
异常捕获完整语法如下:
try:
# 尝试执行的代码
pass
except 错误类型1:
#针对错误类型1,对应的代码处理
pass
except 错误类型2:
#针对错误类型2,对应的代码处理
pass
except (错误类型3,错误类型4):
#针对错误类型3和4,对应的代码处理
pass
except Exception as result:
# 打印错误信息
print(result)
else:
#没有异常才会执行代码
pass
finally:
# 无论有无异常,都会执行的代码
print("无论有无异常,都会执行的代码")
1.3 异常传递
- 异常传递 – 当函数/方法执行出现异常时,会将异常传递给函数/方法的调用一方
- 如果传递到主程序,仍然没有异常处理,程序才会终止
def demo1():
return int("输入整数:")
def demo2():
return demo1()
print(demo2())
提示:
- 在开发中,可以在主函数中增加异常捕获
- 二组主函数调用的其他函数,只要出现异常,都会传递到主函数的异常捕获中
- 这样就不需要在代码中,增加大量的**异常捕获,能保证代码的整洁
1.4 抛出 raise 异常
1.4.1 应用场景
在开发中除了代码执行出错python解释器会抛出异常之外
还可以根据应用程序特有的业务需求,主动抛出异常
1.4.2 抛出异常
- python 中提供一个Exception异常类
- 在开发时,如果满足**特定业务需求时,希望抛出异常,可以:
- 1.创建一个Exception的对象
- 2.使用 raise 关键字 抛出 异常对象
def input_passward():
# 1.提示用户输入绵绵
pwd = input("请输入密码:")
# 2. 如果密码长度大于等于8,返回用户输入的密码
if len(pwd) >= 8:
return pwd
# 3. 如果 <8 主动抛出异常
print("主动抛出异常")
# 1>创建异常对象
ex = Exception("密码长度不够")
# 2>主动抛出异常
raise ex
# 提示用户输入密码
try:
print(input_passward())
except Exception as result:
print(result)
1.5 try-finally
try-finally 语句无论是否发生异常都将执行最后的代码。
try:
<语句>
finally:
<语句> #退出try时总会执行
raise
实例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
try:
fh = open("testfile", "w")
fh.write("这是一个测试文件,用于测试异常!!")
finally:
print "Error: 没有找到文件或读取文件失败"
2.模块
2.1 模块概念
模块是python 程序架构的一个核心概念
- 每一个以py结尾的python 源代码文件都是一个模块
- 模块名同样是一个标识符,需要符合标识符的命名规则
- 在模块中,定义的全局变量,函数,类都是提供给外界直接使用的工具
- 模块好比工具包,要想使用这个工具,就需要先导入这个模块
2.2 模块的两种导入方式
2.2.1 import导入
import 模块名1,模块名2
提示:在导入模块是,每个导入应该独占一行
import 模块名1
import 模块名2
导入后
- 通过 模块名. 使用模块提供的工具 --全局变量,函数,类
使用 as 指定模块的别名
如果模块的名字太长,可以使用 as 指定模块的名称,以方便在代码中的使用
import 模块1 as 模块别名
注意:模块别名符合大驼峰命名法
from … import 导入
- 如果希望从某一模块中,导入部分工具,就可以使用 form … import 的方式
- import 模块名 是一次性把模块中所有工具全局导入,并且通过模块名/别名 访问
from 模块名1 import 工具名
导入之后
- 不需要通过 模块名 .
- 可以直接使用模块提供的工具 – 全局变量,函数,类
注意:如果两个模块,存在同名的函数,那么后导入模块的函数,会覆盖掉先导入的函数
- 开发时,import 代码应该统一写在代码的顶部,更容易及时发现冲突
- 一旦发现冲突,可以使用 as 关键字 给其中一个工具起一个别名
from … import *(知道)
# 从模块 导入所有工具
from 模块名1 import *
这个方式不推荐,因为函数重名并没有任何提示,出现问题不好排查。
模块的搜索顺序[扩展]
python 的解释器在导入模块时,会:
- 搜索当前目录指定模块名的文件,如果有就直接导入
- 如果没有,再搜索系统目录
在开发时,给文件起名,不要和系统的模块文件 重名
python 中每一个模块都有一个内置属性__file__ 可以查看模块的完整路径
import random
print(random.__file__)
# 生成一个0-10 的数字
rand = random.randint(0,10)
print(rand)
注意:如果当前目录下,存在一个 random.py 的文件,程序就无法正常运行了
- 这个时候,python 的解释器会加载当前目录下的 random.py 而不会加载系统的 random 模块
2.3 原则–每一个文件都应该是可以被导入的
- 一个独立的 python文件就是一个模块
- 在导入文件时,文件中所有没有任何缩进的代码都会被执行一遍
注意:全局变量、函数、类,直接执行的代码不是外界提供的工具
文件被导入时,能够直接执行的代码不需要执行
实际开发场景:
- 在实际开发中,每一个模块都是独立开发的,大多都有专人负责
- 开发人员通常会在模块下方增加一些测试代码。
__name__属性
- __name__属性可以做到,测试模块的代码只在测试情况下被运行,而在**被导入时不会执行。
- __name__是python的一个内置属性,记录着一个字符串
- 如果是被其他文件导入时,__name__就是模块名
- 如果是当前执行的程序,__name__是 __main__
在很多python文件中都会看到以下格式的代码
#导入模块
#定义全局变量
#定义类
#定义函数
#在代码最下方
def main():
#...
pass
# 根据__name__判断是否执行下方代码
if __name__ =="__main__"
main()
2.4 包
概念:
- 包时一个包含多个模块的特殊目录
- 目录下有一个特殊的文件,__init__.py
- 包名命名方式和变量名一致,小写字母+_
好处:
- 使用 import 包名 可以一次性导入包中所有的模块
__init__.py
- 要在外界使用包中的模块,需要在__init__.py中指定对外界提供的模块列表
# 从 当前目录:hh_msg 导入 模块列表 init文件中导入
from . import sendMessage
from . import receiveMessage
外界导入当前包
import hh_msg
# 测试调用一下 send() 函数在 send_message文件中定义
hh_msg.send_message.send("hello")
2.5 发布模块
- 如果希望自己开发的模块,分享给他人,可以按照以下步骤操作:
2.5.1 只做发布压缩包步骤
1.创建setup.py文件
from distutils.core import setup
setup(name="hh_msg", #包名
version="1.0" #版本
description="mayun msg manager 发送和接受模块" #描述信息
long_description="完整的发送与接受模块" #完整错误信息
author="mayun" #作者
author_email="www.mayun.com" #主页
py_modules=["hh_msg.send_message",
"hh_msg.receive_message"]
2.构建陌路爱
- python3 setup.py build
3.生成发布压缩包
- python3 setup.py sdist
tree时,目录多了dist目录,目录下多了 hh_msg-1.0.tar.gz
2.5.2 安装模块
- $ tar -zxvf hh_msg-1.0.tar.gz
- $ sudo python3 setup.py install
卸载模块
直接从安装目录下,把安装模块的目录删除就可以了
- $ cd /usr/local/lib/python3.5
- $ sudo rm -rf hh_msg*
2.6 pip 安装第三方模块
- 第三方模块通常是指由知名的三方团队开发的,并且被程序员广泛使用的python包/模块。
例如:pygame就是一套非常成熟的游戏开发模块 - pip是一个现代的,通用的python 包管理工具
- 提供了对python包的查找,下载,安装,卸载等功能
安装卸载命名如下:
#将模块安装到 python2.x 环境
sudo pip install pygame
sudo pip uninstall pygame
# 将模块安装到 python3.x 环境
sudo pip3 install pygame
sudo pip3 uninstall pygame
3 文件
文件的作用:将数据长期保存下来,在需要的时候使用
3.1 文件的存储方式
在计算机,文件以二进制的方式保存在磁盘上
文本文件
- 可以使用文本编辑软件查案
- 本质还是二进制文件
- 例如:python 的源程序
二进制文件
- 保存的内容不是给人直接阅读的,而是提供给其他软件使用的
- 例如:图片文件,音频文件,视频文件等
- 二进制文件不能由文件编辑软件打开
3.2 文件的基本操作
在计算机中操作文件的套路非常固定,一共三个步骤:
- 打开文件
- 读写文件
- 关闭文件
操作函数的方法
在python中要操作文件,记住1个函数和3个方法
序号 | 函数/方法 | 说明 |
---|---|---|
01 | open | 打开文件,返回文件的操作对象 |
02 | read | 文件内容读取到内存 |
03 | write | 指定内容写入文件 |
04 | close | 关闭文件 |
- 如果忘记关闭文件,会造成系统资源消耗,而且会影响到后续对文件的访问
- 方法执行后,会把 文件指针 移动到文件的末尾
file = open("README.mk")
text = file.read()
print(text)
file.close()
- 在开发中,通常会先编写打开和关闭的代码,再编写中间针对文件的读/写操作
文件指针:
- 文件指针标记 从哪个位置开始读取数据
- 第一次打开文件时,通常,文件指针会指向文件的开始位置
- 当执行read方法后,文件指针会移动到读取内容的末尾
第一次读取后,文件指针移动到文件末尾,再次调用不会读取到任何内容
3.3. 打开文件的方式
open函数默认以只读方式打开文件,并且返回文件对象
语法:
f=open("文件名","访问方式")
访问方式 | 说明 |
---|---|
r | 只读打开,文件指针会放到文件的开头,默认模式,文件不存在抛出异常 |
w | 只写,文件存在会被覆盖,文件不存在则创建 |
a | 以追加方式打开,文件存在则追加,文件不存在创建新文件进行写入 |
r+ | 以读写方式打开,文件指针会放到文件开头,若未加不存在抛出异常 |
w+ | 以读写方式打开,文件存在会覆盖,文件不存在,创建新文件 |
a+ | 以读写方式打开,文件存在,文件指针放末尾,文件不存在创建文件希尔 |
- 频繁的移动文件指针,会影响文件的读写效率,开发中更多的时候会以只读、只写的方式来操作文件。
3.4 按行读取文件内容
- read 方法默认会把文件的所有内容一次性读取到内存
- 如果内容太大,会对内存的占用非常严重
readline方法
- readline 方法可以一次读取一行内容
- 方法执行后,会把文件指针移动到下一行,再准备读取
读取大文件的正确姿势
# 打开文件
file = open("readme.txt")
while True:
# 读取一行
text = file.readline()
# 判断是否读到内容
if not text:
bread
# 读取每一行,末尾加 \n
print(text,end=" ")
# 关闭文件
file.close()
3.5 文件/目录的常用管理操作
- 在终端/文件浏览器中可以执行的文件/目录管理操作,例如:
创建、重命名、删除、改变路径、查看目录内容等。。。 - 在python中,如果希望通过程序实现上述功能,需要导入os 模块
文件操作
序号 | 方法名 | 说明 | 示例 |
---|---|---|---|
01 | rename | 重命名 | os.rename(源文件名,目录文件名) |
02 | remove | 删除文件 | os.remove(文件名) |
目录操作
序号 | 方法名 | 说明 | 示例 |
---|---|---|---|
01 | listdir | 目录列表 | os.listdir(目录名) |
02 | mkdir | 创建目录 | os.mkdir(目录名) |
03 | rmdir | 删除目录 | os.rmdir(目录名) |
04 | getcwd | 获取当前目录 | os.getcwd() |
05 | chdir | 修改工作目录 | os.chdir(目标目录) |
06 | path.isdir | 判断是否是文件 | os.path.dir(文件路径) |
提示:文件或目录操作都支持相对路径和绝对路径
3.6 文本文件的编码格式
文本文件存储的内容是基于字符编码的文件,常用的编码有ASCII编码,UNICODE编码
python 2.x 默认使用 ASCII 编码
python 3.x 默认使用 UTF-8 编码
python 2.x 中如何使用中文
在python 2.x 文件的第一行 增加以下代码,解释器会以 utf-8编码来处理 python 文件
# *-* coding:utf8 *-*
这是官方推荐的,也可使用
# coding=utf8
unicode 字符串
- 早python 2.x 中,即使定义了文件使用 UTF-8 的编码格式,但是在遍历字符串时,仍会以字节为单位遍历字符串
- 要能够正确遍历字符串,在定义字符串时,需要在字符串的引号前,增加一个小写字母u,告诉解释器这是一个unicode字符串,使用UTF-8编码格式的字符串
# codeing=utf8
hello_str = u"hello 世界" #加u后,单独遍历会以utf8遍历
print(hello_Str)
for c in hello_Str:
print(c)
4 eval 函数
eval() 函数十分强大,–字符串当成有效的表达式来求值并返回计算结果。
# 基本的数据计算
In[0] :eval("1+1")
out[0]:2
# 字符串重复
In[1] :eval("'*' * 10")
out[1]:**********
# 字符串转换成列表
In[2] :type(eval("[1,2,3,4,5]"))
out[2]:list
# 将字符串转换成字典
In[3] :type(eval("{'name':'xiaoming','age':18}"))
out[3]:dict
不要滥用eval
- 在开发时,千万不要使用eval 直接转换 input 的结果
__inport__.('os').system('ls')
等价代码
import os
os.system('ls')
执行成功,返回0
执行失败,返回错误信息
5 python 读取文件
- 深度学习往往需要处理各种类型的数据,比如XML,txt,json等等。这里介绍利用Python读取文本文件内容的三种方法:read()、readline() 和 readlines()。
5.1 read()方法
read()方法表示一次读取文件全部内容,该方法返回字符串。
f = open("sxl.txt")
lines = f.read()
print lines
print(type(lines))
f.close()
5.2 readline()方法
该方法每次读出一行内容,所以,读取时占用内存小,比较适合大文件,该方法返回一个字符串对象。
f = open("sxl.txt")
line = f.readline()
while line:
print (line)
print(type(line))
line = f.readline()
f.close()
5.3 readlines()方法
readlines()方法读取整个文件所有行,保存在一个列表(list)变量中,每次读取一行,但读取大文件会比较占内存。
f = open("sxl.txt")
lines = f.readlines()
for line in lines:
print (line)
print(type(line))
f.close()
最后还有一种方式,与第三种方法类似。
f = open("sxl.txt")
print (type(f))
for line in f:
print (line)
print(type(line))
f.close()
6 python 写文件
简单的将字符串写入txt中
with open('data.txt','w') as f: #设置文件对象
f.write(str) #将字符串写入文件中
f.close()
列表写入文件
data = ['a','b','c']
#单层列表写入文件
with open("data.txt","w") as f:
f.writelines(data)
双层列表写入
#双层列表写入文件
#第一种方法,每一项用空格隔开,一个列表是一行写入文件
data =[ ['a','b','c'],['a','b','c'],['a','b','c']]
with open("data.txt","w") as f: #设置文件对象
for i in data: #对于双层列表中的数据
#将其中每一个列表规范化成字符串
i = str(i).strip('[').strip(']').replace(',','').replace('\'','')+'\n'
f.write(i) #写入文件
#第二种方法,直接将每一项都写入文件
data =[ ['a','b','c'],['a','b','c'],['a','b','c']]
with open("data.txt","w") as f: #设置文件对象
for i in data: #对于双层列表中的数据
f.writelines(i) #写入文件
数组写入文件中
#将数组写入文件
import numpy as np
#第一种方法
np.savetxt("data.txt",data) #将数组中数据写入到data.txt文件
#第二种方法
np.save("data.txt",data) #将数组中数据写入到data.txt文件
7. Python 其他
pass
- Python pass 是空语句,是为了保持程序结构的完整性。
- pass 不做任何事情,一般用做占位语句。
- 如果定义一个空函数程序会报错,当你没有想好函数的内容是可以用 pass 填充,使程序可以正常运行。
三、vi 终端编辑器
1 学习 vi 的目的
- 工作中,对服务器上文件进行简单修改,可以使用 ssh 远程登录到服务器,并使用vi 进行快速的编辑即可。
常见修改的文件包括
- 源程序配置文件,例如ssh 的配置文件 ~/.ssh/config
- 在没有图形界面环境下,要编辑文件,vi 是最佳的
2.vi 和 vim
vi 是 visual interface的简称,核心思想是 – 让程序员的手指始终保存在键盘的核心,就能完成所有的编辑操作
2.1 打开文件并且定位
vi 文件名 +行数
如果只带上 + 而不指定行号,会直接定位到文件末尾
2.2 异常处理
- 如果 vi 异常退出,在磁盘上可能会保存有交换文件
- 下次再使用vi 编辑该文件时,会看到屏幕信息,按下字母 d 可以 删除交换文件。
提示:按下键盘时,注意关闭输入法
2.3 三种模式
- 命令模式 --进行常规的编辑操作,如定位,翻页,赋值,粘贴,删除等
在其他图形界面编辑器下,通过快捷键或鼠标实现的操作,都在命令模式下编辑 - 末行模式 --执行保存、退出等操作
- 编辑模式 --正常编辑
末行模式
命令 | 因为 | 功能 |
---|---|---|
命令 | write | 保存 |
q | quit | 退出,如果没有保存,不允许退出 |
q! | quit | 强行退出,不保存 |
wq | write&quit | 保存并退出 |
x | 保存并退出 |
3.补充
3.1 3引号换行法
print('''我愿意留在汤婆婆的澡堂里工作两年,
第一年在锅炉房和锅炉爷爷一起烧锅炉水,
将在这个世界变成一头猪。
''')
输出:
我愿意留在汤婆婆的澡堂里工作两年,
第一年在锅炉房和锅炉爷爷一起烧锅炉水,
将在这个世界变成一头猪。
变量命名规范:
1、只能是一个词
2、只能包含字母、数字、下划线
3、不能以数字开头
4、尽量描述包含的数据内容
5、不要使用python函数名或关键字
四、Python技巧
5.1 创建一维二维数组
- 创建一维数组
lists = [1] * 3 #空数组 创建一维数组每个元素都为3
last_time1 = [0 for i in range(3)] - 创建二维数组
lists = [[] for i in range(3)]
lists = [[]] * 3 #错误,[[]]是一个含有一个空列表元素的列表,所以[[]]*3表示3个指向这个空列表元素的引用,修改任何一个元素都会改变整个列表。
五、numpy
numpy.mean() 计算矩阵均值
>>> a = np.array([[1, 2], [3, 4]])
>>> np.mean(a) # 将上面二维矩阵的每个元素相加除以元素个数(求平均数)
2.5
>>> np.mean(a, axis=0) # axis=0,计算每一列的均值
array([ 2., 3.])
>>> np.mean(a, axis=1) # 计算每一行的均值
array([ 1.5, 3.5])
numpy.dot
dot()返回的是两个数组的点积(dot product)
1.如果处理的是一维数组,则得到的是两数组的內积(顺便去补一下数学知识)
In : d = np.arange(0,9)
Out: array([0, 1, 2, 3, 4, 5, 6, 7, 8])
In : e = d[::-1]
Out: array([8, 7, 6, 5, 4, 3, 2, 1, 0])
In : np.dot(d,e)
Out: 84
2.如果是二维数组(矩阵)之间的运算,则得到的是矩阵积(mastrix product)。
In : a = np.arange(1,5).reshape(2,2)
Out:array([[1, 2],[3, 4]])
In : b = np.arange(5,9).reshape(2,2)
Out: array([[5, 6],[7, 8]])
In : np.dot(a,b)
Out:array([[19, 22],[43, 50]])
- 所得到的数组中的每个元素为,第一个矩阵中与该元素行号相同的元素与第二个矩阵与该元素列号相同的元素,两两相乘后再求和。
3.dot()函数可以通过numpy库调用,也可以由数组实例对象进行调用。a.dot(b) 与 np.dot(a,b)效果相同。
- 矩阵积计算不遵循交换律,np.dot(a,b) 和 np.dot(b,a) 得到的结果是不一样的。
np.identity
这个函数和之前的区别在于,这个只能创建方阵,也就是N=M
函数的原型:np.identity(n,dtype=None)
参数:n,int型表示的是输出的矩阵的行数和列数都是n
dtype:表示的是输出的类型,默认是float
返回的是nxn的主对角线为1,其余地方为0的数组
import numpy as np
a=np.identity(3)
print(a)
结果:
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
六 xlsx
#!/use/bin/python
#coding=utf-8
import numpy as np
import openpyxl
import os
import sys
def LoadDatasTxt(txt_path):
print("laod_txt_path:%s!" % txt_path)
load_txt_datas = None
with open(txt_path,'r') as f :
load_txt_datas = np.loadtxt(f,delimiter=" ",dtype="string",comments="#",
skiprows=0, usecols=None)
print("load_txt_datas_size:%d" % len(load_txt_datas))
f.close()
print("load_txt_size:%d" % len(load_txt_datas))
return load_txt_datas
def SaveDatasToTxt(datas,path):
print("load_xl_path :%s" % path)
with open(path,'w') as fout:
for data in datas:
data_str ="".join((str(x)+" ") for x in data)
fout.write(data_str+'\n')
fout.close()
def SaveDatasToXLOne(datas,path):
print("save xsls path: %s" % path)
xl_wb = openpyxl.Workbook()
xl_ws = xl_wb.active
xl_ws.title = "cost_time"
for index_datas in range(len(datas)):
data = datas[index_datas] # 提示 :Row or column values must be at least 1,即最小值为1.
xl_ws.cell(row=(index_datas+1), column=(1)).value= data
xl_wb.save(path)
def SaveDatasToXL(datas,path):
print("save xslsss path: %s" % path)
xl_wb = openpyxl.Workbook()
xl_ws = xl_wb.active
xl_ws.title = "cost_time"
for index_datas in range(len(datas)):
for index in range(len(datas[index_datas])):
data = datas[index_datas][index]
# 提示 :Row or column values must be at least 1,即最小值为1.
xl_ws.cell(row=(index_datas+1), column=(index+1)).value= data
xl_wb.save(path)
def LoadDatasXL(path):
print("load xsls path: %s" % path)
"""
load_xl 函数原型
openpyxl.reader.excel.load_workbook(filename,read_only=False,
use_iterators=False, keep_vba=False,
guess_types=False, data_only=False)
"""
wb = openpyxl.reader.excel.load_workbook(path)
#wb = openpyxl.reader.excel.load_workbook(filename=ExcelFullName)
# 获取当前活跃的worksheet,默认就是第一个worksheet
# ws = wb.active
# rows = ws.rows
# columns = ws.columns
# print(rows,columns)
# 当然也可以使用下面的方法
# 获取所有表格(worksheet)的名字
sheets = wb.get_sheet_names()
print("sheet_names:%s" % sheets)
# # 第一个表格的名称
sheet_first = sheets[0]
# # 获取特定的worksheet
ws = wb.get_sheet_by_name(sheet_first)
print("***")
print(sheet_first)
print(ws.title)
print("^^^")
# 通过坐标读取值
print(ws['A1'].value)# A表示列,1表示行
print(ws.cell(row=1, column=1).value)
# 获取表格所有行和列,两者都是可迭代的
rows = ws.rows
columns = ws.columns
# print("load xls rows:%s,cols:%s !" % (rows,columns))
print("load xls rows:%d,cols:%d !" % (len(rows),len(columns)))
print("迭代所有的行")
# 迭代所有的行
load_xls_datas =[]
for row in rows:
line = [col.value for col in row]
# print(line)
load_xls_datas.append(line)
return load_xls_datas
if __name__ == "__main__":
print("argv_len:%d" % (len(sys.argv)))
load_txt_path = "cost_time.txt"
if len(sys.argv)==2:
load_txt_path = sys.argv[1]
print(load_txt_path)
load_txt_datas = LoadDatasTxt(load_txt_path)
save_xsls_path = "cost_time_1.xlsx"
SaveDatasToXL(load_txt_datas,save_xsls_path)
load_xl_datas = save_xsls_path
load_xl_datas = LoadDatasXL(load_xl_datas)
save_txt_path = "cost_time_xl.txt"
SaveDatasToTxt(load_xl_datas,save_txt_path)
print("finish test ok!")````