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()