文章目录
一、函数
- 模块化编程
模块化编程指把程序进行封装(函数封装、面向对象、文件…) - 函数
函数是一个具有特定功能的代码块,就是将代码进行封装,提高代码的重用性,提高开发效率 - 函数的定义
# 定义函数 [基本结构]
def 函数名([参数列表]):
功能代码
...
# 函数定义后并不会执行,需要进行调用
函数名()
- 函数的特征和注意
1. 函数定义后,不调用不执行
2. 不能在函数定义前调用函数
3. 函数的调用不受次数影响
4. 函数的命名要遵守命名规范
字母数字下划线,不用数字开头
严格区分大小写,不能使用关键字
命名最好有意义,且不要使用中文
函数名不能有冲突,冲突后会被覆盖
1. 函数的参数
'''
命名关键字参数:
1. 关键字参数定义在 收集参数 后面
2. 关键字参数必须通过形参的名字来进行传递
'''
def func(a,b,c=3,*args,name):
print(a,b,c)
print(args)
print(name)
func(1,2,7,4,5,6,7,8,9,name="me")
'''
1 2 7
(4, 5, 6, 7, 8, 9)
me
'''
# 在调用函数时,需要按照顺序进行参数的传递
# 也可以把普通函数的普通参数按照关键字参数进行传递
def func1(age,height):
print(age)
print(height)
func1(height=180,age=19) # 19 180
'''
关键字收集参数
'''
def func2(a,b,c=3,*args,name,**kwargs):
print(a,b,c)
print(args) # 普通收集参数,会把多余的参数收集成 元组
print(name)
print(kwargs) # 关键字参数收集,会把多余的关键字参数收集为字典
# 注意形参声明的位置: 普通参数 --> 默认参数 --> 收集参数 --> 关键字参数 --> 关键字收集参数
func2(1,2,4,112,113,name="aaa",age=222,sex="男")
'''
1 2 4
(112, 113)
aaa
{'age': 222, 'sex': '男'}
'''
2. 函数的返回值
– 函数除了可以完成一定的功能外,还可以按需要返回一些内容,使用return
关键字来指定返回的参数,可以返回任意类型的参数
– 函数的返回值会把数据返回调用处,可以使用变量接收
'''
函数的返回值
return 意味着函数的结束,之后的代码不执行
1. 执行过程函数:函数内完成一定功能,没有返回值
2. 有返回值的函数,函数内完成一定功能,并返回一个结果到函数调用处
'''
def hi(a,b):
res = (f"{a} love {b}")
return res
def hi1(a,b):
res = (f"{a} love {b}")
say=hi("fa","mo")
print(say) # fa love mo
say=hi1("羊","狼")
# 函数中没有使用return或者return后没有任何内容,那么默认返回none
print(say,type(say)) # None <class 'NoneType'>
3. 变量的作用域
'''
变量作用域:变量的有效范围
全局变量:在函数内外都可以使用的变量
1. 在函数内部使用global关键字定义的变量就是全局变量
2. 在函数外定义的变量,在函数内使用global关键字进行声明,那么也是全局变量
局部变量:函数内部可以使用的变量
globals(): 获取全局数据,在任何位置都可获取
locals(): 获取当前作用域的数据
注意:
1. 函数内可以直接获得函数外部的变量
2. 函数内不可直接更改函数外的变量
3. 函数内定义的变量(局部变量),函数外不能使用
变量分两种:
1.可变数据类型:在函数外定义的变量,在函数内可以使用和更新
列表和字典
2.不可变数据类型:在函数外定义的变量,在函数内只能访问,不能使用其他操作
'''
num=10
varlist=[1,2,3]
vardict={'a':'a','b':'b'}
def func3():
print(num) # 10 函数内可以直接获得函数外部的变量
# num+=20 在函数内不可直接更改函数外的变量
nei="pao"
print(nei)
# 可变数据类型
varlist[2] = "狗"
print(varlist) # [1, 2, '狗']
vardict['a'] = 'aa' # {'a': 'aa', 'b': 'b'}
print(vardict)
# 在函数内部使用global关键字定义的变量就是全局变量
global live
live = 'keep going'
func3()
# print(nei) not defined 函数内定义的变量(局部变量),函数外不能使用
print(varlist) # [1, 2, '狗']
print(live) # keep going
4. nonlocal 关键字
'''
nonlocal 关键字
# 变量和函数都有作用域
# 在内函数中如何使用上一层函数中的局部变量?
使用 nonlocal 关键字引用
'''
# 定义一个外函数
def outer():
'''
这里是用来写当前函数的文档说明的
需要说明当前函数的作用
如果当前函数还有形参,那么还需要对形参进行一一说明
:return: 此处说明当前函数的返回值
'''
# 外函数的局部变量
num = 10
def inner():
# nonlocal 关键字在局部函数中使用
nonlocal num # 引用上一层函数中定义的局部变量,但依然不能提升为全局变量
num += 1
print(num)
inner()
outer()
print(__name__) # 获取当前脚本的文件名
print(__doc__) # 获取当前脚本的说明文档 (第一个''''''引用的内容)
print(outer.__doc__) # 获得当前函数的说明文档
5. 高阶函数
5.1 递归函数
'''
递归函数:
递归函数就是定义了一个函数,然后在函数内,自己调用自己的这个函数
递归函数内必须要有结束,不然会导致栈溢出
递归函数是一层一层地进入,再一层一层地返回
'''
def func1(num):
print(num)
if num >0: # 判断递归调用的条件
func1(num-1)
print(num) # 一层一层返回 0 1 2 3
func1(3) # 3 2 1 0 1 2 3
print("======================")
# 递归实现一个数的阶乘 1*2*3*4*5
res=1
def func2(num):
if num == 1:
return 1
else:
return num*func2(num-1)
res = func2(4)
print(res) # 24
# 递归实现斐波那契数列,求第n位上的数是多少? 1,1,2,3,5,8,13...
def fei(n):
if n==1 or n==2:
return 1
else:
return fei(n-1)+fei(n-2)
res3 = fei(6)
print(res3) # 8
5.2 回调函数
'''
回调函数
函数中的参数可以是任意类型的,如果在一个函数中要求传递的参数是一个函数作为参数,
并且在函数中使用了传递进来的函数,那额这个函数就是回调函数
'''
# 定义一个函数,函数中的一个参数要求是另一个函数
def hd(f):
print(f, type(f))
def love():
print("123")
hd(love) # <function love at 0x00C8C0B8> <class 'function'>
5.3 闭包函数
'''
闭包函数
既然可以把函数作为一个形参进行传递,作为回调函数,那么如果在一个函数中,返回一个函数呢?
在一个函数内返回了一个内函数,并且这个返回的内函数还使用了外函数中的局部变量,这就是闭包函数
闭包的特点:
1. 在外函数中定义了局部变量,并且在内部函数中使用了这个局部变量
2. 在外函数中返回内函数,返回的内函数就是闭包函数
3. 闭包的作用: 保护了函数中的变量不受外部的影响,但是又能够不影响使用
'''
# 外函数
def person():
money = 0 # 局部变量
# 内函数
def work():
nonlocal money # 在内函数中使用了外函数的临时变量
money+=100
print(money)
# 在外函数中返回了内函数,这个内函数就是闭包函数
return work
res = person() # retuen work
res() # res() == work()
res() # 200
# 检测一个函数是否为闭包函数,函数名.__closure__如果是闭包函数返回cell
print(res.__closure__) # (<cell at 0x019CD910: int object at 0x014E7CF0>,)
5.4 匿名函数
'''
匿名函数 lambda表达式
匿名函数的意思即可以不使用def定义,并且这个函数也没有名字
在python中可以使用lambda表达式来定义匿名函数
注意: lambda表达式仅仅是一个表达式,不是一个代码块,所有lambda又称为一行代码的函数
lambda表达式也有形参,并且不能访问除了自己形参之外的任何数据包括全局变量
lambda不能写太复杂的逻辑,功能相对单一
语法:
lambda [参数列表]:返回值
'''
res = lambda x,y:x+y
print(res(4,2))
# 带有分支结构的lambda表达式
# lambda 参数列表: 真区间 if 表达式判断 else 假区间
res = lambda sex:"henman" if sex=="男" else "nice"
print(res("nv"))
5.5 迭代器
'''
迭代器
迭代器是python中最具特色的功能之一,是访问集合元素的一种方式
迭代器是一个可以记住遍历访问的位置的对象
从集合的第一个元素访问,直到集合中的所有元素被访问完毕
迭代器只能从前往后一个一个遍历,不能后退
能被next()函数调用,并不断返回下一个值的对象称为迭代器(iterator 迭代器对象)
'''
# range(10) 0--9 返回一个可迭代的对象
- iter()
'''
iter()
功能:把可迭代的对象,转换为一个迭代器对象
参数:可迭代的对象 (str,list,tuple,dict,set,range...)
返回值:迭代器对象
注意:迭代器一定是可以迭代的对象,但是可迭代对象不一定是迭代器
'''
# 定义一个列表,是一个可迭代的对象
arr = ["赵四", "刘能", "沈阳", "拉面"]
# for i in arr:
# print(i)
# 把可迭代对象转换为迭代器使用
res = iter(arr)
print(res, type(res)) # <list_iterator object at 0x0141DBC8> <class 'list_iterator'>
r = next(res)
print(r) # 赵四
print(next(res))
print(next(res))
print(next(res)) # 拉面
# print(next(res)) 超出可迭代的范围 StopIteration
r = list(res)
print(r) # []
- 迭代器取值
'''
迭代器取值的方案
1. next() 调用一次获取一次,直到数据被取完
2. list() 使用list函数直接取出迭代器中的所有数据
3. for 使用for循环遍历迭代器的数据
迭代器取值的特点: 取出一个少一个,直到都取完,最后再获取就会报错
'''
# 使用list取值
r = list(res)
print(r) # []
# 使用for
for i in res:
print(i)
- 检测迭代器和可迭代对象
'''检测迭代器和可迭代对象的方法'''
# 迭代器一定是一个可迭代的对象,可迭代对象不一定是迭代器
from collections.abc import Iterator, Iterable
varstr = '123456'
res = iter(varstr)
# type() 函数返回当前数据的类型
# isinstance() 检测一个数据是不是一个指定的类型
r1 = isinstance(varstr,Iterable) # True 是一个可迭代对象
r2 = isinstance(varstr,Iterator) # False 不是一个迭代器
# next()
next(varstr) # 'str' object is not an iterator
print(r1)
print(r2)
6. 内置函数
- 内置函数是系统安装完python解释器时,由python解释器给提供好的函数
6.1 range()
'''
range() 函数
功能:能够生成一个指定的数字序列
参数:start, stop[, step]
返回值:可迭代的对象,数字序列
'''
res = range(10)
print(list(res)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for i in res:
print(i)
res = range(1,10,2)
print(list(res)) # [1, 3, 5, 7, 9]
# 获取一个倒序的数字序列
res = range(10,1,-2)
print(list(res)) # [10, 8, 6, 4, 2]
res = range(-10,-20,-1)
print(list(res)) # [-10, -11, -12, -13, -14, -15, -16, -17, -18, -19]
6.2 zip()
'''
zip()
功能:zip函数是可以接收多个可迭代的对象,然后把每个可迭代对象中的第i个元素组合在一起,形成一个新的迭代器
参数:*iterables,任意个数的可迭代对象
返回值:返回一个元组的迭代器
zip() 与 * 运算符相结合可以用来拆解一个列表
'''
var1 = [1, 2, 3, 4]
var2 = ['a', 'b', 'c', 'd']
var3 = ('A', 'B', 'C', 'D')
# 调用zip函数,组成新的元组迭代器
res = zip(var1, var2, var3)
print(res, type(zip())) # <zip object at 0x01D30E88> <class 'zip'>
# print(list(res)) # [(1, 'a', 'A'), (2, 'b', 'B'), (3, 'c', 'C'), (4, 'd', 'D')]
for i in res:
print(i)
x = [1, 2, 3]
y = [4, 5, 6]
zipped = zip(x, y)
print(list(zipped)) # [(1, 4), (2, 5), (3, 6)
print(zip(x,y)) # 迭代器对象:<zip object at 0x00E60D28>
print(*zip(x, y)) # 组合好的多个元组数据 (1, 4) (2, 5) (3, 6)
x2, y2 = zip(*zip(x, y)) # (1, 2, 3) (4, 5, 6)
print(x2,y2)
# x == list(x2) and y == list(y2)
# True
6.3 数学相关函数
- 数学计算函数
'''数学相关函数'''
# 返回一个数的绝对值
print(abs(-10)) # 10
# 求和 sum(iterable[, start]) 参数是一个可迭代对象
print(sum([1,2,3]))
# 返回最大值
print(max([1,2,3])) # 3
print(max(99,12,45)) # 99
# 幂运算 pow(x,y) 返回x的y次方
print(pow(2,3)) # 8
# 四舍五入 round(number[, ndigits]) 返回number舍入到小数点后ndigits位精度的值。如果ndigits被省略或为None
# 四舍六入 五留双 (如果与两个倍数的距离相等,则选择偶数 奇进偶退)
r = round(3.1415926,3)
print(r) # 3.142
print(round(4.5)) # 4
print(round(5.5)) # 6
- 进制相关函数
'''进制相关函数'''
# bin() 将数值类型转为二进制
print(bin(123)) # 0b1111011
# int() 将二进制转为十进制
print(int(0b1111011)) # 10
# oct() 转为八进制
print(oct(123)) # 0o173
# hex() 转为十六进制
print(hex(123)) # 0x7b
- ascii 字符转换
'''ASCII 字符转换
A - Z 65-90
a - z 97-122
0 - 9 48-57
'''
# 将字符转为ascii ord()
print(ord('a')) # 97
# 将ascii转为字符 chr()
print(chr(97)) # a
6.4 高阶函数
sorted()
'''
sorted()
运行原理:把可迭代数据里面的元素,一个一个取出来,放到key这个函数中进行处理,并按照函数中return的结果进行排序,返回一个新的列表
功能:排序
参数:
iterable 可迭代的数据(容器类型数据,range数据序列,迭代器)
reverse 可选,是否反转,默认为false(不反转)
key 可选,可以是自定义函数,也可以是内置函数
返回值:排序后的结果
'''
arr = [3,7,1,-9,20,10]
res = sorted(arr)
print(res) # [-9, 1, 3, 7, 10, 20] 默认
res1 = sorted(arr,reverse=True)
print(res1) # [20, 10, 7, 3, 1, -9] 反转
# 使用abs() 这个函数作为sorted的key关键字参数使用
res3 = sorted(arr,key=abs) # 3 7 1 9 20 10
print(res3) # [1, 3, 7, -9, 10, 20]
# 使用自定义函数 作为sorted的key关键字参数使用
def func(num):
return num % 2
arr = [3,2,4,6,5,7,9]
res4 = sorted(arr,key=func) # 1 0 0 0 1 1 1
res5 = sorted(arr,key=lambda x:x%2) # 这里自定义函数可以简化为lambda函数
print(res4) # [2, 4, 6, 3, 5, 7, 9]
print(res5) # [2, 4, 6, 3, 5, 7, 9]
map()
'''
map(function, *iterables)
功能:对传入的可迭代数据中每个元素进行处理,返回一个新的迭代器
参数:
func 函数 自定义函数|内置函数
iterables: 可迭代的数据
返回值:迭代器
'''
varlist = ['1','2','3','4']
# newlist = []
# for i in varlist:
# newlist.append(int(i))
# print(newlist)
res = map(int,varlist) # varlist中的每个元素都用int函数进行处理,返回新的迭代器
# print(list(res)) # <map object at 0x01A5D5C8> [1, 2, 3, 4]
res1 = map(lambda x:x**2,list(res))
print(list(res1)) # [1, 4, 9, 16]
reduce()
'''
reduce(func, *iterables)
功能:每一次从iterable中拿出 两个 元素,放入到func函数中进行处理,得出一个计算结果,然后将计算结果和iterable中的第三个元素,
放入到func函数中继续运算,得出的结果和之后的第四个元素运算,以此类推...
参数:
func 函数 自定义函数|内置函数
iterables: 可迭代的数据
返回值: 最终的运算处理结果
注意: 使用reduce函数时,需要导入 from functools import reduce
'''
varlist1 = [5,2,1,1]
def func(x,y):
return x*10+y
'''
5211
5 * 10 + 2 == 52
52 * 10 + 1 == 521
521 * 10 + 1 == 5211
'''
res = reduce(func,varlist1)
print(res) # 5211
# 不使用int函数,将'456' ==> 456
def myfunc(s):
vardict = {'1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
return vardict[s]
# 1.先用map函数把字符转换为数字
iter1 = map(myfunc,'456')
# print(iter1) # <map object at 0x01C5DCE8>
# print(list(iter1)) # [4, 5, 6]
# 2.把数字列表中的值,使用lambda进行二次处理
res = reduce(lambda x,y:x*10+y,iter1)
print(res) # 456
filter()
'''
filter(func, iterable)
功能:过滤数据,把iterable中的每个元素拿到func函数中进行处理,如果函数返回true则保留这个数据,返回false则丢弃这个数据
参数:
func 函数 自定义函数|内置函数
iterables: 可迭代的数据
返回值:保留下来的数据组成的迭代器
'''
# 保留所有的偶数,丢弃所有奇数
var3 = [1,2,3,4,5,6,7,8,9]
# def ou(x):
# if x%2==0:
# return True
# else:
# return False
res = filter(lambda x:True if x%2==0 else False,var3)
print(list(res)) # [2, 4, 6, 8]