1.循环语句

1.1 while语句

作用:根据一定条件,重复执行一条或多条语句

img

语法:

1
2
3
4
while 真值表达式:
语句块
else
语句块
1
2
3
4
5
6
count = 0
while count < 5:
print(count, " is less than 5")
count = count + 1
else:
print(count, " is not less than 5")

image-20220721151356314

while 语句语法说明:

  1. 先执行真值表达式,判断True/False
  2. 如果为True则执行语块1,然后跳转到第一步
  3. 如果为False则执行else子句部分的语块2,然后结束此while语句的执行,如果没有else语句,则直接结束此while语句
  4. else子句部分可以省略

while语句注意事项:

  1. 要控制真值表达式来防止死循环
  2. 通常用真值表达式内的变量来控制循环条件
  3. 通常要在循环语句块内改变循环变量来控制循环的次数和变量的走向

1.2 break语句和死循环

  • 作用:用于循环语句(while,for语句)中,用来终止当前循环语句的执行

break语句的说明:

  1. 当break语句执行后,此循环语句break后的语句将不再执行
  2. break语句通常和if语句组合使用
  3. break语句终止循环时,循环语句的else子句的语句将不会执行
  4. break语句只能终止当前循环语句的执行,如果有循环嵌套时,不会跳出嵌套的外重循环
  5. break语句只能在循环语句(while或for)中执行
1
2
3
4
5
6
7
n = 1
while n <= 100:
if n > 10: # 当n = 11时,条件满足,执行break语句
break # break语句会结束当前循环
print(n)
n = n + 1
print('END')

1.3 for语句

  • 作用:用来遍历可迭代对象的数据元素

可迭代对象是指能一次获取数据元素的对象

可迭代对象包括:字符串str,列表list,元组tuple,字典dict,集合set

for语句的用法:

1
2
3
4
for 变量列表 in 可迭代对象:
语句块1
else:
语句块2
1
2
3
4
sum = 0
for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
sum = sum + x
print(sum)

image-20220721151830427

for语句语法说明:

  1. 可迭代对象每次提供一个元素一次赋值给变量列表中的变量,赋值完毕后执行语块1,重复执行此步骤,直到可迭代对象不能提供数据为止
  2. 可迭代对象提供完所有元素后,执行else子句部分的语句块2,然后退出此for语句
  3. else子句部分可以省略(同while语句类似)
  4. 当在循环内部用break终止循环时,else子句部分语句不会执行

1.4 range函数

  • range(stop) 从零开始,每次生成一个整数后加1操作,直到stop为止(不包含stop)
  • range(start,stop[,step])从start开始,每次生成一个整数后移动step,直到stop为止(不包含stop,且step可以使负整数)
  • 作用:用来创建一个生成一系列整数的可迭代对象—也叫整数序列生成器
  • 说明:range返回的对象是可迭代对象,可以用于for语句中

特性1:左闭右开

1
2
3
# 左闭右开1<=i<6
for i in range(1, 6):
print(i)

image-20220721152227793

特性2:默认从0开始

1
2
for i in  range(3):
print(i)

image-20220721152309397

1.5continue语句

  • 作用:用于循环语句(while,for语句)中,不再执行本次循环内continue之后的语句,重新开始一次新的循环

    说明:

  1. 在while语句中,执行continue语句将会直接跳转到while语句的真值表达式处重新判断循环条件
  2. 在for语句中,执行contiune语句,将会从可迭代对象中取下一个元素,绑定变量后再次进行循环

2.函数基础function

2.1函数

1
2
3
4
5
def my_abs(x):
if x >= 0:
return x
else:
return -x

什么是函数:函数是可以重复执行的语句块,可以重复使用

  • 作用:
  1. 用于封装语句块,提高代码的重用性
  2. 定义用户级别的函数
  • 函数定义(创建)语句

image-20220721152620550

说明:

1)函数的名字就是语句快的名称

2)函数名的命名规则与变量名相同(函数名必须是标识符)

3)函数有自己的名字空间,在函数外部不可以访问函数内部的变量,在函数内部可以访问函数外部的变量,通常让函数处理外部数据需要用参数给函数传入一些数据

4)函数的形式参数列表可以为空

5)语句部分不能为空,如果为空需要补充pass语句

  • 函数的调用:

