py基础(一)
一、注释
注释内容不会执行
1)作用
- 对某些代码进行标注说明,增强可读性
- 注释部分代码,进行调试
2)单行注释
用
#
放行首进行注释
# 这是一行注释
- 记得在注释后增加空格,会更美观
- Pycharm会在代码的下方以灰线提示错误(比如#后没跟空格)
- 如果出现了灰色线,移动上去,会看到一个灯泡,点击一下,点击第一个选项,会自动调整代码(重新格式化文件)
- 点击代码左侧,出现断点,可以单步执行,看到代码执行情况(注释会被直接跳过)
- 单行注释直接可以放在代码后面
print('hello python') # 这是一行注释
- 为了保证代码的可读性,代码和注释之间,最好保留两个空格
3)多行注释(块注释)
用
'''
进行块注释,以'''
结尾来结束块注释
- 其实块注释是多行字符串。
'''这是一个多行注释
这是一个多行注释
这是一个多行注释
'''
4)注释规范
- 只有复杂的代码,应该在操作前写上若干行注释
- 不是一目了然的代码,应该添加尾注释
- 不要描述代码,而要说它是干什么的
**代码审核:**一个团队彼此阅读对方的代码
PEP8(Python代码格式)
- PEP指的是Python增强建议,第8篇专门针对代码格式,称为PEP8
任何语言的程序员,编写出符合规范的代码,是开始程序生涯的第一步
二、算数运算符
- 算数运算符只是运算符的一种
- 完成基本的算数运算使用的符号,用来处理四则运算
运算符 | 描述 |
---|---|
+ - * / | 加 减 乘 除 |
// | 相除取整 |
% | 相除取余 |
** | 幂 |
- 使用python3打开交互式解释器试试
- 在py中,
*
还可以用于字符串,返回指定次数字符串拼接
# 生成一行分割线
print('-'*50)
- 优先级: 用括号就是了
三、程序执行的原理
1)三大硬件
一个程序要运行,要三个核心硬件缺一不可。分别是CPU,内存和硬盘。
1>CPU
- 中央处理器,是一块超大的集成电路
- 负责处理数据/计算
2>内存
- 临时存储数据(断电之后数据会消失)
- 速度快,空间小,单价高
3>硬盘
- 永久存储数据
- 速度慢,空间大,单价低
2)程序执行的原理
- 程序运行之前,程序是保存在硬盘中的
- 当要运行一个程序时
- 操作系统会首先让CPU把程序复制到内存中
- CPU执行内存中的程序代码(能被CPU识别,就是机器语言0101了)
程序要执行,首先要被加载到内存
3)Python程序执行原理
- OS先让CPU把Python解释器程序复制到内存中
- Python解释器根据语法规则,从上向下让CPU翻译Python程序中的代码
- CPU负责执行翻译完成的代码
- 将解释器加载到内存,会有多大?
which python # 确认解释器所在位置
ls -lh /usr/bin/python # 查看python文件大小(发现只是个软链接)
ls -lh /usr/bin/python2.7 # 查看具体文件大小,发现只有几M
使用软链接,是为了方便使用者不用记住使用的解释器是哪一个具体版本的
4)程序的作用
程序的作用就是处理数据(data)的
5)以QQ为例
- QQ运行时,会先被加载到内存中,并获得一块独立的空间
- QQ密码和号码也获得一个空间,使用一个别名来标记它们在内存中 的位置
- 在程序内部,为QQ号和QQ密码在内存中分配的空间就叫做变量()
- 程序是处理数据的,变量是存储数据的。
四、变量的基本使用
1)变量的定义为
- 变量的定义使用赋值语句
- 变量名 = 值
- 可以直接定义变量,也可以用多个变量运算的值赋给一个变量
- 变量3 = 变量2 + 变量1
pycharm点击单步执行(调试技巧),可以看到变量一步步被定义。当程序执行完成之后,会看到内存中的变量空间被释放。 - 变量名只有在第一次出现时,才是定义变量
- 变量名再次出现,不是定义变量,而是使用之前定义过的变量
- 可以修改变量保存的值,同名覆盖即可
2)变量类型
- 数字型:
- 整型int
- 浮点型float
- 布尔型bool
数字0
被当成假- 复数型(complex)
主要用于科学计算
- 非数字型
- 字符串str
- 列表list
- 元组turple
- 字典dict
- python中,定义变量不需要指定变量的类型(很多高级语言中都需要)
- python解释器会根据赋值语句等号右侧的数据自动推导出变量中保存数据的准确类型
- python的数据计算是非常强大的,比如2 ** 1000,对其它语言来说非常头疼,对python就是小cases。
type() # 查询变量保存的数据类型
3)变量之间计算
- 数字型之间直接计算
进行算数运算。其中True是1,False是0。
- 字符串之间使用+进行拼接,生成新字符串
- 字符串*数字 # 表示把字符串重复多少次
- 数字型变量不能与字符串进行其它任何计算
input(‘用以提示用户输入的文字’) # 获取用户输入的数据,返回一个str
- 在ipython中,如果执行的有返回结果,却没有一个变量来接收,那么就会显示一个Out来提示返回结果。如果使用了print,则不会有Out的提示。
4)类型转换函数
函数 | 说明 |
---|---|
int() | 转换为整数(向下取整) |
float() | 转换为浮点数 |
- 函数可以嵌套使用
五、格式化输出
- 在一个字符串中,需要用到变量,就可以先占个茅坑。这种输出文字信息的同时,一起输出数据的行为叫做格式化字符串。
%
被称为格式化操作符,用于处理字符串中的格式。-
- 包含
%
的字符串,被称为格式化字符串
- 包含
-
%
和不同字符连用,不同类型数据需要使用不同的格式化字符串
格式化字符 | 含义 |
---|---|
%s | 字符串 |
%d | 有符号的十进制整数,%c6d表示输出的最小宽度,不足的地方使用c补齐(注意c可以为0或者为任意字符) |
%f | 浮点数。%.02f表示小数点后只显示两位 |
%% | 输出% |
‘格式化字符串’ % 变量
‘格式化字符串’ % (变量1, 变量2…)
- 演练一下:
# 下面的 1, female,171.00, 000001, 70% 用变量传入
‘身份证中1代表男,单词中female代表女,中国男性平均身高171.00,小明的学号为000001,班上70%是女生。’
a = 1
b = 'female'
c = 171
d = 1
e = 70
string = '身份证中%d代表男,单词中%s代表女,中国男性平均身高%.2f,小明的学号为%06d,班上%d%%是女生。'
print(string % (a, b, c, d, e))
六、变量的命名规则
1)标识符(就是名字)
标识符就是程序员定义的变量名、函数名
需要有见名知义的效果
- 标识符可以有 字母、下划线、 数字 组成
- 不能以数字开头
- 不能和关键字重名
2)关键字
-
关键字就是在
python
内部已经使用的标识符 -
有特殊的功能和含义
-
开发者不允许定义和关键字相同名字的标识符
-
查看关键字
import keyword
print(keyword.kwlist)
3)吉多的命名规范
-
命名规则是一种惯例,目的是为了增强代码识别和可读性
-
python
中的标识符是区分大小写的 -
翻译:(下面图片里是原文)
类型 |
---|
模块 |
包 |
类 |
例外 |
函数 |
全局/类常量 |
全局/类变量 |
实例变量 |
方法名称 |
功能/方法参数 |
局部变量 |
1>下划线命名法
- 定义变量时,
=
两边要使用空格 - 每个单词都要使用小写字母
- 单词之间使用_下划线连接
2>驼峰命名法
- 小驼峰(第一个单词小写,其它单词首字母大写)
- 大驼峰(所有单词首字母大写)
七、判断
- 先看一块伪代码
'''这是一个游乐场的计价系统,其中:
6~12,打五折,12~16,打八折,大于16全票'''
if 年龄>16岁:
全票
elif 年龄>12岁:
八折
elif 年龄>6岁:
五折
else:
幼儿禁止入内
- 判断语句有称为分支语句,正是因为判断,才让程序有了很多的分支
- 代码格式:
if 要判断的条件:
条件成立时,执行的代码块
elif 要判断的条件:
当上一个条件不成立,而该条件成立时,执行的代码块
elif 要判断的条件:
当上一个条件不成立,而该条件成立时,执行的代码块
else:
当所有条件都不成立时,执行的代码块
- 注意: Tab可以直接缩进,但是建议用四个空格。因为Tab和空格不能混用。(pycharm可以自动缩进)
- if 语句、elif语句、else语句及各自的缩进部分共同是一个完整的代码块下方的缩进看作一个完整的代码块。
- 移动光标,可以看到上方标识了所属局部代码块(比如一个if块,elif块,else块。也可以理解为当前在哪一个语句的缩进里。)。点击这个标识,可以跳转到这个局部代码块的头部。
- 代码左侧有缩小按钮,点击可收起一个局部代码块
- else本身不起判断作用,起判断作用的是 if 和 elif 。
注意:elif
和else
都必须和if
联合使用,不能单独使用
1)比较运算符
运算符 | 说明 |
---|---|
== | 等于 |
!= | 不等于 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
2)逻辑运算符
运算符 | 说明 |
---|---|
and | 与 |
or | 或 |
not | 非 |
- 使用逻辑运算符,条件很容易过长。比如:
if ( A ) or ( B ) or ( C ) or ( D ) or ( E ):
# 可以在条件周围添加小括号,然后就可以分行了
if (( A)or ( B )
or ( C ) or ( D )
or ( E )):
# 分行了之后,最好在条件与子代码间增加一个空行,增加可读性。
# 条件判断最好再增加缩进,增加可读性(也就是相对于 if 8 缩进。相对于子句 4 缩进。)
3)嵌套
- elif判断的是同级条件
- 逻辑运算符判断的是当条件同时成立时
- 嵌套是当父级条件满足时,再进行额外的判断
if嵌套的语法格式,除了缩进之外与父级没有任何区别。 - 先看一段伪代码
# 火车站安检
if 有车票:
请接受安检
if 安检通过:
取候车吧
else:
请配合调查
else:
去买票吧
八、循环
1)程序的三大流程
- 顺序: 从上至下执行代码
- 分支: 据条件,选择分支执行
- 循环: 让特定代码重复执行
2)第一种循环:while
- 有关第二种循环:遍历。放在高级变量-列表中赘诉
while 布尔值:
emsp;代码子块
- 当知道次数时,最好使用计数器。当不知道次数时,用条件跳出。
- 循环跳出条件可以用 if 语句,或者在子句中调整判断条件(比如计数器)
下面演示--重要的事情说三遍--利用while循环的两种方法。
# 方法一:用if语句跳出
count = 0
while 1:
print('重要的事情说三遍')
count += 1
if count == 3:
break
# 方法二:用计数器跳出
count = 3
while count:
print('重要的事情说三遍')
count -= 1
- 不小心写出了死循环可以用
Ctrl C
退出(其实它是强制退出的热键)
3)赋值运算符
赋值运算符 | 说明 | 例子 |
---|---|---|
= | 最简单的赋值 | a = 1 |
+= | 加法赋值运算符 | a += b 等同于 a = a + b |
-= | 减法赋值运算符 | 同上 |
*= | 乘法赋值运算符 | 同上 |
/= | 乘法赋值运算符 | 同上 |
//= | 取整除赋值运算符 | 同上 |
%= | 取模赋值运算符 | 同上 |
**= | 幂赋值运算符 | 同上 |
4)计数方法
- 自然计数法(从1开始)
- 程序计数法(从0开始)
5)循环内的关键字
break
退出循环体,不再执行后续循环的代码。continue
跳到循环的条件判断。
# 打印1~3
for i in range(5):
print(i + 1)
if i == 2:
break
# 打印1、2、4、5
for i in range(5):
if i != 2:
print(i + 1)
continue
- 循环也可以嵌套。
6)转义字符
转义字符 | 作用 |
---|---|
\t | 横向制表符:在垂直方向上对齐 |
\符号 | 去除符号特殊意义 |
\n | 换行 |
\r | 回车 |
- 在Unix操作系统,用\n就能换行。在Windows中,用\r 和 \n 结合才能换行。
九、函数
- 函数,就是把具有独立功能的代码块组织为一个小模块,在需要的时候调用
- 函数的使用包括两个步骤:
- 定义函数==>封装独立的功能
- 调用函数
- 函数的作用:使用函数可以提高编写的效率、代码的重用,提高代码的复用性
1)函数的定义
def 函数名():
'''函数注释'''
函数封装的代码
。。。。。。
def
是define
的缩写- 函数名称要能够表达函数封装代码的功能,方便后续的调用
- 函数名是一个标识符
2)函数的调用
- 只有在函数中,主动调用函数,才会让函数执行。
# 同文件中:
函数名()
# 不同文件中:
文件名.函数名()
3)函数的参数
- 参数:增加函数的通用性,针对*8相同的数据处理逻辑**,能够适应更多的数据
- 多个参数以逗号隔开。其本质是将变量从外部传递到函数内部,然后调用。
- 在函数的内部,把常数当作变量使用,进行需要的数据处理
- 形参:定义函数时用来占位的参数,在函数内部作变量使用
- 实参:调用函数时使用的参数,用来把数据传入函数内部
4)函数的返回值
- 返回值,一般使用
return
关键字。 - 希望函数不立即打印结果到终端,或是希望对函数的结果进行进一步的处理,就要用到返回值
- return返回一个结果后,其后续的代码都不会被执行
- 调用函数一方,可以使用变量,来接收函数返回的结果
def sum_two_num(num1,num2):
'''对两数字求和'''
return num1 + num2
# 调用函数,并用一个变量来接收它。注意,变量名和函数名可以重名。
sum_two_num = sum_two_num(99,2)
print('创造!%s' % sum_two_num)
5)函数嵌套
def fun1():
print('这是第一个函数打印的结果')
def fun2():
print('这是第二个函数打印的结果')
fun1()
fun2()
**Tips:**工作中应对需求的变化,应该冷静思考,不要轻易修改之前已经完成的,能够正常执行的函数。
- 添加一个注释
十、模块
模块是Python程序架构的一个核心概念
- 模块需要靠
import
关键字导入 - 以.py结尾的文件就是一个模块
- 模块中定义的全局变量、函数都是模块能够提供给外界直接使用的工具
import 引入的模块名
引入的模块名.函数名1(传入的参数)
- 模块名也是一个标识符,也需要遵循命名规则,否则不能导入。
pyc文件
c
就是compiled
,意思是:编译过- 如果每次导入模块,它都需要一行行执行,那效率就太低了。但这也是解释型语言的一大缺点。所以,Python想到了一个好方法,在模块导入时,就会生成一个pyc二进制文件(相当于编译型语言,是导入模块的二进制版本),以此来加速程序的执行。
- 这个
pyc
文件是由Python解释器将模块源码转化为字节码
十一、高级变量类型
1)列表
- 英文: list
- 在其它语言中也称数组 Array
- 顺序 存储 一串 元素
- 用 [] 定义,元素之间使用
,
分隔 -
- 一切对象皆可为元素,在python中,一切又皆为对象。
- 列表的索引(有地方也称偏移量,是不同的两种角度。也可以叫下标。)从 0 开始
-
- 超出索引范围,程序会报错
-
- 列表最后一个元素的索引是 -1。可以倒着来
- 应用场景:
列表存储相同类型的数据(这是软规定,靠自觉遵守)
通过迭代遍历,取出数据,然后进行相同的操作
1>演示各种列表方法
- 不用背,忘了回来看就好
类别 | 关键字/函数/方法 | 说明 |
---|---|---|
增加 | 列表名.insert(索引,数据) | 在指定位置插入数据 |
列表名.append(数据) | 在末尾追加数据 | |
列表名.extend(列表名2) | 将列表2中的元素追加到列表 | |
修改 | 列表名[索引] = 元素 | 利用赋值语句修改 |
删除 | del 列表名[索引] | 删除指定索引的数据 |
列表名.remove[元素] | 删除第一个出现的指定数据 | |
列表名.pop | 删除末尾数据 | |
列表名.pop(索引) | 删除指定索引出的数据 | |
列表名.clear() | 清空列表 | |
统计 | len(列表名) | 列表长度 |
列表名.count(元素) | 指定元素在列表中的个数 | |
排序 | 列表名.sort() | 升序排序 |
列表名.sort(reverse=True) | 降序排序 | |
列表名.reverse() | 逆序,翻转 | |
查找 | 列表名.index(要查找的元素) | 查找索引 |
- 交互式解释器中:
>>>list_test = ['第一个元素', '第二个元素', '第n个元素']
>>>list_test2 = ['第五个元素', '第六个元素']
>>># 取值
>>># 语法:列表名[索引] 会返回该索引位置的元素
>>>list_test[0]
'第一个元素'
>>># 取索引
>>># 语法:列表名.index(要查找的元素) 如果元素不在列表,会报错
>>>list_test.index('第一个元素')
0
>>># 修改
>>># 语法:使用赋值语句
>>>list_test[2] = '第三个数据'
>>>list_test
['第一个元素', '第二个元素', '第三个元素']
>>># 末尾增加
>>># 语法:列表名.append(追加的元素)
>>>list_test.append('第四个元素')
>>>list_test
['第一个元素', '第二个元素', '第三个元素','第四个元素']
>>># 中间插入
>>># 语法:列表名.insert(索引,新元素) # 这个索引就是这个新元素的索引
>>>list_test.insert(2,'在二三元素之间')
>>>list_test
['第一个元素','在二三元素之间', '第二个元素', '第三个元素','第四个元素']
>>># 追加一个列表的元素
>>># 语法:列表名.extend(序列) # 追加在列表尾
>>>list_test.extend(list_test2)
>>>list_test
['第一个元素','在二三元素之间', '第二个元素', '第三个元素','第四个元素','第五个元素', '第六个元素']
>>># 删除元素
>>># 语法:列表名.remove(元素) # 删除第一个出现的该元素
>>>list_test.remove('在二三元素之间')
>>>list_test
['第一个元素','第二个元素', '第三个元素','第四个元素','第五个元素', '第六个元素']
>>># pop是弹出的意思,使用pop会返回被删除的元素,直接使用pop相当于操作栈
>>># 语法:列表名.pop()
>>>list_test.pop()
'第六个元素'
>>>list_test
['第一个元素','第二个元素', '第三个元素','第四个元素','第五个元素']
>>># 清空列表
>>># 语法:列表名.clear()
>>>list_test.clear()
>>>list_test
[]
>>># 长度
>>># 语法:len(列表名)
>>>len(list_test)
0
>>># 元素个数
>>># 语法:list_test.count(列表名)
>>>list_test.count('第一个元素')
0
>>>list_test3 = ['a','c','b']
>>># 排序:升序,会改变原列表
>>># 语法:列表名.sort()
>>>list_test3.sort()
>>> list_test3
['a', 'b', 'c']
>>># 排序:降序,会改变原列表
>>># 语法:列表名.sort()
>>>list_test3.sort(reverse=True)
>>> list_test3
['c', 'b', 'a']
>>> list_test3.reverse()
>>> list_test3
['a', 'b', 'c']
- del关键字,本质上是将一个变量从内存中删除的
- 在日常开发中,建议使用列表的方法
>>># 使用关键字删除
>>># 语法:del 列表名[索引]
>>>list_test4 = ['第一个元素', '第二个元素', '第三个元素']
>>>del list_test4[2]
>>>list_test4
['第一个元素', '第二个元素']
2>关键字、函数和方法
- 关键字是python内置的、具有特殊意义的标识符
关键字后面不需要使用小括号
- 函数封装了独立功能,可以直接调用
函数名(参数)
函数需要死记硬背
- 方法需要通过对象来调用,表示针对这个对象要做的操作
对象.方法(参数)
方法不需要死记硬背
3>遍历:for循环
- 遍历就是从头到尾迭代
- for 循环可以遍历任何非数字型变量
for 变量 in 集合:
# 变量是集合中的每个元素
...... # (循环体代码)
else:
# 若没有通过break退出循环,循环结束后,会执行的代码
2)元组
- 元组Tuple的用法与列表基本一致
- 元组使用 () 定义
- 元组不能修改
- 应用场景:
- 用于存储不同类型的数据
- 作为函数的参数和返回值。从而使一个函数可以接收任意多个参数,或者一次返回多个数据
- 格式化字符串,
%
后面跟着的(),就是一个元组 - 由于不可被修改,保护数据的安全
# 定义一个空元组
empty_tuple = ()
# 定义只有一个元素的元组,要加逗号,否则()会被忽略
single_tuple = ('一个元素',)
元组的方法
- 元组名.count(元素)==>计数
- 元组名.index(元素)==>获得下标
3)字典
dictionary
,有地方也叫散列表- 字典用来存储多个数据。与列表不同的是,列表取元素用的叫索引,字典取元素用的叫键
key
,换句话说,在字典中,键就是索引。 - 字典 = {key1:value1, key2:value2} # 每一个键和值组成的就叫键值对
- 字典用于存储无序的对象集合
-
- 使用print()函数打印一个字典时,显示的顺序通常和我们定义的顺序不一致(每次打印时,还会变化顺序)。这也说明字典是无序的。
- 遍历只能取出字典的键。但是可以通过取出的键,取出值。
- 键必须是唯一的
- 一个键值对就占一行代码,更加地美观
- 应用场景:
- 键最常用就是字符串
- 通常用于存储描述一个
物体
的相关信息 - 将多个字典放在一个列表里,再进行遍历,在循环体内部对每一个字典进行相同的处理
# 取值
print(字典名[键])
# 增加/键值对,使用**赋值**语句
字典名[键] = 值
# 删除,使用pop
字典名.pop(键)
# 统计键值对数量
print(len(字典名))
# 更新字典(无则加冕,有则改过)
字典名.update(字典2名)
# 清空字典
字典名.clear()
4)字符串
- 大多数编程语言都使用"双引号"来定义字符串
string = "一串字符串字符串"
# 取出“字”
print(string[2])
# 长度
print(len(string))
# 计数(子字符串)
print(string.count("字符"))
# 取索引
print(string.index("字符"))
1> 判断类型
方法 | 说明 |
---|---|
string.isspace() | 如果 string 中只包含空白字符,则返回 True(空白字符,包括空格,换行,制表,回车等) |
string.isalnum() | 如果 string 至少有一个字符并且所有字符都是字母或数字则返回 True |
string.isalpha() | 如果 string 至少有一个字符并且所有字符都是字母则返回 True |
string.isdecimal() | 如果 string 只包含数字则返回 True,全角数字 |
string.isdigit() | 如果 string 只包含数字则返回 True,全角数字、⑴、\u00b2 |
string.isnumeric() | 如果 string 只包含数字则返回 True,全角数字,汉字数字 |
string.istitle() | 如果 string 是标题化的(每个单词的首字母大写)则返回 True |
string.islower() | 如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True |
string.isupper() | 如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回 True |
- 判断数字的三个方法,都不能判断浮点数。
- isdecimal不能判断键盘上不能直观显示的数字。⑴是Unicode下的1,属于数字的特殊表示方法。\u00b2 是平方,属于特殊数字。
- isnumeric可以显示中文数字,如"一二三"
- 三个判断方法,范围越来越大。但应尽量使用isdecimal方法。
- 以下代码直接复制运行:
# 以下演示,皆采取最大范围:即穷举所有可以为True的结果。
A = " \t \n \r".isspace() # 如果 string 中只包含空白字符,则返回 True(空白字符,包括空格,换行,制表,回车等)
B = "Aa1".isalnum() # 如果 string 至少有一个字符并且所有字符都是字母或数字则返回 True
C = "Ab".isalpha() # 如果 string 至少有一个字符并且所有字符都是字母则返回 True
D = "123".isdecimal() # 如果 string 只包含数字则返回 True,全角数字
E = "123⑴²".isdigit() # 如果 string 只包含数字则返回 True,全角数字、⑴、\u00b2
F = "123⑴²一二三".isnumeric() # 如果 string 只包含数字则返回 True,全角数字,汉字数字
G = "Hello Python".istitle() # 如果 string 是标题化的(每个单词的首字母大写)则返回 True
H = "hello python".islower() # 如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True
I = "HELLO PYTHON".isupper() # 如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回 True
for run in [A,B,C,D,E,F,G,H,I]:
print(run) # 全是True
2>查找和替换
方法 | 说明 |
---|---|
string.startswith(str) | 检查字符串是否是以 str 开头,是则返回 True |
string.endswith(str) | 检查字符串是否是以 str 结束,是则返回 True |
string.find(str, start=0, end=len(string)) | 检测 str 是否包含在 string 中,如果 start 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回 -1 |
string.rfind(str, start=0, end=len(string)) | 类似于 find(),不过是从右边开始查找 |
string.index(str, start=0, end=len(string)) | 跟 find() 方法类似,不过如果 str 不在 string 会报错 |
string.rindex(str, start=0, end=len(string)) | 类似于 index(),不过是从右边开始 |
string.replace(old_str, new_str, num=string.count(old)) | 把 string 中的 old_str 替换成 new_str,如果 num 指定,则替换不超过 num 次 |
- index指定的字符串不存在会报错,而find会返回-1
- replace返回一个新的字符串,不会修改原字符串的内容
- 以下代码直接复制运行
# 程序世界会分辨大小写,所以一定要注意
A = "Hello python".startswith("He") # 检查字符串是否是以 str 开头,是则返回 True
B = "Hello python".endswith("on") # 检查字符串是否是以 str 结束,是则返回 True
# 这里会报错takes no keyword arguments,意思是不支持关键字参数,所以当位参传就好了
# C = "Hello python".find("lo", start=0, end=len("Hello python")) # 检测 str 是否包含在 string 中,如果 start 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回 -1
C = "Hello python".find("lo", 0, len("Hello python")) # 检测 str 是否包含在 string 中,如果 start 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回 -1
D = "Hello python".rfind("lo", 0, len("Hello python")) # 类似于 find(),不过是从右边开始查找,索引是不会因为从哪边开始找而变化的。
E = "Hello python".index("lo", 0, len("Hello python")) # 跟 find() 方法类似,不过如果 str 不在 string 会报错
F = "Hello python".rindex("lo", 0, len("Hello python")) # 类似于 index(),不过是从右边开始
G = "Hello python".replace("python", "java", "Hello python".count("python")) # 把 string 中的 old_str 替换成 new_str,如果 num 指定,则替换不超过 num 次
for run in [A,B,C,D,E,F,G]:
print(run)
3>大小写转换
方法 | 说明 |
---|---|
string.capitalize() | 把字符串的第一个字符大写 |
string.title() | 把字符串的每个单词首字母大写 |
string.lower() | 转换 string 中所有大写字符为小写 |
string.upper() | 转换 string 中的小写字母为大写 |
string.swapcase() | 翻转 string 中的大小写 |
A = "hello python".capitalize() # 把字符串的第一个字符大写
B = "hello python".title() # 把字符串的每个单词首字母大写
C = "HellO PythoN".lower() # 转换 string 中所有大写字符为小写
D = "HellO PythoN".upper() # 转换 string 中的小写字母为大写
E = "HellO PythoN".swapcase() # 翻转 string 中的大小写
for run in [A,B,C,D,E]:
print(run)
# 返回的结果
"""Hello python
Hello Python
hello python
HELLO PYTHON
hELLo pYTHOn"""
4>文本对齐
方法 | 说明
string.ljust(width) |返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串
string.rjust(width) |返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串
string.center(width) |返回一个原字符串居中,并使用空格填充至长度 width 的新字符串
string = ["《蜀道难》",
"李白",
"噫吁嚱,",
"危乎高哉!",
"蜀道之难,",
"难于上青天!"]
for poem in string:
print("|%s|" % poem.center(10," ")) # 第一个参数是长度,第二个参数是填充用的字符串(默认用半角空格填充0
print("-"*50)
for poem in string:
print("|%s|" % poem.ljust(10," "))
print("-"*50)
for poem in string:
print("|%s|" % poem.rjust(10," "))
"""| 《蜀道难》 |
| 李白 |
| 噫吁嚱, |
| 危乎高哉! |
| 蜀道之难, |
| 难于上青天! |
--------------------------------------------------
|《蜀道难》 |
|李白 |
|噫吁嚱, |
|危乎高哉! |
|蜀道之难, |
|难于上青天! |
--------------------------------------------------
| 《蜀道难》|
| 李白|
| 噫吁嚱,|
| 危乎高哉!|
| 蜀道之难,|
| 难于上青天!|"""
5> 去除空白字符
方法 | 说明 |
---|---|
string.lstrip() | 截掉 string 左边(开始)的空白字符 |
string.rstrip() | 截掉 string 右边(末尾)的空白字符 |
string.strip() | 截掉 string 左右两边的空白字符 |
- 在网上爬取的文本,很容易有各种空白字符,如转义字符,就可以先用这些方法去除。
string = "\r\t\n hello python \r\t\n"
print(string.lstrip()) # 截掉 string 左边(开始)的空白字符
print(string.rstrip()) # 截掉 string 右边(末尾)的空白字符
print(string.strip()) # 截掉 string 左右两边的空白字符
""" thon
hello python
hello python"""
6>拆分和连接
方法 | 说明 |
---|---|
string.partition(str) | 把字符串 string 分成一个 3 元素的元组 (str前面, str, str后面) |
string.rpartition(str) | 类似于 partition() 方法,不过是从右边开始查找 |
string.split(str="", num) | 以 str 为分隔符拆分 string,如果 num 有指定值,则仅分隔 num + 1 个子字符串,str 默认包含 ‘\r’, ‘\t’, ‘\n’ 和空格 |
string.splitlines() | 按照行(’\r’, ‘\n’, ‘\r\n’)分隔,返回一个包含各行作为元素的列表 |
string.join(seq) | 以 string 作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串 |
A = "hello_world_python".partition("world") # 把字符串 string 分成一个 3 元素的元组 (str前面, str, str后面)
B = "hello_world_python".rpartition("_") # 类似于 partition() 方法,不过是从右边开始查找
C = "hello_world_python".split("_") # 以 str 为分隔符拆分 string(没有就使用所有空白字符分割),如果 num 有指定值,则仅分隔 num + 1 个子字符串,str 默认包含 ‘\r’, ‘\t’, ‘\n’ 和空格
D = "hello\nworld\rpython".splitlines() # 按照行(’\r’, ‘\n’, ‘\r\n’)分隔,返回一个包含各行作为元素的列表
E = "_".join(["hello","world","python"]) # 以 string 作为分隔符,将 seq(序列) 中所有的元素(的字符串表示)合并为一个新的字符串
for run in [A,B,C,D,E]:
print(run)
"""('hello_', 'world', '_python')
('hello_world', '_', 'python')
['hello', 'world', 'python']
['hello', 'world', 'python']
hello_world_python"""
5)非数字型变量的公共方法
- 切片:
序列[开始索引:结束索引:步长] # 取左不取右
索引可以倒序索引
隔一个,步长为2
- 逆序切片(面试题)
seq[-1::-1] # 表示从最后一个开始,往回取
seq[::-1] # 也可以省略为这种形式
- 内置函数
函数 | 说明 | 附注 |
---|---|---|
len(item) | 计算容器中的元素个数 | |
del(item) | 删除变量 | del 有两种方法 |
max(item) | 最大值 | 字典比较的是key |
min(item) | 最小值 | 字典比较的是key |
- 运算符
运算符 | 作用 | 支持的数据类型 |
---|---|---|
+ | 合并 | seq |
* | 重复 | seq |
in | 元素是否存在 | item |
not in | 元素是否不存在 | item |
> >= <= < == != |
元素比较 | seq |
- extend会更改原列表,+产生一个新列表
- in和not in叫成员运算符
6)变量进阶(理解)
1>变量的引用
- 变量 和 数据 都是保存在 内存 中的
- 在
python
中函数的参数传递 以及 返回值 都是靠 引用 传递的
引用的概念
在python
中:
- 变量 和数据 是分开存储的
- 数据 保存在内存中的一个位置
- 变量 保存数据在内存 中的地址
- 变量 中记录数据的地址,就叫做引用
- id() 函数可以查看变量中保存数据所在的内存地址,或直接查看数据的内存地址。(即参数可以是变量,也可以是数据)(内存地址是一个数字)
当给一个已定义的变量赋值时,本质上是修改了数据的引用。即改为对新赋值的数据引用。
- 使用函数形参传递参数时,本质上是让该形参记录实参里保存数据的地址。换句话就是,形参引用了实参记录的数据。
- 函数返回值,返回的也是数据的引用
可变和不可变类型
- 不可变类型,内存中的数据不允许被修改
- 数字类型
int
,bool
,float
,complex
,long(2,x)
- 字符串
str
- 元组
tuple
- 可变类型,内存中的数据可以被修改
- 列表
list
- 字典
dict
a = ["唯一一个元素"]
print(id(a)) # 52136656
a.clear()
print(a,id(a)) # [] 52136656 没有变化,说明是改变数据,不是改变引用
a = []
print(a,id(a)) # [] 52136776 发生变化,说明此空列表非彼空列表。赋值语句会修改变量的引用
- 字典的
key
只能用不可变类型
哈希(hash)
python
中内置一个hash()函数
- 接收一个不可变类型的数据作为参数
- 返回的结果是一个整数(特征码)
- 哈希 是一种算法,作用是提取数据的特征码(指纹)
- 相同的内容得到相同的结果
- 不同的内容得到不同的结果
- 在
python
中,设置字典的键值对时,会首先对key
进行hash
。以保证字典中的数据有个更好的优化,以方便后续的CRUD
十二、局部变量与全局变量
- 局部变量 是在函数内部 定义的变量,只能在函数内部使用
- 全局变量 是在函数外部 定义的变量(没有定义在某一个函数内),所有函数内部都可以使用这个变量
在其他的开发语言中,大多不推荐使用全局变量==>可变范围太大,导致程序不好维护!
- 但在
python
中,使用全局变量的情况比较常见,但是有一些特殊的要求。
1)局部变量
- 局部变量,在函数内部定义,在其它位置,不能被使用。
2)局部变量的生命周期
- 所谓生命周期就是变量从被创建到被系统回收的过程
- 局部变量在函数执行时才会被创建
- 函数执行结束后局部变量被系统回收
- 局部变量在生命周期内,可以用来存储函数内部临时使用到的数据
- 使用单步调试,可以看到局部变量出生死亡的过程。
3)注意
- 在
python
中,是不允许修改全局变量的值的
- 若在函数内定义同名变量,只会定义一个局部变量,与全局变量无关
- 函数会优先使用局部变量,若未找到,才会去找全局变量
- 在开发时,应该把全局变量定义在所有函数的上方
- 在函数内部修改全局变量的值,可以使用
global
关键字
a = 1
def a_num():
global a # 声明修改全局变量
a = 2
def a_print():
print(a)
a_print() # 2
4)代码结构示意图
shebang(用来选择使用哪一个解释器) |
---|
import 模块 |
全局变量 |
函数定义 |
执行代码 |
5)全局变量取名要求
- 全局变量前应该加
g_
或gl_
,具体根据公司要求 - pycharm中,选中变量,右击选择
Refactor
,选择rename
,然后增加前缀,就可以了(快捷键Shift F6)(不会修改同名的局部变量)
十三、函数的返回值与参数进阶
- 希望将外界的数据在函数内处理,使用参数
- 希望将函数内的数据向外界回报执行结果,使用返回值
1)返回值
- 可以使用元组来返回多个值。在return关键字后面直接跟多个参数加逗号隔开,python会将其自动地转变为元组。换句话说,如果返回的是元组,小括号可以省略(最好省略以增强可读性),原理是使用了封包。
- 可以将返回的元组解包
解包和封包
# 封包:将多个数据封装成一个元组。
A = 1,2,3
print(A) # (1,2,3)
# 解包:将一个元组中的数据分配给多个变量。
B, C, D = (1,2,3)
print(B) # 1
print(C) # 2
print(D) # 3
# 解包的同时封包
E, F, G = 4, 5, 6
print(E) # 4
print(F) # 5
print(G) # 6
- 交换两个变量(面试题)
# 解法一:封包解包(python特有解法)
a = 1
b = 2
b, a = a, b
# 解法二:利用数学逻辑(原理是和、乘可以携带多个数据,只要留有)
a = a + b
b = a - b
a = a - b
2)参数
- 传完参数后,在函数内部使用赋值语句定义全局变量。不会影响到外部的实参变量,不论是可变还是不可变数据类型。
gl_num = 13
def fun1(num):
num = 0
print(num)
fun1(gl_num) # 0
# 原因是:函数的num 引用外部变量gl_num 的数据, 当执行到函数内部,发现赋值语句,于是更改了num的引用,num不再引用gl_num 了。
- 如果传递的参数是可变类型,在函数内部,使用方法修改了数据的内容,同样会影响到外部的数据()。调用方法不会修改引用。
gl_list = [1, 3, 5]
def fun1(num_list):
num_list.append(7)
fun1(gl_list)
print(gl_list) # [1, 3, 5, 7],发现调用方法更改了可变数据类型
- 在
python
中,列表变量调用+=
本质上是在执行列表变量的extend
方法,不会修改变量的引用(面试题)
gl_num = 1
gl_list = [1, 3, 5]
def fun(lo_num, lo_list):
lo_num += 99
# 列表变量作 += 本质上是在调用列表的 extend 方法
# 如果是使用 list1 = list1 + list2, 就是赋值语句的意思,不会改变外部变量
lo_list += [7, 9]
fun(gl_num, gl_list)
print(gl_num,gl_list,sep=" ") # 1 [1, 3, 5, 7, 9]
# 原因是,+=对num来说是赋值语句,对list来说是调用方法
1>缺省参数
- 定义函数时,给某个参数指定一个默认值,具有默认值的参数就叫做缺省参数,这个默认的值就叫做缺省值
- 将常见的值设置为参数的缺省值,从而简化函数的调用
**比如:**列表的 sort() 方法,默认使用升序排序。
def print_role(name, gender= "男"):
print("【姓名】%s 【性别】%s" % (name, gender))
print_role("小明")
print_role("小红","女")
print_role("小光", gender="女")
"""【姓名】小明 【性别】男
【姓名】小红 【性别】女
【姓名】小光 【性别】女"""
- 缺省参数,要在参数列表的末尾
- 如果有多个缺省参数,要么按顺序依次输入,要么指定参数名
2>多值参数
- 如果一个函数能够处理的参数个数是不确定的,这个时候,就可以使用多值参数
python
中有两种多值参数
- 参数名前加
*
可以接收元组- 参数名前加
**
可以接收字典
- 一般在给多值参数命名是,习惯使用以下两个名字:
*args
==>存放元组参数**kwargs
==>存放字典参数
args 是 arguments 的缩写,是变量的意思
def fun1(arg1, *args, **kwargs):
print(arg1,args,kwargs,sep=" ")
print("-"*50)
# 注意 字典的键 不能有引号包裹,相当于关键字参数的意味。
fun1(1,2,3,4,5,王二= 18, 张三= 20, 李四= 21)
# 以上代码等同于下面这些代码(对比一下,体会个中感觉,会发现上面简洁多了):
def fun2(arg1, args, kwargs):
print(arg1,args,kwargs,sep=" ")
print("-"*50)
fun2(1, (2, 3, 4, 5), {"王二":18, "张三":20, "李四": 21})
- 多值参数会经常出现在网络上一些大触开发的框架中,理解概念,有利于我们能更好地读懂大触们的代码
- 演练:将数字相加的函数
def sum_num(*args):
sum = 0
for num in args:
sum += num
print(sum)
sum_num(250,38,2) # 290
拆包
- 在调用带有多值参数的函数时,如果希望将一个元组变量,或一个字典变量,直接传递,就可以使用拆包
-在元组变量前,增加
*
-在字典变量前,增加**
def fun(arg1, *args, **kwargs): # 注意形参和实参,都需要用 *
print(arg1,args,kwargs,sep=" ")
print("-"*50)
tuple1 = (2, 3, 4, 5)
dict1 = {"王二":18, "张三":20, "李四": 21}
fun(1, *tuple1, **dict1)
3)递归
- 一个函数内部,自己调用自己的行为,就叫递归。递归是一种特殊的循环
- **特点:**代码不会变化,只是传递的参数发生变化
- 递归需要两个条件:
- **基线条件:**递归跳出的条件
- **递归条件:**进行递归的条件
- 循环的效率更高,但是递归更加优美易度。选择哪种看需求。
- 在不确定循环条件时,递归格外有用
终、项目
项目1:石头剪刀布
1)分析
- 玩家从控制台输入==>input
- 电脑随机==>random
random.randint(a,b) # 生成[a,b]的所有整数
- 比较判断==>bool
2)代码实现
# 引入random模块
import random
user_choice = int(input('请输入您的选择(石头0,剪刀1,布2)'))
computer_choice_index = random.randint(0,2) # 在交互式解释器中,发现这是个int类型的
# 利用列表来取出电脑的选择
bunch_list = ['石头','剪刀','布']
computer_choice = bunch_list[computer_choice_index]
print('电脑输入的是%s'%computer_choice)
# 利用列表的索引来输出结果,利用负数可以从后往前索引
win_or_fail_list = ['打了个平局','你输了!','你赢了!']
print(win_or_fail_list[user_choice - computer_choice_index])
项目2:计算阶乘(循环方法)
1)分析
- 用户输入一个数字
- 利用循环进行阶乘
2)代码实现
num = int(input('请输入一个数字'))
sum = 1
while num - 1:
sum *= num
num -= 1
print(sum)
项目3:打印九九乘法表
1)分析
- 需要生成1~9的数字==>遍历
- 每一级里面有一个小循环==>嵌套
- 小循环,不希望换行==>改变 print 的 end 参数
- 希望对其==>使用转义字符 \t
2)代码实现
for i in range(9):
i += 1
for j in range(i):
j += 1
print('%d * %d = %d' % (j, i, j * i),end='\t')
print()
项目4:找到学生信息
1)分析
- 需要一个存储用户信息的字典
- 能够输入查找的人
- 当遍历到,就退出==>break
2)代码实现
- 直接复制下方代码运行
user_list = [
{"name":"小明",
"height":"188"},
{"name":"小红",
"height":"165"}
]
name = input("请输入希望查找的用户")
for user in user_list:
if user["name"] == name:
print("%s的身高是:%s" % (user["name"],user["height"]))
break
else:
print("没有找到")
- 只有像现在这样,用数据搜索时,才会用到for循环 的else。
项目5:计算阶乘(递归方法)
- 方法一:定义默认参数,存储中间值
def factorial(num, f=1):
f *= num
if num == 1:
print(f)
return
factorial(num - 1, f)
factorial(10)
- 方法二:妙极!利用了数学的归纳总结法
def factorial(num):
if num == 1:
return 1
# 假设factorial可以处理num - 1的阶乘
f = factorial(num - 1)
# f因为是num - 1的阶乘,所以在乘上num时,就变成了num的阶乘(像不像归纳总结?)
return num * f
print(factorial(10))
- 处理逻辑: