函数也是对象
函数内部如果想改变全局变量的值,使用global声明
若想在函数内部使用全局变量a,需要声明:global a
如果想输出局部变量和全局变量,需要使用local和globals:
参数的传递
本质上是赋值的操作。就是实参到形参的赋值操作
传递可变对象
传递不可变对象(int,float,元组,字符串,布尔值)。在赋值操作的时候,系统会创建一个新的对象
a = 100
def f1(n):
print(“n:”,id(n))
n = n+200
print(“n:”,id(n))
print(n)
f1(a)
print(“a:”,id(a))
执行结果:
n:1663816464
n:46608592
300
a:1663816464
浅拷贝和深拷贝:
浅拷贝:不拷贝子对象的内容,只是拷贝子对象的引用
深拷贝:会连子对象的内存也全部拷贝一份,对子对象的修改不会影响源对象
import copy
a = [10,20,[5,6]]
b = copy.copy(a)
print(“a:”,a)
print(“b:”,b)
b.append(300)
b[2].append(7)
print("a:"a)
print("b:"b)
a : [10,20,[5,6]]
b : [10,20,[5,6]]
a : [10,20,[5,6,7]]
b : [10,20,[5,6,7],30]
深拷贝
def testDeepCopy()
import copy
a = [10,20,[5,6]]
b = copy.deepcopy(a)
print(“a:”,a)
print(“b:”,b)
b.append(300)
b[2].append(7)
print("a:"a)
print("b:"b)
testDeepCopy()
b做任何修改,和a没有任何关系
传递不可变对象是浅拷贝
a =(10,20,[5,6])
print(“a:”,id(a))
def test(m):
print(“m”,id(m))
m[2][0] = 888
print(m)
print(“m”,id(m))
test(a)
tuple类型不可变,说的是他里面的地址不可变。
如果tuple类型中有可变类型,比如列表。那么只要列表地址不变,就可以更改
a :41611632
m:41611632
(10,20,[888,6])
m:41611632
(10,20,[888,6])
参数的几种类型
位置参数:
def f1(a,b,c):
print(a,b,c)
f1(2,3,4)
f1(2,3) #报错
默认值参数
def f1(a,b,c = 10,d = 20):
print(a,b,c,d)
f1(8,9)
f1(8,9,19)
f1(8,9,19,29)
8 9 10 20
8 9 19 20
8 9 19 29
命名参数
def f1(a,b,c):
print(a,b,c)
f1(8,9,19)
f1(c = 8,a = 20,b = 33)
8,9,19
20,33,8
可变参数:
指的是可变数量的参数
*param。将多个参数收集到一个元组里
**param。将多个参数收集到一个字典里
def f1(a,b,*c):
print(a,b,c)
f1(8,9,19,20)
def f2(a,b,**c)
print(a,b,c)
f2(8,9,nane = “zhangsan”,age = 18)
def f3(a,b,*c,**d)
print(a,b,c,d)
f3(8,9,20,30,name = “zhangsan”,age = 18 )
8 9 (19,20)
8 9 {nane = “zhangsan”,age = 18)}
8 9 (20,30){nane = “zhangsan”,age = 18)}
强制命名参数
def f1(*a,b,c)
print(a,b,c)
#f1(2,3,4) #会报错,a是可变参数,会将2,3,4全部收集
f1(2,b = 3,c = 4) #必须在调用的时候,强制命名参数
lambda表达式和匿名函数
lambda表达式可以用来声明匿名函数。简单,在同一行中定义函数。lambda实际生成了一个函数对象
lambda表达式只允许包含一个表达式,不能包含复杂语句,计算结果就是函数的返回值
基本语法:
lambda arg1.arg2,arg3…:<表达式>
arg为函数的参数,<表达式>相当于函数的函数体。结果是:表达式的运算结果
f = lambda a,b,c:a+b+c
print(f)
print(f(2,3,4))
g = [lambda a:a2,lambda b:b3,lambda c:c*4]
print(g0,g1,g2)
9
12 21 32
eval()函数
将字符串
s = “ptiny(“hello”)”
eval(s)
a = 10
b = 20
c = eval(“a+b”)
print©
输出结果为
hello
30
dict1 = dict(a = 100,b = 200)
d = eval(“a+b”)
print(d)
30
dict1 = dict(a = 100,b = 200)
d = eval(“a+b”,dict1)
print(d)
递归函数:
白话讲就是自己调用自己的函数
def test01():
print(“test01”)
test02() #栈帧,当方法执行结束的时候,就会栈帧就会消失,释放内存。
def test02():
print(“test02”)
test01()
输出:
test01
test02
def test01():
print(“test01”)
test01()
print("###") #我们会发现,不会输出###,因为每个方法都没有执行完,一直在打开新方法,方法没有结束,就不会释放内存,导致栈满报错
def test02():
print(“test02”)
test01()
会报错,无限制的调用test01()并且输出。
栈满了就会报错
所以在递归中,要设置一个终止条件,并且把第n步和第n-1步关联
def test01():
print(“test01:”,n)
if n == 0:
print(“over”)
else:
test01(n-1)
print(“test01***”,n) # 把上面的代码执行完了,内存释放之前执行的最后一段代码
test01(4)
练习:递归的阶乘:
def factorial(n):
if n == 1:
return 1
else:
return n*factorial(n-1)