函数和模块的使用
函数的参数
#函数的参数
#普通参数 最简单的参数
#收集参数:不确定要传递多少个参数,使用*args,最后会形成一个元组
def fuc(*args):
sum=0
for i in args:
sum+=i
print(sum,args)
fuc(1,2,3,4,5,5,6)#26 (1, 2, 3, 4, 5, 5, 6)
*args表示任何多个无名参数,它是一个tuple;
#收集关键字参数
def fuc(**kwargs):
for i,j in kwargs.items():
print(i,j)
fuc(name='huang',age=12,sex='男')
**kwargs表示关键字参数,它是一个 dict。
并且同时使用args和kwargs时,必须*args参数
列要在kwargs前,像foo(a=1, b=‘2’, c=3, a’,
1, None, )这样调用的话,会提示语法错误“SyntaxError: non-keyword arg after keyword arg”。
函数变量的作用域
#global
num=1#不可变变量
ls1=[1,2,3]#可变变量
def main():
# 在函数内部无法改变不可变的变量,将其改为全局变量
global num
num+=1
# 在函数内部可以改变可变变量
ls1.append(4)
print(ls1,num)
print(globals())#用来查找所有全局变量
print(locals())#用来查找所有局部变量
main()
#print
print(globals())
print(locals())
#函数内定义的变量函数外不能使用,除非变成全局变量
#nonlocal函数
#直接看例子,如果有两层函数,内层函数想调用外层函数的不可变的变量(整型等),内层函数现需要用nonlocal引用。
'''
这是外层的注释
'''
def outer():
'''
这是一个函数的注释
:return:
'''
num=10
ls1=[1,2,3]
def inner():
nonlocal num
num+=1
ls1.append(4)
print(num,ls1)
return inner()
outer()
print(globals())
'''
脚本有默认的魔法方法,其中__name__==__main__的时候是脚本作为主程序运行,当脚本作为模块的时候__name__就是脚本名字
__doc__是脚本的注释
'''
# '__name__': '__main__',
# '__doc__': '\n这是外层的注释\n',
#单独打印函数的注释
print(outer.__doc__)
高阶函数
递归函数
#递归函数就是定义了一个函数,然后在函数内,自己调用自己
#递归函数必须有结束
#一层一层进入再一层一层返回
def digui(num):
print(num,end='')
if num>0:
digui(num-1)
#进到最里层后先打印最里层然后在一层一层出来
print(num,end='')
digui(3)#32100123
#用递归函数实现阶乘
def jiecheng(num):
if num==1:
return 1
else:
return num*jiecheng(num-1)
print(jiecheng(5))
#用递归函数实现斐波那契数列
def feibonaqie(n):
'''
求第n位的斐波那契数列是什么
:param n:
:return:
'''
if n==1:
return 1
if n==2:
return 1
#第n为等与n-1位加n-2位
else:
return feibonaqie(n-1)+feibonaqie(n-2)
print(feibonaqie(5))
回调函数
#回调函数就是将函数作为传入的参数
def huidiao(x,y,f):
print(f([x,y]))
huidiao(1,2,sum)
闭包函数
#在函数中返回了一个函数,并且内函数使用了外函数的局部变量
#作用一是可以保护变量受更改
#一个简单的闭包,可以保护money不能在外部更改
def outer():
money=0
def inner():
nonlocal money
money+=100
print(money)
return inner
res=outer()
res()
#查看一个函数是不是闭包,如果是返回cell,如果不是返回None
print(res.__closure__)
#作用2 写一个装饰器
#这个func就是我们要接收的函数(需要装饰的函数)
#我们设置一个装饰器,它的功能就是在原函数print之前先print一句话
def func1(func):
def func2():
print('我是闭包')
#这里传回的是原函数的执行
return func()
#这里将闭包传回
return func2
#语法糖
@func1
def func():
print('这是一个普通的函数')
#假如装饰器和被装饰的函数都有参数的处理
#写一个带参数的装饰器,装饰一个带参数的函数
#装饰器有三层
def outer(sex):#装饰器参数写外层
def medium(fun):
def inner(x,y):#函数参数写内层
if sex=='man':
print('我是男的,我喜欢奥运')
else:
print('我是女的,我不喜欢奥运')
return fun(x,y)#返回时候别忘了传参数
return inner
return medium
#给这个函数加一个装饰器
@outer('男')
def winter_olypic(time,area):
print(f'{area}要在{time}月举办奥运会了!')
winter_olypic(12,'北京')
匿名函数 lambda表达式
#定义一个不需要名字的函数,在相对简单的函数构造中使用
#定义一个加法
res=lambda x,y:x+y
print(res(1,2))
#定义一个分支结构
res_=lambda x:f'这是{x}' if x=='man' else f'这不是{x}'
print(res_('man'))
迭代器
#用来访问集合元素的一种方式,迭代器可以记住访问遍历的位置,迭代器只能一个一个遍历,不能后退。
#iter()可以转换为迭代器对象
#功能:将一个可迭代对象,转为一个迭代器对象
#参数:可迭代对象(list,list,tuplt,set,range,str)
#返回迭代器对象
#取值方式(一次性)
#使用next()去调用,每一次可以取迭代器里面的一个数据
#使用list()可以一次性取出
#使用for()循环取出
list1='abcd'
ls=iter(list1)
print(ls,type(ls))#
print(next(ls))#a
print(list(ls))#['b', 'c', 'd']
list1='abcd'
ls=iter(list1)
#检测是可迭代对象还是迭代器
from collections import Iterator,Iterable
#字符串是一个可迭代对象,但不是迭代器对象
print(isinstance(list1,Iterable))#True
print(isinstance(list1,Iterator))#False
#迭代器是一个可迭代对象,也是迭代器对象
print(isinstance(ls,Iterator))
print(isinstance(ls,Iterable))
内置函数
#range() 包头不包尾
#取值方式
#转为list
res=range(10)
print(list(res))
#for循环
for i in res:
print(i,end='')
#转为迭代器
res_=iter(res)
print(next(res_))
print(next(res_))
#zip(*iterable)接收任意个可迭代对象,之后把第i个元素组合在一起返回一个元组迭代器
ls1=[1,2,3]
ls2=set([4,5,6])
ls3=(7,8,9)
res=zip(ls1,ls2,ls3)
print(res)#
from collections import Iterator
print(isinstance(res,Iterator))#True
#可以使用迭代器的取值方式
print(next(res))#(1, 4, 7)
print(list(res))# [(2, 5, 8), (3, 6, 9)]
#*和*zip的探究
#在python中,*可以拆掉外层的数据结构,但是一般不能单独使用
ls0=[(1,),(2,)]
ls00={(1,)}
ls000=[1,2,3]
# print(*ls0,*ls00)#(1,) (2,) (1,)
# print(*ls000)#1 2 3
#如果直接res=*ls0会报错
#对于迭代器对象同样可以,但是会使迭代器对象变空
list1=[1,2,3]
list_=iter(list1)
print(*list_)#1 2 3
print(list_)#
print(list(list_))#[]
#因此在*使用zip函数的过程中就有这样的用途
ls1=[1,2,3]
ls2=set([4,5,6])
ls3=(7,8,9)
#*号可以拆掉数据外层结构
print((*zip(ls1,ls2,ls3)))#将zip返回的迭代器对象变成了三个单独的元组(1, 4, 7) (2, 5, 8) (3, 6, 9)
'''
因此在下面就有这样的操作
首先zip(*zip(ls1,ls2,ls3))是先合在一起变成迭代器对象,拆开后变成三个元组,在进行zip就恢复到原来的三个元组了,在使用*list可以看到三个单独的元组了
'''
print(*list(zip(*zip(ls1,ls2,ls3))))#(1, 2, 3) (4, 5, 6) (7, 8, 9)
#数学相关
#abs
print(abs(-10))#10
#sum中必须是可迭代对象
print(sum([1,2,3]))#6
#max
print(max(1,2,3),max([1,2,3]))#3
# 求幂
print(pow(5,4))#625
#四舍五入
print(round(1.5))#2
#进制相关
#转化为二进制bin
#转化为八进制oct
#转化为16进制hex
#转化为ascii码ord
#将字符转为ascii码chr
print(bin(10),
oct(10),
hex(10),
ord('a'),
chr(98))
#0b1010 0o12 0xa 97 b
其他高阶函数
#sorted(iterable;reverse=False;key=函数)
#返回排序后的结果
#运行原理:把可迭代的数据一个一个取出然后放到key里面的函数里处理,并按照函数中return的结果再进行排序,返回一个新的列表
ls1=[1,-3,4,8,5,6,10]
print(sorted(ls1))#[-3, 1, 4, 5, 6, 8, 10]
print(sorted(ls1,reverse=True,key=abs))#[10, 8, 6, 5, 4, -3, 1]
print(sorted(ls1,key=lambda x:x%2))#[4, 8, 6, 10, 1, -3, 5]
#map(func,iterable)
#对传入的可迭代对象放入func中进行处理,之后返回一个迭代器对象
ls1=[1,2,3,4]
res=map(lambda x:x**2,ls1)
print(list(res))
#reduce(func,iterable)
#从迭代对象中取出两个元素放入func中计算,得到的结果在与可迭代对象中的第三个元素放入func中计算,以此类推到最后
# 返回func最终运算的处理结果
#将'123'转换成123
from functools import reduce
ls1='123'
result=reduce(lambda x,y:int(x)*10+int(y),ls1)
print(result)#123
#filter(func,iterable)
#把每个数据输入func,True保留,False丢弃,返回迭代器
varlist=[1,2,3,4,5,6,7,8]
res=filter(lambda x:x%2==0,varlist)
print(list(res))