语法: def 函数名(参数列表):
‘’‘文档字符串’’’
函数体/若干语句
要点
def 后面跟着的那个叫形式参数,调用函数给具体的值就是实际参数。
def printMax(a,b):
'用于比较两个数的大小'
if a>b:
print(a,'大')
else:
print(b,'小')
printMax(10,20)
help(printMax.__doc__)
###运行结果###
20 小
No Python documentation found for '用于比较两个数的大小'.
Use help() to get the interactive help utility.
Use help(str) for help on the str class.
其中,a和b都叫做形式参数,10,20叫做实际参数,help可以调用函数定义里面的文字部分,所以函数里面要多说明一下
return的两个作业:结束运行或者返回值
def test03(a,b):
"测试返回值的基本用法"
print('计算的{0}和{1}的和:{2}'.format(a,b,a+b))
return a+b
test03(10,20)
def test04():
print('dada')
return
print('hello')
test04()
###运行结果###
计算的10和20的和:30
dada
看第二个部分,return用于结束,后面的部分不会再运行
函数作为一个对象,可以作为参数来传递,也可以作为对象的值来传递。
def test01():
print('ads')
c = test01
c()
print(id(c))
print(id(test01))
c 和 test01的id是一样的。
变量分为全局变量和局部变量:
全局变量:作用域为定义的模块,从定义位置开始直到模块结束。
tips: 尽量避免全局变量的使用,全局变量一般作为常量使用,要改变全局变量应该用global声明一下。
局部变量:在函数体内部声明的变量,全局变量和局部变量有冲突的时候,隐藏全局变量,使用局部变量。
a = 3 # 全局变量:整个文件都可以使用
#局部变量
def test01(b):
b = 4
print(b * 10)
print(a)
#b是不存在的,只在函数内部存在的,在外部读取则不存在
print(b)
### 运行结果 ###
3
Traceback (most recent call last):
File "D:/PycharmProjects/MyTest/Day_5/function.py", line 48, in <module>
print(b)
NameError: name 'b' is not defined
运行机制:
当要调动test01的时候,会出现一个栈帧(b),也是一个对象,但是调用完test01,栈帧就没有了
a = 3 # 全局变量
def test01():
b = 4
print(b * 10)
a = 300
print(a)
# 使用a的时候,隐藏了全局变量,使用了局部变量,若不想改变,应该加global a
test01()
# 仍然打印的是全局变量a
print(a)
####运行结果####
40
300
3
a = 100
def f1(a, b, c):
print(a, b, c)
print(locals()) # 打印输出局部变量
print("#" * 20)
print(globals()) # 打印输出全局变量
f1(2,3,4)
####运行结果####
2 3 4
{'c': 4, 'b': 3, 'a': 2}
####################
{'__name__': '__main__', '__doc__': '\n@author: Di
所以在有全局变量的时候速度要慢的多,在有大量代码的时候,才考虑这种,否则会降低代码的可读性
# 使用全局变量 math.sqrt 和 不适用全局变量 math.sqrt的时间
import time
import math
def test01():
start = time.time()
for i in range(100000):
math.sqrt(30)
end = time.time()
print('有全局变量耗时:{0}'.format((end - start)))
def test02():
# 记得把函数赋给某一个变量的时候,不要加括号!
b = math.sqrt
start = time.time()
for i in range(100000):
b(30)
end = time.time()
print('没有全局变量耗时:{0}'.format((end - start)))
test01()
test02()
####运行结果####
有全局变量耗时:0.011970281600952148
没有全局变量耗时:0.008986711502075195
函数参数传递的本质上就是:从形参到实参的赋值操作。
可变对象:字典,列表,集合,自定义可变对象
不可变对象:数字,字符串,元组,function
参数传递的实质:对于可变对象来说,不生成新的对象,直接在原来的值上进行修改。
b = [10, 20]
print(id(b))
def f2(m):
print('m', id(m))
m.append(30)
f2(b)
print(b)
###运行结果###
2482609933832
m 2482609933832
[10, 20, 30]
传递不可变对象:生成一个新的对象对其进行修改
# 传递不可变对象:生成一个新的对象对其进行修改
a = 100
print(id(a))
def f01(m):
m *= 20
print("m", m, id(m))
f01(a)
print(a, id(a))
运行结果
1347319968
m 2000 2012825890512
100 1347319968
浅拷贝(copy):不拷贝子对象的内容,只是拷贝子对象的引用
深拷贝(deepcopy):会连子对象的内存全部拷贝一份,对子对象的修改不会影响源对象
浅拷贝
# 浅拷贝和深拷贝
import copy
a = [10, 20, [4, 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)
###运行结果###
a: [10, 20, [4, 5, 6]]
b: [10, 20, [4, 5, 6]]
浅拷贝.......
a: [10, 20, [4, 5, 6, 7]]
b: [10, 20, [4, 5, 6, 7], 30]
运行机制讲解
浅拷贝的话只拷贝“父系”:也就是蓝色部分,所以在b的尾巴后面增加了30,a就不会有。但是如果要增加b没有拷贝的部分,也就是“子系”,就相当于对a进行修改。
深拷贝
import copy
a = [10, 20, [4, 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)
####运行结果####
a: [10, 20, [4, 5, 6]]
b: [10, 20, [4, 5, 6]]
深拷贝.......
a: [10, 20, [4, 5, 6]]
b: [10, 20, [4, 5, 6, 7], 30]
运行机制讲解
对b进行的操作,b的元素全都有,所以就不对a进行修改了。
传递不可变对象时候,如果发生拷贝,是浅拷贝。也就是说一旦对下面的a里面的嵌套里的嵌套进行修改,那么a也会发生相应改变。
对于不可变对象来说,没有嵌套里面的嵌套,那么就相当于重新生成一个新的对象。
a = (10, 20, [5, 6])
print('a:', id(a))
def test01(m):
print('m:', id(m))
m[2][0] = 888
print(m)
print('m:', id(m))
test01(a)
print(a)
####运行结果####
a: 2180368644280
m: 2180368644280
(10, 20, [888, 6])
m: 2180368644280
(10, 20, [888, 6])
通过位置顺序传递,形参和实参一一对应的关系。
我们可以为某些参数设置默认值,这样这些参数在传递的时候就是可选的。
!!默认参数必须位于普通参数后面!!
def f1(a, b, c=10, d=20):
print(a, b, c, d)
f1(29, 34)
f1(80, 0, 102, 3)
####运行结果####
29 34 10 20
80 0 102 3
def f1(a, b, c=10, d=20):
print(a, b, c, d)
f1(c=10, d=30, a=1, b=3)
###运行结果###
1 3 10 30
可变参数指的是数量可变。
def f1(a, b, *c):
print(a, b, c)
f1(10, 20, 30, 40)
def f2(a, b, **c):
print(a, b, c)
f2(8, 9, name='Di', age=18)
####运行结果####
10 20 (30, 40)
8 9 {'name': 'Di', 'age': 18}
# 用lambda创建一个函数
f = lambda a, b, c: a + b + c
# 用普通方式创建一个函数
def test01(a, b, c):
print("*****")
return a + b + c
print(f(1, 2, 3))
# 用列表创建函数
g = [lambda a: a * 2, lambda b: b * 3, lambda c: c * 4]
print(g[0](6), g[1](5), g[2](4))
# 用列表创建函数
g1 = [test01, test01]
print(g1[0](3, 4, 5))
####运行结果####
6
12 15 16
*****
12
语法:eval(source[,globals[,locals]])
source : 一个python 表达式或函数compile()返回的代码对象
globals: 可选,必须是dictionary
locals : 可选。任意映射对象
# 测试eval()函数
# 执行代码:eval(''),eval里面加的是字符串
eval("print('afwfww')") # 注意内部和外部的引号不能一样
a = 10
b = 20
print(eval('a+b'))
dic1 = dict(a=100, b=101)
d = eval('a+b', dic1)
print(d)
###运行结果###
afwfww
30
201
递归函数指的是自己调用自己的函数,在函数体内部直接或间接地调用自己。递归类似于大家中学数学学习过的"数学归纳法",每个递归函数必须包含两个部分:
# 测试递归函数的基本原理
def test01():
print('test01')
test01()
def test02():
print('test02')
test01()
# 测试递归函数的基本原理
def test01(n):
print('test01')
if n == 0:
print('over')
else:
test01(n - 1)
print("******************")
test01(6)
运行结果
test01
test01
test01
test01
test01
test01
test01
over
******************
******************
******************
******************
******************
******************
******************
原理说明
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n - 1)
print(factorial(6))
# 嵌套函数使用方法:打印名字
# 第一个参数传入任意非空就表示是“中国人”
def printName(isChinese, Name, FamilyName):
def innerfunction(a, b):
print('{0},{1}'.format(a, b))
if isChinese:
innerfunction(FamilyName, Name)
else:
innerfunction(Name, FamilyName)
printName('ad', 'Di', 'Huang')
```**运行结果**
```python
Huang,Di
外部函数有一个变量,内部函数使用外部的变量,就使用nonlocal,跟global有一点像。
def outer():
b = 10
def inner():
nonlocal b
print("inner:", b)
b = 20
inner()
print("outer:",b)
outer()
运行结果
inner: 10
outer: 20
按照下列规则进行查找的:Local→ Enclosed → Global → Built in
Local :代表内部函数
Enclosed:代表外部函数
Global : 代表全局变量
Built in:代表Python 为自己保留的特殊名称(python内部有这个变量)
如果都没有找到这些变量,那么就会报错:Name Error
# 测试LEGB
# str = 'global str'
def outer():
# str = 'outer'
def inner():
# str = 'inner'
print(str)
inner()
outer()
运行结果
<class 'str'>
上述结果是最后在built in 里面找到了,也就是python本身就有这个变量