Part5:函数用法和底层分析
格式:
要点:
(1)Python执行def时,会创建一个函数对象,并绑定到函数名变量上。
(2)形式参数不需要声明类型,也不需要指定函数返回值类型
内存底层分析:
实际上,执行def 定义函数后,系统就创建了相应的函数对象。我们执行如下程序,然后进行解释:
def print_star(n):
'''根据传入的n,打印多个星号'''
print("*"*n)
print(print_star)
print(id(print_star))
c = print_star
c(3)
上面代码执行def 时,系统中会创建函数对象,并通过print_star 这个变量进行引用。
我们执行“c=print_star”后,显然将print_star 变量的值赋给了变量c。因此,执行c(3)和执行print_star(3)的效果是完全一致的。
参数的传递
函数的参数传递本质上就是:从实参到形参的赋值操作。Python 中“一切皆对象”,所有的赋值操作都是“引用的赋值”。
传递可变对象的引用:
传递参数是可变对象(例如:列表、字典、自定义的其他可变对象等),实际传递的还是对象的引用。在函数体中不创建新的对象拷贝,而是可以直接修改所传递的对象。
传递不可变对象的引用:
传递参数是不可变对象(例如:int、float、字符串、元组、布尔值),实际传递的还是对象的引用。在”赋值操作”时,由于不可变对象无法修改,系统会新创建一个对象。
a = 100
def f1(n):
print("n:",id(n)) #传递进来的是a 对象的地址
n = n+200 #由于a 是不可变对象,因此创建新的对象n
print("n:",id(n)) #n 已经变成了新的对象
print(n)
f1(a)
print("a:",id(a))
浅拷贝和深拷贝
浅拷贝:不拷贝子对象的内容,只是拷贝子对象的引用。
深拷贝:会连子对象的内存也全部拷贝一份,对子对象的修改不会影响源对象
#测试浅拷贝和深拷贝
import copy
def testCopy():
'''浅拷贝'''
a = [10,20,[5,6]]
b = copy.copy(a)
print("a:",a)
print("b:",b)
b.append(30)
b[2].append(7)
print("浅拷贝。。。。")
print("a:",a)
print("b:",b)
def testDeepCopy():
'''深拷贝'''
a = [10,20,[5,6]]
b = copy.deepcopy(a)
print("a:",a)
print("b:",b)
b.append(30)
b[2].append(30)
print("深拷贝。。。。")
print("a",a)
print("b:",b)
testCopy()
print("*********************")
testDeepCopy()
浅拷贝:
深拷贝
可变参数
可变参数指的是“可变数量的参数”。分两种情况:
1. *param(一个星号),将多个参数收集到一个“元组”对象中。
2. **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,name="kiki",age=20)
def f3(a,b,*c,**d):
print(a,b,c,d)
f3(8,9,20,30,name='kiki',age=19)
lambda表达式和匿名函数
lambda 函数是一种简单的、在同一行中定义函数的方法。lambda 函数实际生成了一个函数对象。
lambda 表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是函数的返回值。
f = lambda a,b,c:a+b+c
print(f)
print(f(2,3,4))
g = [lambda a:a*2,lambda b:b*3,lambda c:c*4]
print(g[0](6),g[1](7),g[2](8))
eval()函数
功能:将字符串str 当成有效的表达式来求值并返回计算结果。
s = "print('abc')"
eval(s)
a = 10
b = 20
c = eval("a+b")
print(c)
dict1 = dict(a = 100,b = 200)
d = eval("a+b",dict1)
print(d)
嵌套函数
def printName(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)
printName(True,"A","a")
printName(False,"A","a")