参数间的优先级:位置参数>关键参数、默认参数
形参
实参
位置参数 :按位置把形参和实参对应起来。def 带几个参数调用def时就要传几个参数,否则程序会报错
默认参数:可在形参处设置默认参数,必须写在末尾处(重要提醒:默认参数在定义时赋值,且仅仅赋值一次,当函数多次被调用,且并没有提供默认的参数值,就会从定义时赋值的地方取得值。即使函数中给默认参数重新赋值了,下次调用还是会从定义赋值的地方取得值!)
i=5
def function(argument=i):
print(argument)
i=6
function()
输出:
5
当默认参数为可变类型的list/dict等类型时,需要注意:
def function2(a,l=[]):
l.append(a)
return l
print(function2(1))
print(function2(1,[]))
print(function2(3))
输出:
[1]
[1]
[1,3]
关键参数:带参数名赋值
非固定参数:在定义函数时候,不确定后面调用时,会传递多少个参数进来,用*args,**kwargs来表示:额外追加的关键参数会被kwargs接收(字典),位置参数被args接收(数组)
执行完return函数结束,可以return多个值(以元组的形式)
全局变量(程序一开始定义的变量)和局部变量(函数内定义的变量)
在函数里不能直接修改全局变量(但当全局变量是列表或字典时除外,可对其进行增删改),如果一定要修改可以在函数内部声明一个全局变量:global XXXXX(不建议使用)
print(locals())打印局部变量
print(globals())打印全局变量
name="小圆圈"
def change():
name="小圆圈,学编程"
def change2():
name="90天自学编程"
print("第三层打印",name)
change2() #调用内层函数
print("第二层打印",name)
change()
print("最外层打印",name)
输出:
第三层打印 90天自学编程
第二层打印 小圆圈,学编程
最外层打印 小圆圈
def calc(x,y):
return x**y
print(calc(2,5))
匿名函数语法:
c=lambda x,y:x**y
print(c(2,5))
主要是和其他函数搭配使用:
例如和map(func, *iterables)
map(lambda x:x2,[1,5,7,4,8])
三元运算:lambda x:x2 if x>7 else x**3
def func(x):
if x<=3:
return x**2
if x>3:
return x**3
def maps(num,f):
return f(num)
print(maps(6,func))
特点:1.接受一个或多个函数作为输入 2.return返回另外一个函数。满足其中一个即使高阶函数
另外,python的map()也是一个高阶函数
def func(tuple):
l=[]
for x in tuple:
l.append(x**2)
return l
def map(f,*args):
return f(args)
print(map(func,1,3,4,5,7))
一个函数在内部调用自己本身,这个函数就叫做递归函数
def fun(n):
print(n)
n = n // 2
if n>0:
fun(n) #调用自己
print(n)
fun(50)
输出:
50
25
12
6
3
1
0
1
3
6
12
25
执行过程:
函数在每进入下一层的时候,当前层并未结束,它必须等它调用的下一层函数执行结束返回后它才会往下走,所以下面那句print(n)会等最里层函数执行时才会执行,然后再往外退层,所以会出现0以后倒着打印的效果
特性:1.必须有一个明确的结束条件 2.没进入更深一层递归时,问题规模相比上一次递归应有所减少 3.递归效率低,递归层数过多会导致栈溢出(在计算机里,函数调用是通过栈stack这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小有限,所以递归调用的次数过多会导致栈溢出)
id()
abs() #求绝对值
ascii() #返回ascii码
bin() #返回整数的二进制
bool()
all() #遍历所有值,如果有一个是False就返回False否则返回True
any() #遍历所有值,如果有一个是True就返回True否则返回False
bytearray() #(字符串不可修改)用bytearray()就可以实现修改
bytes() # bytes(“中国”,“utf-8”) 等同于 “中国”.encode(“utf-8”)
callable #判断一个对象是否可调用
chr #返回一个数字对应的ascii字符
dir() #返回对象的可调用属性
enumerate() #返回索引和元素
eval() #把字符串形式的list,dict,set,tuple转换成原有的数据类型
exec #把字符串格式的代码进行解译并执行,比如exec(“print(‘hello world’)”),会解意里面的字符串并执行
filter() #对list、dict 、set、tuple等可迭代对象进行过滤,filter(lambda x: x % 2 == 0, range(10))过滤出10以内能被2整除的数
max() #求最大值,可对列表、字典等求最大值
next()
object()
oct() #求八进制
ord () #返回十进制
vars() #返回一个对象属性
zip() #可以把两个或者多个列表拼成一个由元组组成的列表
a=[1,4,8,9] ,b=[‘b’,‘c’,‘e’]
list(zip(a,b)) 输出:[(1,‘b’),(4,‘c’),(8,‘e’)]
存放变量名称与绑定关系的地方
名称空间有四种:LEGB(查找顺序)
locals:函数内部的名称空间,一般包含函数的局部变量和形式参数
enclosing function:在嵌套函数中外部函数的名称空间,若fun2嵌套在fun1里,对于fun2来说fun1的名称空间就是enclosing
globals:当前的模块空间,模块就是一些py文件。也就是说globals()类似全局变量
builtins:内置模块空间,也就是内置变量或者内置函数的名称空间,print(dir(builtins))可查看包含的值
不同变量的作用域不同就是由这个变量所在的名称空间决定的
def outer():
name='人生苦短,我学python'
def inner():
print("inner",name)
return inner #只做了返回函数名内存地址的动作
func=outer() # 返回了inner的内存地址
func() #相当于函数inner()
由于内层函数return出去了,并调用了函数外面变量的名称空间导致不能释放内存,叫做闭包
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹着一层作用域,这使得该函数无论在何处调用,优先使用自己外层包裹的作用域
软件开发中的一个原则——‘开放-封闭’。
高阶函数,闭包
a=[1,2,3,4,5,6,7,8,9] 实现列表里的元素加一
一般写法1:
for index,i in enumerate(a):
a[index]=+1
一般写法2:
a=list(map(lambda x:x+1,a))
高端写法:
a=[x+1 for x in range(10)] #生成式
边执行边运算,优化循环效率,如下:
>>>x * x for x in range(10)
at 0x0000019F57A43ED0>
生成算法,结果还未生成
>>>g = (x * x for x in range(10))
>>>next(g)
0
>>>next(g)
1
>>>next(g)
4
>>>next(g)
9
..........
..........
函数生成器
斐波拉契数列:除了第一个和第二个数外,任意一个数都可由前两个数相加得到
1,2,3,5,8,13,21,34…
实现100以内的斐波那契数代码:
def fibonacci(n):
a=0
b=1
count = 0
while count < n:
tmp = a # 存旧值
a=b
b=tmp+b
yield b # 暂停,返回b
count += 1
f=fibonacci(20)
print( next( f ) )
print( next( f ) )
print( next( f ) )
print( next( f ) )
print( next( f ) )
输出:
1
2
3
5
8
生成器实现并发编程
可以被直接内for循环的对象统称为可迭代对象(iterable):
一类是几何数据类型
另一类是generator,包括生成器和带yield的generator function
可以使用isinstance()判断是否是iterable对象:
>>>from collections import Iterable
>>>isinstance({},Iterable)
True
>>>isinstance(11,Iterable)
False
可以被next()函数调用并不断返回下一个值的对象称为迭代器(iterator)
>>>from collections import Iterator
>>>isinstance((x for x in range(10)),Iterator)
True
>>>isinstance({},Iterator)
False
>>>isinstance(iter({}),Iterator)
True
>>>isinstance('abc',Iterator)
False