image-20220721152656049

注:实际调用传递参数以后统称实参

说明:

1)函数调用是一个表达式

2)如果没有return语句,此函数执行完毕后返回None对象

3)如果函数需要返回其他的对象需要用到return语句

2.2 return语句

  • 作用:用于函数中,结束当前函数的执行,返回调用该函数的地方,同时返回一个对象的引用关系

说明:

  • return语句后面跟的表达式可以省略,省略后相当于return None
  • 如果函数没有return语句,则函数执行完最后一条语句后返回None(相当于在最后加了一条return None语句)

2.3 引入参数检查

1
2
3
4
5
6
7
8
9
10
def my_abs_find_error(x):
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x
my_abs_find_error(8)
my_abs_find_error(-0.25)
my_abs_find_error("Hi")

image-20220721152917539

2.4 python函数的参数传递

传递方式:

1)位置传参:实际参数(实参)的对应关系和形式参数(形参)的对应关系是按照位置来以此对应的,实际参数和形式参数通过位置进行传递的匹配,实参个数必须与形参个数相同

1
2
3
4
5
6
7
def power(x, n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
power(3, 5)

image-20220721153139933

2)序列传参:序列传参是指在函数调用的过程中,用*将序列拆解后按位置传参的方式进行参数传递

1
2
3
4
5
6
7
8
def myfun(a,b,c):
print(a)
print(b)
print(c)
s = [1,2,3]
myfun(*s)
s2 = "ABC"
myfun(*s2)

image-20220721153528644

3)关键字传参:是指传参时,按着形参的名称给形参赋值,实参和形参按名称进行匹配

4)字典关键字传参:是指实参为字典,将字典用**拆解后进行关键字传参(1.字典的简明必须和形参名保持一致2.字典键名必须为字符串3.字典的键名要在形参中存在)

1
2
3
4
5
6
def myfun(a,b,c):
print(a)
print(b)
print(c)
d = {'c':33,'b':22,'a':25}
myfun(**d)

image-20220721153812184

5)综合传参:函数的传参方式,在确定形参能唯一匹配到相应实参的情况下可以任意组合

1
2
3
4
5
6
7
def myfun(a, b, c):
print(a, b, c)
myfun(100, *[200,300])
myfun(*'AB', 300)
myfun(100, c = 300, b = 200)#交叉进行传参,根据形参列表的索引进行交换传参
myfun(1,**{'c':3, 'b':2})
myfun(**{'c':3, 'b':2}, a = 1)

image-20220721153907822

2.5 函数默认参数

设置默认参数

1
2
3
4
5
6
def information(name, gender, age=6, city='Beijing'):
print('name:', name)
print('gender:', gender)
print('age:', age)
print('city:', city)
information('Sarah', 'F')

image-20220721153732717

!!!!默认参数的究极重要特性:

1
2
3
4
5
6
7
def add_string(L = []):
L.append('string')
return L
print(add_string([1,2,3]))
print(add_string())
print(add_string())
print(add_string())

image-20220721154202306

  • Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。

    【重要】默认参数必须指向不变对象!

2.6 函数的缺省参数

语法:def 函数名(形参名1=默认实参1,形参名2=默认实参2...)

说明:

  1. 缺省参数必须自右至左依次存在,如果一个参数有缺省参数,则其右侧的所有参数必须有缺省参数
  2. 缺省参数可以有0个或多个,甚至全部都有缺省参数

2.7 形参的定义方式

1)位置形参:def 函数名(形参名1,形参名2....)

2)可变参数:

1
2
3
4
5
6
7
def calc(numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
print(calc([2, 5, 6, 8]))
print(calc({2, 5, 7, 8}))

image-20220721154717986

3)星号数组形参

  • def 函数名(*元组形参名)
  • 作用:收集多合的位置传参
  • 说明:元组形参名通常用args
1
2
3
4
5
6
def func(*args):
print("参数个数是:", len(args))
print('args=', args)
func(1, 2, 3, 4)
func("hello", "world", 1, 2, 3)
func("hello,world")

image-20220721154826348

4)命名关键字形参

def 函数名(×,命名关键字形参)def 函数名(*args,命名关键字形参)

作用:所有的参数都必须用关键字传参或字典关键字传参

