函数
#函数可以被反复调用
def MAX(a,b):
'''输入两个数,输出其中的较大值'''
if a>b:
print(a,"max")
else:
print(b,"max")
MAX(10,30)
MAX(50,10)
help(MAX.__doc__)
#查询function的功能说明
'''
定义函数的格式为 def 函数名字(形参变量): 一定要注意符号,以及function的缩进
调用的时候,实参与形参一定要一一对应,type和数量要一致;实参调用,形参定义
'''
函数返回值
#函数中用return返回值,同时结束函数运行
def add(a,b):
'''计算两个数的和'''
return a+b
#函数的调用到return就停止了,后续的语句都不会被执行
c=add(30,40)
print(c)
def test(a,b,c):
return [a*10,b*10,c*10]
#返回值只能是一个对象,但是可以借用返回列表、元组等的形式将需要返回的数据存储起来
print(test(2,3,4))
#如果没有定义return返回值,默认返回None
全局变量、局部变量
a=100 #全局变量
def f1():
b=3
a=4 #局部变量
print(a+b)
f1()
print(a)
'''
7
100 局部变量再被使用完成后就会回收
'''
a=100 #全局变量
def f1():
b=3
global a
a=4 #局部变量
print(a+b)
f1()
print(a)
'''
7
4 global生命以后函数内部可以操作全局变量的值
'''
'''
fi在def时就将栈中的f1指向了堆中的function对象
每次运行f1会在栈中开辟一个栈帧,局部变量储存在里面指向堆中的对象
global声明后,栈帧中对a的操作都会使得原来的变量a进行改变
******局部变量的引用效率更高
'''
位置参数、默认参数、强制命名参数
def f1(a,b,c):
pass
f1(2,3,4)
#要一一对应,不能缺少
def f2(a,b,c=100):
pass
f2(1,2)
#默认值参数可以在没有主动赋值时有一个默认参数,默认参数必须在位置参数后
def f3(a,b,c):
pass
f3(c=1,b=3,a=3)
#强制命名参数
def f1(a,b,*c): #一个星号代表元组,会将所有参数传到元组中
print(a,b,c)
f1(1,2,3,4,5)
def f2(a,b,**c): #字典,但是不能传入集合
print(a,b,c)
f2(1,2,name="Jim",age="22")
#如果字典或者元组的参数在前,则必须使用强制命名
LEGB规则
a=100
def aa():
c=10
print(a)
def bb():
global a
nonlocal c #内部函数不像外部那样可以读取到全局变量,写的操作都需要声明
print(a)
print(c)
a=20
c=50
bb()
print(a)
print(c)
aa()
'''
当只需要调取外部数据时不需要定义,但是需要改变变量value时需要在内部函数声明,nonlocal是外部函数,global用于全局变量声明
没有声明时会一层层往外查找
'''
参数传递
'''
参数传递与全局、局部变量概念不同,是函数运行需要传入的实际参数
列表、字典、集合、自定义等可以修改的参数,在传递时不会增加新的对象
字符串、数字、元组、function不可以修改,传递时会创建出新的对象
'''
'''
只进行读操作,任何可变或不可变对象都可以进行
'''
a=[10,20,30]
def f1(m):
print(id(m))
m.append(40)
print(id(m))
f1(a)
print(a)
#传递可变对象的时候,写的操作会作用在原对象上
a=1000
def f2(m):
print(id(m)) #地址仍然是传递进来的a的地址
m=m+1000 #写操作
print(m)
print(id(m)) #id和value改变,新的一个对象
f2(a)
print(a) #原对象没有改变
#如果传递的是不可变对象且需要进行修改,需要在def中给出print或return
不可变对象中包含可变对象的参数传递
a=(10,20,30,[50,60])
print(id(a))
def test1(m):
print(id(m))
m[3][0]=70
print(id(m))
print(m)
test1(a)
print(a)
#元组本身的元素不可以改变,但是其中的可变子对象的内容可以改变,且不会影响id
'''
函数传递不可变对象时是采用浅拷贝
'''
嵌套函数
def print_name(ischinese,name,familyname): #隐藏内部函数,给出一个外部的封装,封装中定义和直接调用内部的函数
def inner_print(a,b): #公用一个函数用于内部调用
print("{0} {1}".format(a,b))
if ischinese:
inner_print(familyname,name)
else:
inner_print(name,familyname)
print_name(True,"junyang","chen")
'''
if判断语句的结果时True和False 所以调用赋值也是这两个,0、1也可以用
'''
递归函数
#递归的本质是自己调用自己;谨慎使用,因为会占据大量的内存
def test01(n):
print("a=",n)
if n==0:
print("over")
else:
test01(n-1)
print("b=",n)
test01(4)
'''
a= 4
a= 3
a= 2
a= 1
a= 0
over
b= 0
b= 1
b= 2
b= 3
b= 4 为什么会输出这个结果?是因为调用自己时会在栈里开辟一个新的栈帧,导致b语句还没有进行执行就先进行了后面的调用;
而执行完n=0时,没有新的栈帧再开辟所以会回过头来一个个消除掉栈帧,b语句由新到旧依次执行完毕
'''
lambda表达式声明匿名函数
f=lambda a,b,c:a+b+c #只能返回简单表达式的值
print(f(1,2,3))
#lambda表达式可以声明匿名函数 由元素:表达式组成 会直接返回表达式的计算值
g=[lambda a:a*2,lambda b:b*3,lambda c:c*4]
print(g[0](1),g[1](2),g[2](3))
#放在一个列表里面也可以分开调用;lambda只能包含一个简单的表达式
eval函数
#eval应该包含的是依据逻辑执行语句的字符串形式
c=dict(a=10,b=15)
print(eval("a+b",c)) #以c为取值范围
#可以指定eval的调用范围,范围只能是字典形式
n=input("please input:") #输入 (x,x) eval可以将该字符串转换为元组,可以用于储存坐标
print(eval(n))
'''
如果直接将字符串转为 list或者tuple只能将字符串元素进行储存
例如输入 200,300 list以后只能转化为 ['2', '0', '0', ',', '3', '0', '0']
'''