067.函数的基本概念_内存分析_函数的分类_定义和调用
a.内置函数,标准库函数,第三方函数,用户自定义函数;
b.函数的定义和调用:
def 函数名([参数列表]):
函数体/若干语句
def fun(): print("***") print("aaa") fun()要点:写法的细节;参数列表;return 返回值;使用函数前得先定义函数(与C中类似)
068.形参和实参_文档字符串_函数注释
a.形参和实参:
def fun(a,b): m=a+b print(m) fun(2,3) fun(4,5) def fun1(a,b): return a+b m1=fun1(1,2) print(m1)
b.文档字符串: 注释;
def fun(a,b): '''lalallalal''' m=a+b print(m) fun(2,3) fun(4,5) help(fun.__doc__)069.返回值详解
a.要点:如果函数体中包含return 语句,则结束函数执行并返回;如果函数体中不包含return语句,则返回None值;要返回多个返回值,使用列表、元组、字典、集合将多个值“存起来”即可。
def add(a,b): print("计算两个数的和") return a+b print(3)#return已经结束语句 这句话不会被打印出来 c=add(1,2) print(c*20) def dd(): print(c) m=dd() print(m) #返回空 #返回多个返回值 def vv(a,b,c): return (a*2,b*3,c*4) last=vv(1,2,3) print(last) #<注>与下面的子函数进行对比,发现,return返回用括号则返回元组,如果是[]则为列表 def vv(a,b,c): return [a*2,b*3,c*4] last=vv(1,2,3) print(last) def vv(a,b,c): return {a*2,b*3,c*4} last=vv(1,2,3) print(last)070.函数也是对象_内存分析
#测试函数也是对象 def test01(): print("lall") test01() #在python里,小括号是调用的意思 c=test01 #tset01的值赋给c,c调用的和test01一样 c() print(id(test01)) print(id(c))071.变量的作用域_全局变量_局部变量_栈帧内存分析讲解
a.全局变量和局部变量的作用域和C里一样
b.全局变量:降低了函数的通用性和可读性,应尽量避免全局变量的使用
全局变量一般做常量使用‘
<新知识>函数内要改变全局变量,使用globa声明
c.局部变量:局部变量的引用比全局变量快,优先考虑使用
如果局部变量和全局变量同名,则在函数内隐藏全局变量,只使用局部变量
自我小结:在函数里面如果使用同名的全局变量,在函数体里优先输出局部变量,在一个新的函数里再次调用,但是新函数里面没有与全局变量同名,并改变其值,输出仍为全局变量。如果想在函数内改变全局变量,需用global,如果第一个子函数改变了全局变量的值,第二个子函数输出的全局变量值为新值
i=3 def f(): m=3 # global i # print(i) print(m) i = 200 print(i) f() print(locals())#打印输出局部变量 print(globals())#打印输出全局变量 def g(): #global i print(i) #print(m) #m为局部变量 g()072.局部变量和全局变量_效率测试
import math import time def test01(): start = time.time() for i in range(1,100000): math.sqrt(30) end = time.time() print("耗时:{0}".format((end-start))) def test02(): start = time.time() b=math.sqrt for i in range(1, 100000): b(30) end = time.time() print("耗时:{0}".format((end - start))) test01() test02()073.参数的传递_传递可变对象_内存分析
a.python中参数 的传递都是“引用传递”,不是“值传递”
b.可变对象:字典、列表、集合、自定义对象等
b=[10,20] print(id(b)) def te(m): print("m",id(m)) m.append(30) print("m",id(m)) te(b) print(b)
c.数字(int、 floa)、字符串、元组、function等
074.参数的传递_传递不可变对象_内存分析
传递参数是不可变对象时,实际传递的还是对象的引用,在“赋值操作”时,由于不可变对象无法修改,系统会创建一个新的对象
a=100 print("a",id(a)) def t(n): print("n",id(n)) n=n+200#因为不可变对象不可修改,所以创建了一个新的对象 print("n",id(n)) print(n) t(a) print("a",id(a))075.浅拷贝和深拷贝_内存分析
a.使用内置函数:copy(浅拷贝),deepcopy(深拷贝)
b.浅拷贝:不拷贝子对象的内容,只拷贝子对象的引用
深拷贝:会连子对象的内存也全部拷贝一份,对子对象的修改不会影响源拷贝
import copy def t1(): print("拷贝前:") 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 t2(): print("拷贝前:") a = [10, 20, [5, 6]] b = copy.deepcopy(a) print("a:", a) print("b:", b) b.append(30) b[2].append(7) print("深拷贝:") print("a:", a) print("b:", b) t1() print("----------------------") t2()
076.参数的传递_不可变对象含可变子对象_内存分析
《注》:传递不可变对象时,如果是发生拷贝,用的是浅拷贝
a=10 print("a",id(a)) def test01(m): print("m:",id(m)) m=20 print(m) print("m:", id(m)) test01(a) print("----------------- \n") #列表可变 b=[10,20,[5,6]] print("b:",id(b)) def test02(m): print("m:", id(m)) m[2] = 222 print(m) print("m:", id(m)) test02(b) #元组不可变 下面程序将会报错 v=(10,20,[5,6]) print("v:",id(v)) def test03(m): print("m:", id(m)) #m[2] = 222 此句不可执行 m[2].append(888) print("m:",m) m[2][0]=2 print("m:", m) print("m:", id(m)) test03(v) print("v:",v)077.参数的类型_位置参数_默认值参数_命名参数
a.位置参数:需要个数和形参匹配
b.默认值参数:在定义形参的时候,直接给形参值;并且默认值参数要放在位置参数的后面;如果传到默认值参数,则改变默认值参数的值
c.命名参数:可以按照形参的名称传递参数
def f(a,b,c=1): print(a+b+c) f(1,2) f(1,4,5) def g(a,b,c): print(a+c) g(a=2,b=1,c=7)
078.参数的类型_可变参数_强制命名参数
a.可变参数:*param(一个星号),将多个参数收集到一个“元组”对象中
**param(两个星号),将多个参数收集到一个“字典”对象中
def f1(a,b,*c): print(a,b,c) f1(1,2,3,4) def f2(a,b,**c): print(a,b,c) f2(1,2,name="lal",age=13) def f3(a,b,*c,**d): print(a,b,c,d) f3(1,2,5,66,name="rr",age="17")b.强制命名参数:在带星号的“可变参数”后面增加新的参数,必须是“强制命名参数”
def f1(*a,b,c): print(a,b,c) f1(1,2,b=2,c=3)079.lambda表达式和匿名函数
a.lambda表达式用来声明匿名函数;只允许包含一个表达式;该表达式的计算结果就是函数的返回值
f=lambda a,b,c:a+b+c print(f) print(f(2,3,4)) g=[lambda a,d:a*2+d,lambda b:b*3,lambda c:c*4] print(g[0](6,1),g[1](7),g[2](8))080.eval()函数用法
功能:将字符串str当成有效的表达式求值并返回计算结果
s="print('abdg')" eval(s) a=10 b=20 c=eval("a+b") print(c) dict1=dict(a=100,b=200) d=eval("a+b") print(d) d=eval("a+b",dict1) print(d)081.递归函数_函数调用内存分析_栈帧的创建
a.终结条件;递归步骤
def f1(n): print(n) if(n==0): print("over") else: f1(n-1) print("##",n) def f2(): print("2") f1(4)082.递归函数_阶乘计算案例
def f1(n): if(n==1): return 1 else: return n*f1(n-1) print(f1(5))#可以通过递归做分析几何,
083.嵌套函数_内部函数_数据隐藏
嵌套函数:将细节隐藏,分装、隐藏、降低重复代码、闭包
def f1(): print(1) def f2(): print(2) f2() f1()084.nonlocal_global
nonlocal:用来声明外层的局部变量
def f1(): i=2 print(i) def f2(): nonlocal i i=5 print(i) f2() f1()085.LEGB规则
查找规则:local(函数或者类的方法内部)->enclosed(嵌套函数)->global(模块中的全局变量)->built in(Python为自己保留的特殊名称)
如果在所有命名空间都没有找到则返回NameError()
str ="global" def f1(): #str="outer" def f2(): # str="inner" print(str) f2() f1()