1
2
3
4
def func(*,d,e):
print("d=",d)
print("e=",e)
func(d=100,e=200)

image-20220721155003211

5)双星号字典形或def 函数名(*args,命名关键字形参)

作用:收集多合的关键字传参,通常字典形参名定位kwargs

【重点】

缺省形参,位置形参,星号元组形参,命名关键字形参,双星号字典形参可以混合使用。函数参数自左向右的顺序为:位置形参,星号元组形参,命名关键字形参,双星号字典形参

1
2
3
4
5
6
7
def f1(a, b, *args, c, **kwargs):
print(a)
print(b)
print(c)
print(args)
print(kwargs)
f1(1, 2, 3, 4, d = 6, c = 5, e = 7)

image-20220721155056453

2.8 函数的不定长参数

1
def func(*args,kwargs)

可以接受任意的位置传参和关键字传参

函数式编程:函数式编程是指用函数解决一系列问题

函数是一等公民!!!

1)函数本身可以赋值给变量,赋值后变量绑定函数

2)允许将函数本身作为参数传入另一个函数

3)允许返回一个函数

【案例制作】

小练习:

  • 写一个函数isprime(x)判断x是否为素数,如果是素数,返回True,如果不是返回False
  • 写一个函数prime_m2n(m,n)返回从m开始到n结束(不包含n)的范围内的素数列表
1
2
3
4
5
6
7
8
9
10
11
def isprime(x):
if x<=1:
return False
for i in range(2,x):
if x%i==0:#素数的判断方式,进行跟比自己小的每一个数进行取余
return False
return True
def prime_m2n(m,n):
return[x for x in range(m,n) if isprime(x)]#使用列表推导式--代码精简
l=prime_m2n(1,10)
print(l)

image-20220721155234322

2.9 函数的作用域

作用域:也叫名字空间,访问变量时查找变量名的范围空间

1)局部作用域:local function--L

2)外部嵌套函数作用域:enclosing function locals--E

3)函数定义所在模块作用域global(mudule)--G

4)Python内置模块的作用域 builtin(python)--B

范围包含越来越广

1
2
3
4
5
6
a = 8
def mytest():
a = 'hi'
print(a)
mytest()
print(a)

image-20220721155419133

2.10 global语句

  • 作用:告诉解释器global语句声明的一个或多个变量,这些变量的作用域为模块的作用域,也称作全局变量,全局声明(global)将赋值变量映射到模块文件内部的作用域
  • 语法:
1
global 变量1,变量2
1
2
3
4
5
6
7
8
v = 100
def f():
global v
v = 200
f()
print(v)
#有global语句的输出结果为:200
#无global语句的输出结果为:100

image-20220721155500964

说明:

  • 全局变量如果要在函数内部被赋值,则必须通过全局变量声明,否则会被认为是局部变量
  • 全局变量在函数内部不经过声明就可以直接访问
  • 不能先声明局部的变量,再用global声明为全局变量,此做法不符合规则
  • global变量列表里的变量不能出现在此作用域内的形参列表里

2.11 nonlocal语句

作用:告诉解释器,nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量。

语法:

1
nonlocal 变量名1,变量名2...
1
2
3
4
5
6
7
8
9
10
11
12
var = 100
def f1():
var = 200
print("f1里的var=", var)
def f2():
nonlocal var
var = 300
print("f2里的var=", var)
f2()
print("f2调用结束后f1里的var值为", var)
f1()
print('全局的var=', var)

image-20220721155629509

说明:

  • nonlocal语句只能在被嵌套函数内部使用
  • 访问nonlocal变量将对外部嵌套函数的作用域变量进行操作
  • 当有两层或两层以上的函数嵌套时,访问nonlocal变量只能对最近一层变量进行操作
  • nonlocal语句的变量列表里的变量名,不能出现在此函数的参数列表

