环境准备
解释器
Python是一门解释型语言。
常见的解释器有如下几种
- CPython,基于C语言开发的解释器。
- IPython,基于CPython的一种交互式解释器。
- PyPy,基于Python语言开发的解释器。
- Jython,运行在Java平台的解释器。
- IronPython,运行在微软.Net平台上的Python解释器。
我们所使用的解释器是CPython,这也是官方的解释器,应用广泛的解释器
下载地址:https://www.python.org
PyCharm
PyCharm,一种IDE。
下载地址:https://www.jetbrains.com/pycharm
PyCharm专业版是收费的,只能体验30天。也与IDEA一样,存在延长体验期的方法。
具体方法可以参考《基于Java的后端开发入门:1.基础语法》,关于"安装IDEA"的部分。
Anaconda
Anaconda,如果我们要用Jupyter(.ipynb
格式的文件)的话,强烈建议Anaconda,PyCharm虽然也支持,但是极其难用,而且性能低下。
官网不一定能打开,可以考虑镜像站。
清华镜像:https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/
阿里镜像:https://mirrors.aliyun.com/anaconda/
VS-Code
还可以在VS-Code上运行Python。
安装插件Python extension for Visual Studio Code
https://marketplace.visualstudio.com/items?itemName=ms-python.python
我个人认为,.ipynb
在VS-Code上的体验更好。
点击红框之处,选择Python的解释器。
注释
Python中的注释分为两类:
- 单行注释
- 多行注释
单行注释
单行注释,只能注释一行内容,格式如下:
1 | # 注释内容 |
多行注释
多行注释,可以注释多行内容,格式如下,单引号和双引号均可。
1 | """ |
1 | ''' |
变量
定义变量
格式
定义一个变量的格式如下:
1 | 变量名 = 值 |
命名规则
在Python中,定义各种名字的时候有统一的规范,具体如下:
- 由数字、字母、下划线组成
- 不能数字开头
- 严格区分大小写
- 不能使用内置关键字
常见的内置关键字有:False
、None
、True
、and
、 as
、 assert
、break
、class
、continue def
、del
、elif
、else
、except
、finally
、for
、from
、 global if
、import
、in
、 is
、 lambda
、nonlocal
、not
、 or
、 pass
、raise
、return
、try
、 while
、with
、yield
。
数据类型
Python中的数据类型有:
- 整型:
int
- 浮点型:
float
- 字符串:
str
- 布尔型:
bool
- 元组:
tuple
- 列表:
list
- 集合:
set
- 字典:
dict
前五种,为不可变类型
后三种,为可变类型
前五种中,除了元祖,其他四种,其不可变的现象,有点类似Java或者JavaScript中的基本数据类型。
(为什么要除了元祖?我们在下文讨论元祖的是会解释。)
后三种,有点类似Java的引用数据类型。
我们可以通过type()
查看某个变量的数据类型。
示例代码:
1 | a = 1 |
运行结果:
1 | <class 'int'> |
打印
打印方法
print
,在控制台打印内容。
格式化
格式化,即按照一定的格式输出内容。
格式符号 | 转换 |
---|---|
%s |
字符串 |
%d |
有符号的十进制整数 |
%f |
浮点数 |
技巧
%06d
:表示输出的整数显示位数,不足以0补全,超出当前位数则原样输出%.2f
:表示小数点后显示的小数位数。- 格式化字符串除了
%s
,还可以写为f'{表达式}'
,例如print(f'我的名字是{name}, 明年{age + 1}岁了')
。
示例代码:
1 | age = 18 |
运行结果:
1 | 我的名字是TOM |
转义字符
\n
:换行。
\t
:制表符,一个tab键(4个空格)的距离。
结束符
注意看,我们的每一个print都自动换行了。
因为,在Python中,print(), 默认自带end="\n"
这个换行结束符。
1 | print('输出的内容', end="\n") |
如果不想换行,可以指定end
参数为空字符串。
1 | print('输出的内容', end="") |
缓存机制
例如,我们执行nohup python3.x abc.py &
。
一般理解,print的内容能及时输出到nohup.out中,但可能几十分钟都没更新。
因为,python的print是有缓存机制的,要想直接立即输出,则带上-u
参数即可,如下:
1 | nohup python3.x -u abc.py & |
(关于nohup
的作用,可以参考《Linux操作系统使用入门:2.命令》。)
数据类型转换
在上文,我们讨论了八种数据类型。接下来,我们介绍数据类型之间的转换。
方法 | 说明 |
---|---|
int(x[,base]) |
转换为一个整数 |
float(x) |
转换为一个浮点数 |
complex(real[,imag]) |
创建一个复数,real为实部,imag为虚部 |
str(x) |
转换为字符串 |
repr(x) |
将对象 x 转换为表达式字符串 |
eval(str) |
计算在字符串中的有效Python表达式,并返回一个对象 |
tuple(s) |
将序列转换为元组 |
list(s) |
将序列转换为列表 |
chr(x) |
将一个整数转换为一个Unicode字符 |
ord(x) |
将一个字符转换为它的ASCII整数值 |
hex(x) |
将一个整数转换为一个十六进制字符串 |
oct(x) |
将一个整数转换为一个八进制字符串 |
bin(x) |
将一个整数转换为一个二进制字符串 |
- 其中加粗部分为常用的方法。
示例代码:
1 | # 1. float() -- 转换成浮点型 |
运行结果:
1 | 1.0 |
示例代码:
1 | # 整数之间的进制转换 |
运行结果:
1 | 0x10 |
运算符
常见的运算符有五类:
- 算数运算符
- 赋值运算符
- 比较运算符
- 逻辑运算符
- 三目运算符
算数运算符
运算符 | 描述 | 实例 |
---|---|---|
+ |
加 | 1+1 ,输出结果为 2 |
- |
减 | 1-1 ,输出结果为 0 |
* |
乘 | 2*2 ,输出结果为 4 |
/ |
除 | 10/2 ,输出结果为 5 |
// |
整除 | 9//4 ,输出结果为 2 |
% |
取余 | 9%4 ,输出结果为 1 |
** |
指数 | 2**4 ,输出结果为 16 |
- 可以利用小括号
()
来提高运算优先级。
赋值运算符
运算符 | 描述 | 实例 |
---|---|---|
= |
赋值 | 将= 右侧的结果赋值给等号左侧的变量 |
+= |
加后赋值 | c+=a 等价于 c=c+a |
-= |
减后赋值 | c-=a 等价于 c=c-a |
*= |
乘后赋值 | c*=a 等价于 c=c*a |
/= |
除后赋值 | c/=a 等价于 c=c/a |
//= |
整除后赋值 | c//=a 等价于 c=c//a |
%= |
取余后赋值 | c%=a 等价于 c=c%a |
**= |
幂后赋值 | c**=a 等价于 c=c**a |
关于赋值运算符,还有一些操作,比如多个变量赋值、多变量赋相同值。
多个变量赋值
示例代码:
1 | num1, float1, str1 = 10, 0.5, 'hello world' |
多变量赋相同值
示例代码:
1 | a = b = 10 |
但是,非常不建议这么做,降低了代码的可读性。
比较运算符
比较运算符,也被称为关系运算符。
运算符 | 描述 |
---|---|
== |
判断是否相等。 |
!= |
判断是否不相等 |
> |
左侧操作数是否大于右侧操作数 |
< |
左侧操作数是否小于右侧操作数 |
>= |
左侧操作数是否大于等于右侧操作数 |
<= |
左侧操作数是否小于等于右侧操作数 |
逻辑运算符
与、或、非
运算符 | 逻辑表达式 | 说明 |
---|---|---|
and |
x and y |
与 |
or |
x or y |
或 |
not |
not x |
非 |
示例代码:
1 | a = 1 |
运行结果:
1 | True |
在Java中,有逻辑运算符和短路逻辑运算符。但在Python中,只有逻辑运算符。Python中的逻辑运算符对应的就是Java中的短路逻辑运算符。
短路是指,在逻辑与运算中,只要有一个表达式的值为false,那么结果就可以判定为false了,不会将所有表达式的值都计算出来。同理在逻辑或运算中,一旦发现值为true,右边的表达式将不再参与运算。
and
:如果左边为真,右边执行;如果左边为假,右边不执行。
or
:如果左边为假,右边执行;如果左边为真,右边不执行。
在JavaScript中,也只有逻辑运算符,JavaScript中的逻辑运算符对应的就是Java中的短路逻辑运算符。
数字之间的逻辑运算
and
,只要有一个值为0,则结果为0,否则结果为最后一个非0数字。
or
,只有所有值为0结果才为0,否则结果为第一个非0数字。
示例代码:
1 | a = 0 |
运行结果:
1 | 0 |
三目运算符
三目运算符,也被称为三元运算符。
属于条件语句的一种。
(所以有些资料会在讨论条件语句的时候,讨论三目运算符,我们放在运算符这里讨论。)
语法如下:
1 | 值一 if 条件 else 值二 |
- 满足条件,值一
- 不满足条件,值二
示例代码:
1 | a = 1 |
运行结果:
1 | 2 |
条件
if
1 | if 条件: |
示例代码:
1 | if True: |
运行结果:
1 | 条件成立执行的代码1 |
if-else
条件成立执行if下方的代码; 条件不成立执行else下方的代码。
1 | if 条件: |
if-elif
1 | if 条件1: |
if-elif
,也可以和else
配合使用。
判断规则
0
为False
,其他所有数值皆为True
。- 空串(
""
)为False
,其他所有字符串皆为True
。 - 空list(
[]
)为False
,其他所有list皆为True
。 - 空tuple(
()
)为False
,其他所有tuple皆为True
。 - 空dict(
{}
)为False
,其他所有dcit皆为True
。 - 函数也可以作为参数,函数为
True
循环
while
1 | while 条件: |
示例代码:
1 | i = 1 |
运行结果:
1 | 5050 |
break和continue
break
,结束循环。
continue
,跳出当前循环,执行下一次循环。
示例代码:
1 | i = 1 |
运行结果:
1 | 吃了第1个苹果 |
示例代码:
1 | i = 1 |
运行结果:
1 | 吃了第1个苹果 |
特别注意:在continue
之前一定要修改计数器,否则会陷入死循环。
for
1 | for 临时变量 in 序列: |
示例代码:
1 | s = '菜刀门菜刀门菜刀门' |
运行结果:
1 | 菜 |
range
range(start, end, step)
,生成从start到end的数字(不包含end),步长为 step,供for循环使用。
示例代码:
1 | # 1 2 3 4 5 6 7 8 9 |
运行结果:
1 | 1 2 3 4 5 6 7 8 9 |
while-else
1 | while 条件: |
示例代码:
1 | i = 1 |
运行结果:
1 | 菜刀门 |
特别注意,break
的话,不会执行else
的语句,因为不属于正常的循环结束。
示例代码:
1 | i = 1 |
运行结果:
1 | 菜刀门 |
但是continue
可以,因为continue
只是结束当前循环,进入下一次循环。
示例代码:
1 | i = 1 |
运行结果:
1 | 菜刀门 |
for-else
1 | for 临时变量 in 序列: |
for-else
与while-else
类似,不赘述。
zip
提到了循环,就不得不讨论zip
。
zip与for循环
示例代码:
1 | names = ["A", "B", "C"] |
运行结果:
1 | A 11 |
不同长度的Lists
zip若遇到不同长度的list时,会以长度最短的list为准,超过长度的部分回被舍弃。
示例代码:
1 | names2 = ["A", "B", "C"] |
运行结果:
1 | A 11 |
若要以长度最长的list为准,可以改用zip_longest
,长度不足的list会以None补足。
示例代码:
1 | from itertools import zip_longest |
运行结果:
1 | A 11 |
字符串
什么是字符串
字符串是Python中最常用的数据类型,一般使用引号来创建字符串,单引号和双引号均可。
示例代码:
1 | a = 'hello world' |
运行结果:
1 | <class 'str'> |
字符串的分类
一对引号字符串
这也是我们最常见的字符串
1 | name1 = 'Tom' |
三引号字符串
三引号形式的字符串支持换行。
但这种方式一般不用,因为代码的可读性不强。
如果需要换行的话,更多时候利用转义字符\n
。
示例代码:
1 | name3 = '''Tom''' |
运行结果:
1 | Tom |
下标
下标
,也被称为索引
。
示例代码:
1 | s = "你爹回来了" |
运行结果:
1 | 爹 |
切片
切片是指对操作的对象截取其中一部分的操作。
字符串、列表、元组都支持切片操作。
1 | 序列[开始位置下标:结束位置下标:步长] |
注意:
- 不包含结束位置下标对应的数据
- 步长是选取间隔,默认为
1
示例代码:
1 | name = "abcdefg" |
运行结果:
1 | cde |
查找
find
find()
,检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则返回-1。
1 | 字符串序列.find(子串, 开始位置下标, 结束位置下标) |
- 开始和结束位置下标可以省略,表示在整个字符串序列中查找。
示例代码:
1 | mystr = "hello world and Python and Java and JavaScript" |
运行结果:
1 | 12 |
index
index()
:检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则报异常。
1 | 字符串序列.index(子串, 开始位置下标, 结束位置下标) |
- 开始和结束位置下标可以省略,表示在整个字符串序列中查找。
示例代码:
1 | mystr = "hello world and Python and Java and JavaScript" |
运行结果:
1 | 12 |
count
count()
,返回某个子串在字符串中出现的次数。
1 | 字符串序列.count(子串, 开始位置下标, 结束位置下标) |
- 开始和结束位置下标可以省略,表示在整个字符串序列中查找。
示例代码:
1 | mystr = "hello world and Python and Java and JavaScript" |
运行结果:
1 | 3 |
rfind
rfind()
,和find()
功能相同,但查找方向为右侧开始。
rindex
rindex()
,和index()
功能相同,但查找方向为右侧开始。
修改
replace
replace()
,替换。
1 | 字符串序列.replace(旧子串, 新子串, 替换次数) |
默认会替换字符串中的所有符合条件的字符串。
示例代码:
1 | mystr = "hello world and Python and Java and JavaScript" |
运行结果:
1 | hello world he Python he Java he JavaScript |
解释说明:
数据按照是否能直接修改分为可变类型和不可变类型两种。字符串类型的数据修改的时候不能改变原有字符串,属于不能直接修改数据的类型,即不可变类型。
split
split()
,按照指定字符分割字符串。
1 | 字符串序列.split(分割字符, num) |
num
表示的是分割字符出现的次数,即返回数据个数为num+1
个。
示例代码:
1 | mystr = "hello world and Python and Java and JavaScript" |
运行结果:
1 | ['hello world ', ' Python ', ' Java ', ' JavaScript'] |
join
join()
,将多个字符串合并为一个新的字符串。
1 | 字符或子串.join(多字符串组成的序列) |
示例代码:
1 | l = ['a', 'b', 'c', 'd'] |
运行结果:
1 | a_b_c_d |
特别注意:不但对list有效,有元祖也有效。
lower
lower()
:将字符串中大写转小写。
示例代码:
1 | mystr = "hello world and Python and Java and JavaScript" |
运行结果:
1 | hello world and python and java and javascript |
upper
upper()
:将字符串中小写转大写。
示例代码:
1 | mystr = "hello world and Python and Java and JavaScript" |
运行结果:
1 | HELLO WORLD AND PYTHON AND JAVA AND JAVASCRIPT |
capitalize
capitalize()
:将字符串第一个字符转换成大写,其他字符都小写。
示例代码:
1 | mystr = "hello world and Python and Java and JavaScript" |
运行结果:
1 | Hello world and python and java and javascript |
title
title()
:将字符串每个单词首字母转换成大写。
示例代码:
1 | mystr = "hello world and Python and Java and JavaScript" |
运行结果:
1 | Hello World And Python And Java And Javascript |
ljust
ljust()
:返回一个原字符串左对齐,并使用指定字符(默认空格)填充至对应长度的新字符串。
1 | 字符串序列.ljust(长度, 填充字符) |
示例代码:
1 | print('1'.ljust(10, '0')) |
运行结果:
1 | 1000000000 |
rjust
rjust()
:返回一个原字符串右对齐,并使用指定字符(默认空格)填充至对应长度的新字符串,语法和ljust()
相同。
示例代码:
1 | print('1'.rjust(10, '0')) |
运行结果:
1 | 0000000001 |
center
center()
:返回一个原字符串居中对齐,并使用指定字符(默认空格)填充至对应长度的新字符串,语法和ljust()相同。
示例代码:
1 | print('1'.center(10, '0')) |
运行结果:
1 | 0000100000 |
lstrip
lstrip()
:删除字符串左侧空白字符。
rstrip
rstrip()
:删除字符串右侧空白字符。
strip
strip()
:删除字符串两侧空白字符。
判断
startswith
startswith()
:检查字符串是否是以指定子串开头,是则返回True
,否则返回False
。如果设置开始和结束位置下标,则在指定范围内检查。
1 | 字符串序列.startswith(子串, 开始位置下标, 结束位置下标) |
示例代码:
1 | mystr = "hello world and Python and Java and JavaScript" |
运行结果:
1 | True |
endswith
endswith()
:检查字符串是否是以指定子串结尾,是则返回True
,否则返回False
。如果设置开始和结束位置下标,则在指定范围内检查。
1 | 字符串序列.endswith(子串, 开始位置下标, 结束位置下标) |
示例代码:
1 | mystr = "hello world and Python and Java and JavaScript" |
运行结果:
1 | True |
isalpha
isalpha()
:如果字符串只包含字母则返回True
, 否则返回False
。
示例代码:
1 | mystr1 = 'hello' |
运行结果:
1 | True |
isdigit
isdigit()
:如果字符串只包含数字则返回True
否则返回False
。
示例代码:
1 | mystr1 = 'aaa12345' |
运行结果:
1 | False |
isalnum
isalnum()
:如果字符串只包含字母或数字则返回True
,否则返回False
。
示例代码:
1 | mystr1 = 'aaa12345' |
运行结果:
1 | True |
isspace
isspace()
:如果字符串中只包含空白,则返回True
,否则返回False
。
示例代码:
1 | mystr1 = '1 2 3 4 5' |
运行结果:
1 | False |
列表
什么是列表
1 | [数据一, 数据二, 数据三, 数据四......] |
列表可以一次性存储多个数据,且可以为不同数据类型。
查找
根据下标查找
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | Tom |
index
index()
:返回指定数据所在位置的下标,如果查找的数据不存在则报错。
1 | 列表序列.index(数据, 开始位置下标, 结束位置下标) |
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | 1 |
count
count()
:统计指定数据在当前列表中出现的次数。
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | 1 |
len
len()
:访问列表长度,即列表中数据的个数。
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | 3 |
in
in
:判断指定数据在某个列表序列,如果在返回True
,否则返回False
。
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | True |
not in
not in
:判断指定数据不在某个列表序列,如果不在返回True
,否则返回False
。
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | False |
增加
append
append()
:列表结尾追加数据。
1 | 列表序列.append(数据) |
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | ['Tom', 'Lily', 'Rose', 'xiaoming'] |
解释说明:列表追加数据的时候,是直接在原列表里面追加了指定数据,即可变类型数据。
特别的,如果我们append一个序列呢?
因为列表中的元素的类型可以不一样,那么你append一个序列,就是append一个序列了。
不报错,也不会神奇的帮我们合并。
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | ['Tom', 'Lily', 'Rose', ['xiaoming', 'xiaohong']] |
那么,如果我们想把两个List合并怎么办呢?extentd
,或者直接+
。
extend
extend()
:在列表结尾,以遍历的方式追加数据,所以要求被extend的数据必须可以被遍历。
1 | 列表序列.extend(数据) |
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | ['Tom', 'Lily', 'Rose', 'x', 'i', 'a', 'o', 'm', 'i', 'n', 'g'] |
解释说明:字符串也被认为是序列。
那么,我们apped一个int类型的数据可以吗?
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | TypeError: 'int' object is not iterable |
解释说明,不可以,因为int类型不能被遍历。
但是用元祖可以。
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | ['Tom', 'Lily', 'Rose', 100] |
最后,我们讨论一下用extend合并list。
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | ['Tom', 'Lily', 'Rose', 'xiaoming', 'xiaohong'] |
也可以直接+
,示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | ['Tom', 'Lily', 'Rose', 'xiaoming', 'xiaohong'] |
insert
insert()
:指定位置新增数据。
1 | 列表序列.insert(位置下标, 数据) |
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | ['Tom', 'xiaoming', 'Lily', 'Rose'] |
删除
del
语法
1 | del 目标 |
我个人更喜欢del()
风格,因为这个更像是程序语言。
del
,空格,然后跟上想被del
的对象,像命令,不像程序语言。
删除整个列表
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | NameError: name 'name_list' is not defined |
删除指定数据
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | ['Lily', 'Rose'] |
pop
pop()
:删除指定下标的数据(默认为最后一个),并返回该数据。
1 | 列表序列.pop(下标) |
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | Lily |
remove
remove()
:移除列表中某个数据的第一个匹配项。即使有多个的话,也只会移除第一个。
1 | 列表序列.remove(数据) |
示例代码:
1 | name_list = ['Tom', 'Rose', 'Lily', 'Rose', 'Rose'] |
运行结果:
1 | ['Tom', 'Lily', 'Rose', 'Rose'] |
clear
clear()
:清空列表。
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | [] |
修改
修改指定下标数据
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | ['aaa', 'Lily', 'Rose'] |
逆置
reverse()
,逆置。
示例代码:
1 | num_list = [1, 5, 2, 3, 6, 8] |
运行结果:
1 | [8, 6, 3, 2, 5, 1] |
sort
sort()
,排序。
1 | 列表序列.sort( key=None, reverse=False) |
reverse
表示排序规则reverse=True
降序reverse=False
升序(默认)
示例代码:
1 | num_list = [1, 5, 2, 3, 6, 8] |
运行结果:
1 | [1, 2, 3, 5, 6, 8] |
复制
复制?
来吧!
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | ['Tom', 'Lily', 'Rose'] |
修改name_li2
,name_list
也被改了?
这不对啊。
来,再试一下。
copy()
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | ['Tom', 'Lily', 'Rose'] |
列表是可变类型。
如果我们把可变数据类型看做Java或JavaScript中的引用数据类型的话,就特别容易理解为啥第一种情况,修改name_li2
,name_list
也被改了。
关于该部分,在《3.拷贝、类型注解、闭包、装饰器和一些常用的包》的"内存结构、拷贝和深拷贝"部分,有更多讨论。
遍历
while
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | Tom |
for
示例代码:
1 | name_list = ['Tom', 'Lily', 'Rose'] |
运行结果:
1 | Tom |
列表嵌套
所谓列表嵌套指的就是一个列表里面包含了其他的子列表。
1 | name_list = [['小明', '小红', '小绿'], ['Tom', 'Lily', 'Rose'], ['张三', '李四', '王五']] |
那么,如何查找到数据"李四"呢?
示例代码:
1 | name_list = [['小明', '小红', '小绿'], ['Tom', 'Lily', 'Rose'], ['张三', '李四', '王五']] |
运行结果:
1 | ['张三', '李四', '王五'] |
元组
应用场景
如果想要存储多个数据,但是这些数据是不能修改的数据,怎么做?
列表?列表可以一次性存储多个数据,但是列表中的数据允许更改。
元祖!一个元组可以存储多个数据,元组内的数据是不能修改的。
定义元组
元组特点:定义元组使用"小括号","逗号"隔开各个数据,数据可以是不同的数据类型。
1 | # 多个数据元组 |
注意:如果定义的元组只有一个数据,那么这个数据后面也要添加逗号。
示例代码:
1 | t2 = (10,) |
运行结果:
1 | <class 'tuple'> |
查找
按下标查找数据
示例代码:
1 | tuple1 = ('aa', 'bb', 'cc', 'bb') |
运行结果:
1 | aa |
index
index()
:查找某个数据,如果数据存在返回对应的下标,否则报错。
语法和列表、字符串的index方法相同。
示例代码:
1 | tuple1 = ('aa', 'bb', 'cc', 'bb') |
运行结果:
1 | 0 |
如果不存在的话,会报错。
我们知道,有一个不会报错的好东西,find
。
很可惜,这个在元祖中没有。
示例代码:
1 | tuple1 = ('aa', 'bb', 'cc', 'bb') |
运行结果:
1 | AttributeError: 'tuple' object has no attribute 'find' |
in
但是,可以用in
。示例代码:
1 | tuple1 = ('aa', 'bb', 'cc', 'bb') |
运行结果:
1 | False |
count
count()
:统计某个数据在当前元组出现的次数。
示例代码:
1 | tuple1 = ('aa', 'bb', 'cc', 'bb') |
运行结果:
1 | 2 |
len
len()
:统计元组中数据的个数。
示例代码:
1 | tuple1 = ('aa', 'bb', 'cc', 'bb') |
运行结果:
1 | 4 |
修改
“元祖中不能被修改”,如果一定要修改,会报错。
示例代码:
1 | tuple1 = ('aa', 'bb', 'cc', 'bb') |
运行结果:
1 | TypeError: 'tuple' object does not support item assignment |
示例代码:
1 | tuple1 = ('aa', 'bb', 'cc', 'bb') |
运行结果:
1 | TypeError: 'tuple' object doesn't support item deletion |
但是如果元组里面有列表等可变数据类型,可变数据类型中的数据可以被修改。
(把可变数据类型,理解为Java或JavaScript中的引用数据类型,就特别容易理解这个特性。)
示例代码:
1 | tuple2 = [10, 20, ['aa', 'bb', 'cc'], 50, 30, {}] |
运行结果:
1 | [10, 20, ['aa', 'bb', 'cc'], 50, 30, {}] |
字典
创建字典
字典特点:
- 花括号:
{
}
- 数据为"键值对"形式出现
- 各个键值对之间用"逗号"隔开
示例代码:
1 | dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} |
运行结果:
1 | {'name': 'Tom', 'age': 20, 'gender': '男'} |
增加
如果key存在则修改这个key对应的值;如果key不存在则新增此键值对。
1 | 字典序列[key] = 值 |
示例代码:
1 | dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} |
运行结果:
1 | {'name': 'Rose', 'age': 20, 'gender': '男'} |
解释说明:字典为可变类型。
删除
del
del
或del()
,删除字典或删除字典中指定键值对。
示例代码:
1 | dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} |
运行结果:
1 | {'name': 'Tom', 'age': 20} |
clear
clear()
:清空字典。
示例代码:
1 | dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} |
运行结果:
1 | {} |
修改
如果key存在则修改这个key对应的值;如果key不存在则新增此键值对。
1 | 字典序列[key] = 值 |
查询
key值查找
示例代码:
1 | dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} |
运行结果:
1 | Tom |
解释说明:如果当前查找的key存在,则返回对应的值;不存在就报错。
get
get()
1 | 字典序列.get(key, 默认值) |
- 如果当前查找的key不存在则返回第二个参数(默认值),如果省略第二个参数,则返回None。
示例代码:
1 | dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} |
运行结果:
1 | Tom |
keys
keys()
示例代码:
1 | dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} |
运行结果:
1 | dict_keys(['name', 'age', 'gender']) |
values
values()
示例代码:
1 | dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} |
运行结果:
1 | dict_values(['Tom', 20, '男']) |
items
示例代码:
1 | dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} |
运行结果:
1 | dict_items([('name', 'Tom'), ('age', 20), ('gender', '男')]) |
遍历
遍历字典的key
示例代码:
1 | dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} |
运行结果:
1 | name |
遍历字典的value
示例代码:
1 | dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} |
运行结果:
1 | Tom |
遍历字典的元素
示例代码:
1 | dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} |
运行结果:
1 | ('name', 'Tom') |
遍历字典的键值对
示例代码:
1 | dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'} |
运行结果:
1 | name = Tom |
zip
zip
,除了和for循环配合使用,还可以用来快速的基于列表创建字典。
示例代码:
1 | keys = ["tw", "us", "it"] |
运行结果:
1 | {'tw': 2.1, 'us': 3.8, 'it': 6.9} |
集合
创建集合
创建集合使用{}
或set()
, 但是如果要创建空集合只能使用set()
,因为{}
用来创建空字典。
示例代码:
1 | s1 = {10, 20, 30, 40, 50} |
运行结果:
1 | {40, 10, 50, 20, 30} |
集合特点
- 集合可以去掉重复数据;
- 集合数据是无序的,故不支持下标
增加
add
add()
示例代码:
1 | s1 = {10, 20} |
运行结果:
1 | {100, 10, 20} |
update
如果追加的数据是序列,可以用update()
。
示例代码:
1 | s1 = {10, 20} |
运行结果:
1 | {100, 10, 20, 200} |
删除
remove()
,删除集合中的指定数据,如果数据不存在则报错。
示例代码:
1 | s1 = {10, 20} |
运行结果:
1 | {20} |
discard
discard()
,删除集合中的指定数据,如果数据不存在不会报错。
示例代码:
1 | s1 = {10, 20} |
运行结果:
1 | {20} |
pop
pop()
,随机删除集合中的某个数据,并返回这个数据。
(其实不是随机的,是有规律的。但在实际应用中,和随机差不多。)
示例代码:
1 | s1 = {10, 20, 30, 40, 50} |
运行结果:
1 | {40, 10, 50, 20, 30} |
查找
in
:判断数据在集合序列。
not in
:判断数据不在集合序列。
示例代码:
1 | s1 = {10, 20, 30, 40, 50} |
运行结果:
1 | True |
容器的操作
在上述,我们讨论了三种序列,分别是列表、元祖以及字符串。还有两种序列的,集合和字典。
这五种,我们合称为容器。
"容器"这名字,是我取的。在其他资料上,应该没有这个名字。
运算符
常见运算符
运算符 | 描述 | 支持的容器类型 |
---|---|---|
+ |
合并 | 字符串、列表、元组 |
* |
重复 | 字符串、列表、元组 |
in |
元素是否存在 | 字符串、列表、元组、字典 |
not in |
元素是否不存在 | 字符串、列表、元组、字典 |
+
示例代码:
1 | # 1. 字符串 |
运行结果:
1 | aabb |
*
示例代码:
1 | # 1. 字符串 |
运行结果:
1 | ---------- |
in或not in
示例代码:
1 | # 1. 字符串 |
运行结果:
1 | True |
方法
常见方法
函数 | 描述 |
---|---|
len() |
计算容器中元素个数 |
max() |
返回容器中元素最大值 |
min() |
返回容器中元素最小值 |
enumerate() |
将一个可遍历的数据对象,组合为一个索引序列,同时列出数据和数据下标(元祖的形式)。 |
len()
示例代码:
1 | # 1. 字符串 |
运行结果:
1 | 7 |
max
max()
示例代码:
1 | # 1. 字符串 |
运行结果:
1 | g |
min
min()
示例代码:
1 | # 1. 字符串 |
运行结果:
1 | a |
enumerate()
1 | enumerate(可遍历对象, start=0) |
start
参数用来设置遍历数据的下标的起始值,默认为0
。
示例代码:
1 | list1 = ['a', 'b', 'c', 'd', 'e'] |
运行结果:
1 | (0, 'a') |
类型转换
容器类之间,可以进行类型转换。
tuple
tuple()
,转换成元组
示例代码:
1 | list1 = [10, 20, 30, 40, 50, 20] |
运行结果:
1 | (10, 20, 30, 40, 50, 20) |
list
list()
,转换成列表。
示例代码:
1 | tuple1 = (10, 20, 30, 40, 50, 20) |
运行结果:
1 | [10, 20, 30, 40, 50, 20] |
set
set()
,转换成集合。
示例代码:
1 | list1 = [10, 20, 30, 40, 50, 20] |
运行结果:
1 | {40, 10, 50, 20, 30} |
str
str
,转换成字符串
这个可以是可以,但是可能和我们预期的效果不一样。
示例代码:
1 | list1 = [10, 20, 30, 40, 50, 20] |
运行结果:
1 | <class 'str'> |
例如,想将t1 = ('a', 'b', 'c', 'd', 'e')
转成字符串,可以考虑.join
运算。示例代码:
1 | t1 = ('a', 'b', 'c', 'd', 'e') |
运行结果:
1 | abcde |
但对于字典,需要关注其顺序。示例代码:
1 | s1 = {'a', 'b', 'c'} |
运行结果:
1 | bca |
推导式
列表推导式
列表推导式,也被称为列表生成式。其作用是用一个表达式创建一个有规律的列表或控制一个有规律列表。
创建一个0-10的列表
例如,创建一个0-10的列表。
示例代码:
1 | list1 = [i for i in range(10)] |
运行结果:
1 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] |
带if的列表推导式
例如,创建0-10的偶数列表
方法一:range()步长实现。
示例代码:
1 | list1 = [i for i in range(0, 10, 2)] |
运行结果:
1 | [0, 2, 4, 6, 8] |
方法二:if实现
示例代码:
1 | list1 = [i for i in range(10) if i % 2 == 0] |
运行结果:
1 | [0, 2, 4, 6, 8] |
多个for循环实现列表推导式
例如,创建列表如下:
1 | [(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] |
示例代码:
1 | list1 = [(i, j) for i in range(1, 3) for j in range(3)] |
运行结果:
1 | [(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] |
字典推导式
字典推导式作用:快速合并列表为字典或提取字典中目标数据。
创建字典
例如,创建一个字典,字典key是1-5数字,value是这个数字的2次方。
示例代码:
1 | dict1 = {i: i**2 for i in range(1, 5)} |
运行结果:
1 | {1: 1, 2: 4, 3: 9, 4: 16} |
合并列表为字典
将两个列表合并为一个字典
示例代码:
1 | list1 = ['name', 'age', 'gender'] |
运行结果:
1 | {'name': 'Tom', 'age': 20, 'gender': 'man'} |
提取字典中目标数据
示例代码:
1 | counts = {'MBP': 268, 'HP': 125, 'DELL': 201, 'Lenovo': 199, 'acer': 99} |
运行结果:
1 | {'MBP': 268, 'DELL': 201} |
集合推导式
示例代码:
1 | list1 = [1, 1, 2] |
运行结果:
1 | {1, 4} |
函数
函数的使用步骤
- 定义函数
- 调用函数
定义函数
1 | def 函数名(参数): |
调用函数
1 | 函数名(参数) |
函数的说明注释
定义函数的说明注释
1 | def 函数名(参数): |
查看函数的说明注释
1 | help(函数名) |
示例代码:
1 | def sum_num(a, b): |
运行结果:
1 | Help on function sum_num in module __main__: |
局部变量和全局变量
根据变量的生效范围,可以分为"局部变量"和"全局变量"两种,没有"块级变量"
局部变量
所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效。
示例代码:
1 | def testA(): |
运行结果:
1 | 100 |
全局变量
全局变量:指的是在函数体内、外都能生效的变量。
示例代码:
1 | # 定义全局变量a |
运行结果:
1 | 100 |
解释说明:global a
,声明a是全局变量。
没有块级作用域
示例代码:
1 | if True: |
运行结果:
1 | 123 |
num
并不是只在if
代码块生效,而是全局生效。
函数的参数
位置参数
位置参数:调用函数时根据函数定义的参数位置来传递参数。
示例代码:
1 | def user_info(name, age, gender): |
运行结果:
1 | 您的名字是TOM, 年龄是20, 性别是男 |
关键字参数
通过键=值
形式加以指定,可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。
(推荐这种。)
示例代码:
1 | def user_info(name, age, gender): |
运行结果:
1 | 您的名字是Rose, 年龄是20, 性别是女 |
- 函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序。
默认参数
默认参数,也被称为缺省参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值。
示例代码:
1 | def user_info(name, age, gender='男'): |
运行结果:
1 | 您的名字是TOM, 年龄是20, 性别是男 |
不定长参数
不定长参数也被称为可变参数,用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。
分为包裹位置参数和包裹关键字参数两种。
包裹位置参数
*args
,包裹位置参数。
示例代码:
1 | def user_info(*args): |
运行结果:
1 | ('TOM',) |
解释说明:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递。
包裹关键字传递
**kwargs
,包裹关键字参数。
示例代码:
1 | def user_info(**kwargs): |
运行结果:
1 | {'name': 'TOM', 'age': 18, 'id': 110} |
函数作为参数传递
函数本身,也可以作为参数传入另一个函数内。传入的是函数的逻辑,而非数据。
示例代码:
1 | def test_func(computer): |
运行结果:
1 | 5 |
lambda匿名函数
什么是lambda匿名函数
lambda函数,也被称为匿名函数,没有名称的内联函数,用lambda关键字创建的。
lambda匿名函数的定义语法:
1 | lambda 传入参数:函数体(只能写一行) |
注意:
lambda
是关键字,表示定义匿名函数。- 传入参数表示匿名函数的形式参数,如:
x, y
表示接收2个形式参数。 - 函数体,就是函数的执行逻辑,只能写一行,无法写多行代码。
示例代码:
1 | z = lambda x: x * y |
上述语句使用lambda关键字创建匿名函数,将两个值相乘。
x
是传递给lambda函数的参数,参数x
后面跟着一个冒号字符,冒号右边的代码是在调用lambda函数时执行的表达式,lambda函数被分配给z
变量。
简单使用
在下面示例中,我们有两个函数对一个值求平方。
示例代码:
1 | def square(x): |
运行结果:
1 | 9 |
lambda函数可以没有输入,示例代码:
1 | def constant(): |
运行结果:
1 | 1 |
lambda函数可以有多个输入参数,示例代码:
1 | def product(x, y): |
运行结果:
1 | 12 |
lambda与map
lambda函数对于map()
函数很有用,我们可以给予lambda创建更简洁的代码。
示例代码:
1 | def square(x): |
运行结果:
1 | <map object at 0x10b9a98a0> |
注意,这里的map()
不同于Java中的Map,即不是Python中的{}
字典。
这里的map()
是一个内置函数,将给定的函数应用于迭代器iterable的每一项,并返回一个迭代器iterator对象。
示例代码:
1 | nums = [1, 2, 3, 4, 5, 6] |
运行结果:
1 | 1 |
当然lambada函数可以结合map()函数,输入两个参数,以下示例提供了两个列表,对两个列表中相同位置的数据进行相加。
示例代码:
1 | num_add = map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10]) |
运行结果:
1 | 3 |
lambda与filter
lambda函数可以与filter()函数一起使用,从iterable中返回true的元素构造一个列表。
filte()
函数为Python自带函数,主要用于过滤掉不符合设定条件的元素,并返回符合条件元素组成的迭代器iterable。该函数有两个输入参数,第一个参数为处理函数,第二个参数为要处理的序列。序列的每个元素作为参数给函数进行判断,返回True或 False,过滤到返回False的参数,并将返回True的元素放到迭代器中。
通过使用filter()滤除奇数,示例代码:
1 | def is_even(x): |
运行结果:
1 | <filter object at 0x10da85930> |
lambda函数结合filter函数过滤整数列表,新列表仅包含奇数整数,示例代码:
1 | nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] |
运行结果:
1 | [1, 3, 5, 7, 9, 11] |
lambda与sort
使用lambda函数,按照用户的出生日期以相反的顺序对其进行排序。
示例代码:
1 | users = [ |
运行结果:
1 | {'name': 'Robert Brown', 'date_of_birth': 1977} |
拆包
元组
关于元祖的拆包,我们在上文讨论遍历"enumerate"的时候,其实已经讨论过了。
示例代码:
1 | def return_num(): |
运行结果:
1 | 100 |
字典
对字典进行拆包,取出来的是字典的key。
示例代码:
1 | dict1 = {'name': 'TOM', 'age': 18} |
运行结果:
1 | name |
所以,判断某个字典中是否有某个key,也可以基于拆包。示例代码:
1 | dict1 = {'name': 'TOM', 'age': 18} |
运行结果:
1 | True |
文件操作
读写等操作
打开
在Python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件,语法如下:
1 | open(name, mode) |
name
:要打开的目标文件名的字符串(可以包含文件所在的具体路径)。mode
:打开文件的模式(访问模式):只读、写入、追加等。
打开文件的模式
r
:读w
:写(清空写)a
:追加(追加写)b
:二进制+
r
的时候,拼接+
,那么拼接的是w
w
和a
的时候,拼接+
,那么拼接的是r
常见的几种组合如下:
模式 | 描述 |
---|---|
r |
以只读方式打开文件。 文件的指针会放在文件的开头。 |
rb |
以二进制格式,只读方式打开文件。 文件指针会放在文件的开头。 |
r+ |
以读写方式打开文件。 文件指针会放在文件的开头。 会覆盖文件中已有的内容 |
w |
以写入的方式打开文件。 如果该文件已存在,先清空文件内容,再写入。如果该文件不存在,创建新文件。 |
w+ |
以读写的方式打开文件。 如果该文件已存在,先清空文件内容,再写入。如果该文件不存在,创建新文件。 |
a |
打开一个文件用于追加。 如果该文件已存在,在已有内容之后追加写入。如果该文件不存在,创建新文件。 |
a+ |
以读写的方式打开文件。 如果该文件已存在,在已有内容之后追加写入。如果该文件不存在,创建新文件。 |
写
write
1 | 对象对象.write('内容') |
示例代码:
1 | # 1. 打开文件 |
运行结果:
1 | hello world |
特别的,我们来演示一下r+
的覆盖写。
假设存在一个文件,内容如下:
1 | 123456789 |
示例代码:
1 | # 1. 打开文件 |
运行结果:
1 | 999456789 |
如果我们想追加写,用a
。示例代码:
1 | import datetime |
writelines
1 | 文件对象.writelines(序列) |
注意:参数是序列,比如列表,迭代写入文件。
读
read
1 | 文件对象.read(num) |
num
表示要从文件中读取的数据的长度(单位是字节),如果没有传入num
,那么就表示读取文件中所有的数据。
readlines
1 | 文件对象.readlines() |
readlines
可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。
假设存在一个文件,内容如下:
1 | hello world |
示例代码:
1 | f = open('test.txt') |
运行结果:
1 | ['hello world\n', '1\n', '2\n', '3\n', '4\n', '5\n'] |
readline
1 | 文件对象.readline() |
readline()
,一次读取一行内容。
示例代码:
1 | f = open('test.txt') |
运行结果:
1 | 第一行:hello world |
seek
seek()
,移动文件读取指针到指定位置。
1 | 文件对象.seek(offset[, whence]) |
offset
:开始的偏移量,也就是代表需要移动偏移的字节数。whence
:可选,表示要从哪个位置开始偏移0
:从文件开头开始偏移1
:从当前位置开始偏移2
从文件末尾开始偏移。
如果操作成功,则返回新的文件位置
如果操作失败,则返回-1
。
假设,存在一个文件如下:
1 | 1 |
示例代码:
1 | # 打开文件 |
运行结果:
1 | 文件名为: test.txt |
关闭
关闭,释放资源。
1 | 文件对象.close() |
文件和文件夹的操作
在Python中文件和文件夹的操作要借助os
模块里面的相关功能。
文件重命名
1 | os.rename(目标文件名, 新文件名) |
删除文件
1 | os.remove(目标文件名) |
创建文件夹
1 | os.mkdir(文件夹名字) |
删除文件夹
1 | os.rmdir(文件夹名字) |
获取当前目录
1 | os.getcwd() |
获取目录列表
1 | os.listdir(目录) |
判断文件还是文件夹
示例代码:
1 | import os |
运行结果:
1 | it's a normal file |
判断是否存在
示例代码:
1 | import os |
运行结果:
1 | True |
判断访问权限
使用os.access()
可以判断文件的权限。
1 | os.access(path, mode) |
path
为文件路径mode
为操作模式os.F_OK
: 检查文件是否存在os.R_OK
: 检查文件是否可读os.W_OK
: 检查文件是否可以写入os.X_OK
: 检查文件是否可以执行
绘制树形目录
示例代码:
1 | import os |
运行结果:
1 | root:[../jpxd/] |