函数也是对象
def fun():
print('a')
c = fun
c()
print(id(fun))
print(id(c))
显然,我们可以看出变量 c 和funr 都是指向了同一个函数对象。因此,执行 c()和执
行 fun()的效果是完全一致的。 Python 中,圆括号意味着调用函数。在没有圆括 号的情况下,Python 会把函数当做普通对象。
全局变量和局部变量
a = 100
def ab1():
a = 200
def ab2():
global a
a = 200
ab1()
print(a)
ab2()
print(a)
ab1()函数的a是局部变量,虽然与全局变量重名,但优先使用局部变量,该变量在函数调用完之后就消失了。ab2()函数的a是全局变量,直接改变了全局变量的值,函数调用完这个改变也不会消失。
局部变量效率更高
import time
import math
def test01():
start = time.time()
for i in range(1000000):
math.sqrt(i)#math.sqrt是全局的
end = time.time()
print(end-start)
def test02():
b = math.sqrt#math.sqrt是全局的,这里把它变为局部
start = time.time()
for i in range(1000000):
b(i)
end = time.time()
print(end-start)
test01()
test02()
0.1147310733795166
0.08174300193786621
test01()用全局变量,test02()将全局变量变为局部变量,而是执行效率有区别。局部效率更高。
参数传递
函数的参数传递本质上就是:从实参到形参的赋值操作。 Python 中“一切皆对象”, 所有的赋值操作都是“引用的赋值”。所以,Python 中参数的传递都是“引用传递”,不 是“值传递”。具体操作时分为两类:
1. 对“可变对象”进行“写操作”,直接作用于原对象本身。
2. 对“不可变对象”进行“写操作”,会产生一个新的“对象空间”,并用新的值填 充这块空间。(起到其他语言的“值传递”效果,但不是“值传递”)
可变对象有:
字典、列表、集合、自定义的对象等
不可变对象有:
数字、字符串、元组、function 等
#传递可变对象,列表是一个可变对象,当做实参传入,此时实参和形参指向同一个地址,操作的是同一个对象,改变形参指向的对象就会同时改变实参指向的对象
a = [10,20]
print(id(a))
def test01(m):
print(id(m))
print(m)
m.append(30)
print(id(m))
print(m)
test01(a)
print(a)
浅拷贝与深拷贝
import copy
def testcopy():
print('****浅拷贝****')
a = [10, 20, [5, 6]]
b = copy.copy(a)
print(a)
print(b)
b.append(30)
b[2].append(7)
print(a)
print(b)
def testDeepCopy():
print('****深拷贝****')
a = [10, 20, [5, 6]]
b = copy.deepcopy(a)
print(a)
print(b)
b.append(30)
b[2].append(7)
print(a)
print(b)
testcopy()
testDeepCopy()
****浅拷贝****
[10, 20, [5, 6]]
[10, 20, [5, 6]]
[10, 20, [5, 6, 7]]
[10, 20, [5, 6, 7], 30]
****深拷贝****
[10, 20, [5, 6]]
[10, 20, [5, 6]]
[10, 20, [5, 6]]
[10, 20, [5, 6, 7], 30]
浅拷贝的内存原理图
浅拷贝工作原理图
进行同样幅值操作的深拷贝的工作原理图
函数参数类型
def f1(a,b,c):
print('{0}-{1}-{2}'.format(a,b,c))
f1(1,2,3)#位置参数
def f2(a,b,c=10):
print('{0}-{1}-{2}'.format(a,b,c))
f2(1,2)#默认参数,要放在最后面
def f3(a,b,c):
print('{0}-{1}-{2}'.format(a,b,c))
f3(c = 30,b = 20,a = 10)#命名参数
可变参数
def f1(a,b,*c):#*c是变参数,把多于的参数放入一个元组,
print(a,b,c)
f1(1,2,3,4)
def f1(a,b,**c):#*c是变参数,把多于的参数放入一个字典
print(a,b,c)
f1(1,2,name=1,age=1)
def f1(*a,b,c):#*c是变参数,把多于的参数放入一个元组,
print(a,b,c)
f1(3,b=1,c=2)
lambda表达式
lambda 表达式可以用来声明匿名函数。lambda 函数是一种简单的、在同一行中定义函数
的方法。lambda 函数实际生成了一个函数对象。
lambda 表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是函数
的返回值。
#lambda表达式lambda 形参,形参 :表达式
f = lambda a,b,c: a+b+c
print(f(2,3,4))
g = [lambda a:a*2,lambda b:b*3,lambda c:c*4]
print(g[0](2),g[1](3),g[2](4))
eval()函数
# eval 函数,执行代码,计算表达式
eval("print('abcde')")
a = 10
b = 20
c =eval('a+b')#可以是a*b,因此很灵活
dict1 = dict(a=100,b=200)
d = eval('a+b',dict1)#取字典的a和b
print(d)
递归函数
# 递归函数自己调用自己
def test01(n):
print('test01',n)
if n == 0:
print('over')
else:
test01(n-1)
print('test01*',n)
# 体现了栈道工作原理,后进先出
运行结果为
test01 4
test01 3
test01 2
test01 1
test01 0
over
test01* 0
test01* 1
test01* 2
test01* 3
test01* 4
其工作原理如图
阶乘递归函数
def fac(n):
s = 1
if n == 1:
return 1
else:
return n*fac(n-1)
print(fac(10))