2.12【案例】天天向上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#天天向上的力量
dayfactor = 0.01
dayup = pow(1 + dayfactor, 365)
daydown = pow(1 - dayfactor, 365)
print("向上:{:.2f},向下:{:.2f}".format(dayup, daydown))
#工作日的力量
dayup1 = 1.0
dayfactor1 = 0.01
for i in range(365):
if i % 7 in[6, 0]:
dayup1 = dayup1 * (1 - dayfactor1)
else:
dayup1 = dayup1 * (1 + dayfactor1)
print("工作日的力量:{:.2f}".format(dayup1))
#工作日的努力
def dayUp(df):
dayup2 = 1
for i in range(365):
if i % 7 in [6, 0]:
dayup2 = dayup2 * (1 - 0.01)
else:
dayup2 = dayup2 * (1 + df)
return dayup2
dayfactor2 = 0.01
while dayUp(dayfactor) < 37.78:
dayfactor += 0.001
print("工作日的努力值参数是:{:.3f}".format(dayfactor))

image-20220721155826839

2.13 lambda表达式

(又称为匿名函数)

  • 作用:创建一个匿名函数对象
  • 同def函数类似,但不提供函数名
  • 语法:
1
lambda[参数1, 参数2...]: 表达式
1
2
3
4
5
def myfunction1(x, y):
return x + y
myfunction2 = lambda x, y : x ** y
print(myadd(1, 2))
print(myadd2(3, 2))

image-20220721160020572

语法说明:

  • lambda只是一个表达式,它用来创建一个函数对象
  • 当lambda表达式调用时,先执行冒号后的表达式,并返回表达式的结果的引用
  • lambda表达式创建的函数只能包含一条表达式
  • lambda比函数简单,且可以随时创建和销毁,有利于减少程序的耦合度

2.14 eval()函数和exec()函数

eval()函数:

格式:

1
eval(source,global = None,locals = None)
  • 作用:把一个字符串当成一个表达式来执行,返回表达式执行后的结果

exec()函数:

格式:

1
exec(source,global = None,locals = None)
  • 作用:把一个字符串当成程序来执行

说明:evalexec的两个参数globalslocals此两个参数是用来设置’表达式’或’程序’运行的全局变量和局部变量

1
2
3
4
5
6
7
x = 100
y = 200
s = 'print(x,y,x+y)'
exec(s)
exec(s, {'x':10, 'y':20})
exec(s, {'x':10}, {'x':1, 'y':2})
exec(s, {'x':10}, {'y':2})

image-20220721160154953

3函数进阶

3.1 高阶函数

满足下列一个条件的函数即为高阶函数:

  • 函数接收一个或多个作为参数传入
  • 函数返回一个函数

Python中的高阶函数:

1)map(func, *iterables):用函数和可迭代对象中的每一个元素座位参数计算出新的可迭代对象,当最短的一个可迭代对象不再提供数据时,此可迭代对象生成结束

1
2
3
4
def pow2(x):
return x ** 2
for x in map(pow2, range(1, 10)):
print(x)

image-20220721160302780

匿名函数与高阶函数综合:

1
print(list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])))

image-20220721160510257

2)filter(func,iterable)

作用:筛选可迭代对象iterable中的数据,返回一个可迭代对象,此可迭代对象对iterable进行筛选

说明:函数func将对每个元素进行求值,返回False将次数据丢弃,返回True则保留此数据

1
2
3
4
5
6
def isodd(x):
return x % 2 == 1
for x in filter(isodd, range(1, 10)):
print(x)
even=[x for x in filter(lambda x : x % 2 == 0, range(10))]
print(even)

image-20220721160604458

3)sorted函数:

作用:将原可迭代对象的数据进行排序,生成排序后的列表

格式:sorted(iterable,key=None,reverse=False)

说明:

  • iterable是可迭代对象
  • key函数是用来提供一个参考值,这个值将作为排序的依据
  • reverse标志用来设置是否降序排序
1
sorted([36, 5, -12, 9, -21], key = abs)

image-20220721163948558

3.2 函数递归

函数直接或间接的调用自身

递归说明:

1)递归一定要控制递归的成层数,当符合某一条件时要终止递归

2)几乎所有的递归都能用while循环来代替

  • 对象:属性和方法
  • 分而治之:通过函数或对象封装程序划分为模块和模块之间的表达
  • 紧耦合:两个部分交流很多,无法独立存在松耦合:两个部分交流很少,可以独立存在
  • 函数递归的理解:链条:计算过程之间存在递归链条基例:存在一个或多个不需要再次递归的基例实现递归:函数和分支语句的结合,递归本身也是一个函数

控制递归的示例:

1
2
3
4
5
6
7
8
def fx(n):
print("递归进入第:", n, "层")
if n == 3:
return
fx(n + 1)
print("递归退出第", n, "层")
fx(1)
print("end")

