函数用法
函数的参数类型
不可变类型参数:数值型、字符串str、元组tuple。
可变类型:列表list,字典dict
函数中a不可变,fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
1、传递不可变类型参数,不会影响参数本身
2、传递可变类型参数,会影响参数本身
# 不可变参数类型
a =1
print(id(a))
# 2009628784
def func(a):
a= 10
print(a,id(a))
func(a)
# 20 2009629392
def func(a):
a= 1
print(a,id(a))
func(a)
# 1 2009628784
print(a,id(a))
# 1 2009628784
# 可变参数类型
b=[10,20]
print(id(b))
#2324968580360
def func(b):
b.append(30)
print(id(b))
func(b)
#2324968580360
print(b,id(b))
# [10, 20, 30] 2324968580360
函数参数(必选参数、默认参数,可选参数、关键字参数)
# 必选参数
def func1(x):
return x*x
func1(2)
#4
#默认参数,
#注意:默认参数必须放到必选参数之后
#缺陷:
def funcx(L=[]):
L.append("The End"
return L
funcx()
# 在函数定义时,默认参数L所制定的地址已经确定。每次调用都会改变L的内容
def func2(x,y=10):
return x*y
func2(3)
# 30
func2(3,5)
# 15
可选参数
def func3(*nmbers):
sum = 0
for i in numbers:
sum = sum+i*i
return sum
func3([1,2,3])
# 14
关键字参数
def func4(name,**kwargs):
print("data:",kwargs)
递归函数
递归函数 如果一个函数在内部调用自身本身,这个函数就是递归函数。
使用递归函数的条件:
1. 必须留出口
2. 自己调用自己
case1:
# 使用递归函数求 1*2*3....*7*8*9*10
def func(x):
if x==1:
return x
return x*func(x-1)
print(func(10))
#3628800
case2:
# 将列表全部展开
lst1 = [1,2,[3,4,[5,[6,[7],8,9]],10],11,12,13]
lst2 =[]
def func(lst1):
for i in lst1:
if isinstance(i,list): # 如果是列表就执行func(i)
func(i)
else:
lst2.append(i) # 如果不是就把元素放到lst2列表中
func(lst1)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,13]
case3:
# 使用递归函数求斐波拉契数列
#1 1
#2 2
#3 2+1=3
#4 3+2 = 5
#...
#n f(n-1)+f(n-2)
def func(n):
if n==1 or n==2:
return n
return func(n-1)+func(n-2)
print(func(5))
# 8
case3:
青蛙一次能跳1个或3个或7个或10个台阶,问:有n个台阶,青蛙跳上去有几种跳法?
1-2 1 n<=2 f(n)=1
3 2 f(2)+f(0)=2
4 2+1=3 f(3)+f(1)=4
5 3+1=4
6 4+2=6
...
n f(n-1)+f(n-3)+f(n-7)+f(n-10)
def func(x):
if 1<=x<3:
return 1
elif x<0:
return 0
else:
return func(x-1)+func(x-3)+func(x-7)+func(x-10)
print(func(10))
#22
函数的命名空间
命名空间一共分为三种:局部命名空间、全局命名空间、内置命名空间
局部命名空间:每个函数都有自己的命名空间,叫做局部空间,它记录了函数的变量,包括函数的参数和局部定义的变量
def test():
a =2
print(a)
test()
print(a)
#2
#NameError: name 'a' is not defined
全局命名空间:每个模块拥有它自已的命名空间,叫做全局命名空间,它记录了模块的变量,包 括函数、类、其它导入的模块。
a=2
def test():
print(a)
test()
print(a)
#2
#2
内置命名空间:任何模块均可访问它,它存放着内置的函数和异常。
print(),input()...
局部变量和全局变量
局部变量:定义在函数内部的变量
全局变量:定义在函数外部的变量,如果是不可变类型,则在函数内部不可以被修改
name='zzq'
list1=[10]
def func():
name='johnson'
list1.append(name)
print("inner",name)
func()
print("outer",name)
print(list1)
#inner johnson
# outer zzq
name ='zzq'
name ='johnson'
def func():
global name #全局变量
name='123'
func()
print(name)
# 123
name = 'zzq'
def func1():
name='ls'
def func2():
nonlocal name # 在函数本地作用域找不到变量的情况下,解释器会自动在外层函数寻找
name='abc'
func2()
print("---------",name)
func1()
print(name)
#---- bac
# zzq
- 函数定义了本地作用域,而模块定义的是全局作用域。
如果想要在函数内定义全局作用域,需要加上global修饰符。- 变量名解析:LEGB原则
当在函数中使用未认证的变量名时,Python搜索4个作用域[本地作用域(L)(函数内部声明但没有使用global的变量),之后是上一层结构中def或者lambda的本地作用域(E),之后是全局作用域(G)(函数中使用global声明的变量或在模块层声明的变量),最后是内置作用域(B)(即python的内置类和函数等)]并且在第一处能够找到这个变量名的地方停下来。如果变量名在整个的搜索过程中
都没有找到,Python就会报错。