目录
控制语句
选择结构
1.单分支选择结构语句
语法形式: if 条件表达式(逻辑,关系,算术等表达式):
语句 (多条语句,缩进必须一致)
2.双分支选择语句
语法形式: if 条件表达式:
语句
else:
语句
三元条件运算符
语法格式: 条件为真时的语句 if (条件表达式) else 条件为假时的语句
3.多分支选择语句
语法形式: if 条件表达式:语句
elif 条件表达式:语句
……
[else: 语句]
计算机行业,描述语法格式时,使用括号[]表示可选,非必选
4.条件表达式详解
在选择,循环结构中,条件表达式的值为false的情况如下
false,0, 0.0, 空值, None, 空序列对象, 空range对象, 空迭代对象
条件表达式中,不能有赋值操作符“=”
循环语句
1.while 循环
语法格式: while 条件表达式
循环体语句
2.for循环和可迭代对象遍历
for循环语法格式: for 变量 in 可迭代对象
循环体语句
可迭代对象:(Python)
1.序列。包含:字符串,列表,元组
2.字典
3.迭代器对象
4.生成器对象
5.range对象
break语句
结束本层循环
continue语句
结束本次循环,直接进入下一次
else语句
while、for循环可以附带一个else语句(可选),如果for、while语句没有被break语句结束,则会执行else语句,否则不执行,语法格式如下:
while 条件表达式: 或者 for 变量 in 可迭代对象:
循环体 循环体
else: else:
语句块 语句块
例:
#测试循环中的else语句
salarySum = 0
salarys = []
for i in range(4):
s = input("请输入一共4名员工的薪资(按Q或q中途结束)")
if s.upper() == 'Q': #s.upper() 将s中的字母全都大写
print("录入完成,退出")
break
if float(s) < 0:
continue
salarys.append(float(s))
salarySum += float(s)
else:
print("您已经全部录入4名员工的薪资")
print("录入薪资", salarys)
print("平均薪资{0}", format(salarySum/4))
若向正常输入四个薪资,则输出结果为:
如图可看出,在输入四位员工的薪资后,执行了else中的内容。
若提前结束,则输出结果:
可看出,由于执行了break语句,循环结束后并没有执行else语句
循环代码优化
编写循环时,遵守以下原则,可大大提高运行效率,避免不必要的代数计算
-
尽量减少循环内部不必要的计算
-
嵌套循环中,尽量减少内层循环的计算
-
局部变量查询较快,尽量使用局部变量(尽量避免使用全局变量)
其他优化手段
1.连接多个字符串,使用join()而不使用+
2.列表进行元素插入和删除时,尽量在列表尾部操作
使用zip()并行迭代
可通过zip()函数对多个序列进行并行迭代,zip()函数在最短序列“用完”时就会停止
names = ("小高","小李","小张","小明")
ages = (17,18,19,20)
jobs = ("老师","程序员","公务员")
for name,age,job in zip(names,ages,jobs)
print("{0}-{1}-{2}".format(name,age,job))
'''
运行结果:
小高-17-老师
小李-18-程序员
小张-19-公务员
'''
推导式创建序列
列表推导式
列表推导式生成列表对象,语法:
[表达式 for 变量 in 可迭代对象] 或者:
{表达式 for 变量 in 可迭代对象 if 条件判断}
字典推导式
字典的推导式生成字典对象,语法格式:
{key_expression : value_expression for 表达式 in 可迭代对象}
类似列表推导式,字典推导式也可以增加if条件判断,多个for循环
例:文本中字符出现的次数
my_text = "python is a programming language"
char_count = {c:my_text.count(c) for c in my_text}
print(char_count) #输出:{'p': 2, 'y': 1, 't': 1, 'h': 1, 'o': 2, 'n': 3, ' ': 4, 'i': 2, 's': 1, 'a': 4, 'r': 2, 'g': 4, 'm': 2, 'l': 1, 'u': 1, 'e': 1}
集合推导式
集合推导式生成集合对象,和列表推导式的语法格式相似
{表达式 for 变量 in 可迭代对象 if 判断对象}
生成器推导式(生成元组)
元组是没有推导式的
a=(x for x in range(1,100) if x%9==0)
print(a) #输出:<generator object <genexpr> at 0x000001CF664A04A0>
print(tuple(a)) #输出结果:(9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 99)
print(tuple(a)) #输出结果:()
每执行一次生成器,其只能进行一次元组转换,第二次则数据就没有了
函数
函数用法和底层分析
函数是可重用的程序代码块,函数的作用,不仅可实现代码的复用,更能实现代码的一致性
一致性:只要修改函数的代码,则所有调用该函数的地方都能得到体现
函数简介(基本概念)
1.一个程序由一个个任务组成,函数就是代表一个任务或者一个功能
2.函数是代码复用的通用机制
Python函数的分类
1.内置函数
例:str()、len()等都是内置函数,可直接使用
2.标椎库函数
通过import语句导入库,可使用其中定义的函数
第三方库函数
Python社区也提供了很多高品质的库,下载安装这些库后,通过import语句导入便可使用
4.用户自定义函数
用户自己定义的函数,开发中适应用户自身需求定义的函数
函数的定义和调用
Python中,定义函数的语法如下:
def 函数名([参数列表])
''' 文档字符串'''
函数体/若干语句
要点:
1.使用def定义函数,然后就是一个空格和函数名称
Python执行def时,会创建一个函数对象,并绑定到函数名变量上
2.参数列表
(1)圆括号内是形式参数列表,有多个参数则使用逗号隔开
(2)形式参数不需要声明类型,也不需要指定函数返回值类型
(3)无参数,也必须保留空的圆括号
(4)实参列表必须与形参列表一一对应
3.return返回值
(1)若函数体内包含return语句,则结束函数执行并返回值
(2)若函数体内不包含return语句,则返回None值
4.调用函数之间,必须要先定义函数,即先调用def创建函数对象
(1)内置函数对象会自动创建
(2)标椎库和第三方函数库,通过import导入模块时,会执行模块中的def语句
形参和实参
def printMax(a,b)
'''实现两个数的比较,并返回较大值'''
if a>b :
print(a,"较大值")
else:
print(b,"较大值")
printMax(10,20) #输出:20 较大值
上面的printMax函数中,在定义时写的printMax(a,b),a和b成为“形式参数”,简称:形参。形式参数的命名只需符合“标识符”的命名规则即可。调用函数时,传递的参数成为“实际参数”,如上面的10和20
文档字符串(函数的注释)
程序的可读性最重要,一般建议在函数体开始 附上函数定义说明,这就是“文档字符串”如上个代码中三单引号中的内容。
调用help(函数名,——doc——)可以打印输出函数的文档字符串
返回值
return返回值要点
1.若函数体内包含return语句,则结束函数执行并返回值
2.若函数体内不包含return语句,则返回None值
3.要返回多个返回值,使用列表、元组、字典、集合将多个值“存起来”即可
函数也是对象,内存底层分析
Python中,“一切都是对象”,实际上,执行def定义函数后,系统就创建了相应的函数对象
def print_star(n):
print("*"*n)
print(print_star)
print(id(print_star))
c=print_star
c(10)
'''
输出:
<function print_star at 0x00000188BA863EB0>
1686756540080
**********
'''
上面代码执行def时,系统中会创建函数对象,并通过print_star这个变量进行引用
变量的作用域(全局变量和局部变量)
变量起作用的范围成为变量的作用域,不同作用域内同名变量之间互不影响,变量分为:全局变量和局部变量
全局变量
1.在函数和类定义之外声明的变量,作用域为定义的模块,从定义位置开始直到模块结束
2.全局变量降低了函数的通用性和可读性,应尽量避免函数值的使用
3.全局变量一般做常量使用
4.函数内改变全局变量的值,需要使用global声明 若未声明,只能引用,不能改变其值
局部变量和全局变量效率
局部变量的查询和访问速度比全局变量快,优先考虑使用,尤其是在循环和一些特别强调效率的时候
#测试局部变量和全局变量的效率
import time
a=3
def text01():
for x in range(100000000):
b=a*3
def text02():
c=a
for x in range(100000000):
b=c*3
t1=time.time() #当前时间到1970.1.1 00:00,到距离,以秒为单位
text01()
t2=time.time()
t3=time.time()
text02()
t4=time.time()
print("耗时:{0}".format(t2-t1))
print("耗时:{0}".format(t4-t3))
输出结果:
参数的传递
函数声明时的形式参数使用时等同于函数体内的局部变量,由于Python中一切皆对象,因此,参数传递时直接传递参数的地址
具体使用分几类:
1.传递不可变对象的使用(起到其他语言传递值的效果)
2.传递可变对象的引用(起到其他语言引用传递的效果)
3.对“可变对象”进行“写操作”,直接作用与源对象本身
4.对“不可变对象”进行“写操作”,会产生一个新的“对象空间”,并用新的值填充这块空间
可变对象:字典、列表、集合、自定义的对象等
不可变对象:数字、字符串、元组、function(函数)等
可传递对象的引用
传递参数时可变对象,实际传递的还是对象的引用,在函数体内不创建新的对象拷贝,而是可以直接修改所传递的对象
传递不可变对象的引用
传递参数是不可变对象,实际传递的不是对象的引用,在“赋值操作”时,由于不可变对象无法修改,系统会新建一个对象
浅拷贝和深拷贝
浅拷贝:不拷贝子对象的内容,只是拷贝子对象的引用 copy()浅拷贝
深拷贝:会连子对象的内存也全部拷贝一份,对子对象的修改,不会影响到源对象 deepcopy()深拷贝
传递不可变对象是浅拷贝
传递参数是不可变对象,实际传递的还是对象的引用,但在“写操作”时,会创建一个新的对象拷贝,这个拷贝使用的是“浅拷贝”
参数的几种类型
位置参数
函数调用时,实参默认按位置顺序传递,需要个数和形参匹配,按位置传递的参数,称为“位置参数”
默认值参数
可为某些参数设置默认值,这样参数在传递时就是可选的
命名参数
可按照形参的名称传递参数,称为“命名参数”,也称为“关键字参数”
可变参数
可变参数指的是“可变数量的参数”,分两种情况:
1.*param(一个星号),将多个参数收集到一个“元组”对象中
2.**param(两个星号),将多个参数收集到一个"字典"对象中
强制命名参数
在带星号的“可变参数”后面增加新的参数,必须是强制命名参数
lambda表达式和匿名函数
lambda表达式可以用来声明匿名函数,lambda函数是一种简单在同一行中定义函数的方法,lambda函数实际生成了一个函数对象,lambda表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是函数的返回值。
基本语法: lambda arg1,arg2…… :表达式
d=lambda a,b,c:a+b+c
print(d(2,5,9)) #输出:16
eval()函数
功能:将字符串str当成有效的表达式来求值并返回计算结果
语法: eval(source[,globals[,locals]]
source:一个Python表达式或函数compilel返回的代码对象
globals:可选,必须是dictionary
locals:可选,任意映射对象
#测试eval函数
s = "print('hbjj')"
eval(s)
a=10
b=20
c=eval("a+b")
print(c)
d=dict(a=100,b=200,c=300)
c=eval('a+b+c',d)
print(c)
输出结果:
递归函数
自己调用自己的函数,在函数体内部直接或间接的自己调用自己,每个递归函数必须包含两个部分
1.终止条件:一般用于返回值,不在调用自己
2.递归步骤:把第n步的值和第n-1步相关联
递归函数由于会创建大量的函数对象,过量的消耗内存和运算能力。在处理大量数据时,谨慎使用
#一个简单的递归函数
def text01(n):
if n==1:
return 1
else:
return n*text01(n-1)
print(text01(5)) #输出:120
嵌套函数(内部函数)
在函数内部定义的函数
一般在什么情况下使用嵌套函数
1.封装,隐藏数据
外部无法访问“嵌套函数”
2.贯彻 DRY(Don't Repeat Yourself)原则
嵌套函数可以让我们在函数内部避免重复代码
3.闭包
def text01():
a=9
def text02(): #内嵌函数
print("*"*10)
nonlocal关键字
nonlobal:用来声明外层的局部变量
global:用来声明全局变量
未用其进行声明时,仍可在内层函数调用外层变量,只是不能修改
LEGB规则
Python在查找“名称”时,是按照LEGB规则查找的:local enclosed global built in
local:指的是函数或类的方法内部
enclosed:指的是嵌套函数(一个函数包裹另一个函数,闭包)
global:指的是模块中的全局变量
built in:指的是Python为自己保留的特殊名称
如果某个name映射在局部(local)命名空间中没有找到,接下来会在闭包作用域(enclosed)进行搜索,如果闭包作用域也没有找到,Python就会到全局(global)命名空间中进行查找,最后会在内建(built in)命名空间搜索(如果一个名称在所有命名空间中都没有找到,就会产生一个nameerror)