image-20220721160808982

递归的优缺点:

  • 优点:递归可以把问题简单化,让思路更为清晰,代码更为简洁
  • 缺点:递归因系统影响较大,当递归深度太大是,可能会得到不可预知的结果

实现方法:先假设函数已经实现

1
2
3
4
5
6
#递归例子1:字符串翻转
def rvs(s):
if s == "":
return s
else:
return rvs(s[1:]) + s[0]

image-20220721160857277

1
2
3
4
5
6
#递归例子2:斐波那契数列
def f(n):
if n == 1 or n == 2:
return 1
else:
return f(n - 1) + f(n - 2)

image-20220721160947600

1
2
3
4
5
6
7
8
9
10
11
12
#递归例子3:汉诺塔问题
count = 0
def hanoi(n, src, dst, mid):
global count
if n == 1:
print("{}:{}->{}".format(1, src, dst))
count += 1
else:
hanoi(n - 1, src.mid, dst)
print("{}:{}->{}".format(n, src, dst))
count += 1
hanoi(n - 1, min, dst, src)

3.3 闭包

闭包closure

将内嵌函数的语句和这些语句的执行环境打印在一起时,得到的对象称为闭包(closure)

闭包必须满足三个条件:

  • 必须有一个内嵌函数
  • 内嵌函数必须引用外部函数中的变量
  • 外部函数返回值必须是内嵌函数
1
2
3
4
5
6
def make_power(y):
def fx(arg):
return arg ** y
return fx #返回的是一个函数
pow2 = make_power(2) #pow2=make_power中y赋值为2的函数
print(pow2(3))

image-20220721161215203

3.4 函数装饰器

(函数高级用法)

函数装饰器是指装饰的是一个函数,传入的是一个函数,返回的也是一个函数

函数装饰器语法:

1
2
3
def 装饰器函数名(参数):
语句块
return 函数对象

被装饰函数语法:

1
2
3
@装饰器函数名
def 函数名(形参列表)
语句块被装饰函数的语法:
1
2
3
4
5
6
7
8
9
10
11
12
#装饰器函数
def mydeco(fn):
def fx():
print('+++++++++')
fn()
print('---------')
return fx
@mydeco
def myfunc():#相当于myfunc()放到fn()中了
print("myfunc被调用")
myfunc()
myfunc()

image-20220721161332798

装饰器应用案例

银行业务:存钱savemoney取钱 withdraw添加短消息余额变动提醒功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def message_send(fn):
def fx(name, x):
print("发送消息:", name, "来银行办理业务")
fn(name,x)
print("发送信息:", name, "办了", x, "元的业务")
return fx
@message_send
def savemoney(name,x):
print(name, "存钱", x, "元")
@message_send
def withdraw(name,x):
print(name, "取钱", x, "元")
savemoney('小李', 200)
savemoney('小赵', 500)
withdraw('小王', 300)

image-20220721161418093

3.5 函数文档字符串

函数内部,第一个没有赋值给任何变量的字符串为文档字符串

语法:

1
2
3
def 函数名(形参列表):
'''函数的第一个字符串'''
pass

作用:让调用者明白函数的用途和含义

通过help函数可以访问

3.6 函数的doc属性

__doc__属性用于绑定该函数的文档字符串

1
2
3
4
def fx(a,b):
'''这是第一行字符串
这是第二行'''
print(fx.__doc__)

image-20220721161457383

3.7 函数的name属性

__name__属性用于绑定函数

1
2
3
4
def fx():
pass
f1 = fx
print(f1.__name__)

image-20220721161538909

函数定义语句(def语句的语法汇总)

1
2
3
4
5
6
[@装饰器名1]
[@装饰器名2]
....
def 函数名([位置形参],[元组形参名],[命名关键字形参],[**字典形参]):
'''文档字符串'''
语句块

说明:默认参数(缺省参数):绑定在函数对象内部,随函数的生命一起存在

1
2
3
4
5
6
7
8
9
10
11
12
def f(n, lst = []):
lst.append(n)
print(lst)
f(100)
f(200)
def f2(n, lst = None):
if lst is None:
lst = []
lst.append(n)
print(lst)
f2(100)
f2(200)

image-20220721161616615