You are on page 1of 53

函数

def fun():
x=3 def fun(x):
return x + x x=6
return x + x def fun():
x=5 return x + x
print(fun()) x=5
print(x) print(fun(x)) x=5
print(x)
print(fun())
print(x)
本章节目标

掌握变量的作用域应用

掌握匿名函数应用方法

了解递归函数应用方法
1 变量的作用域

2 匿名函数

3 递归函数

课程目录 4 闭包
Course catalogue
变量的作用域是指变量的作用范围,即定义一个变量
后,在哪些地方可以使用这个变量。按照作用域的不同,

Python中的变量可分为局部变量和全局变量。
在一个函数中定义的变量就是局部变量(包括形参),其作用域
是从定义局部变量的位置至函数结束位置

def LocalVar1(x): #定义函数LocalVar1,形参x是局部变量


print('LocalVar1中x的值为:',x)
x=100 #将x的值修改为100
print('LocalVar1中x修改后的值为:',x)
y=20 #定义局部变量y,将其赋值为20
print('LocalVar1中y的值为:',y)
def LocalVar2(): #定义函数LocalVar2
x=10 #定义局部变量x,将其赋值为10
print('LocalVar2中调用LocalVar1前x的值为:',x)
LocalVar1(15) #调用LocalVar1函数
print('LocalVar2中调用LocalVar1后x的值为:',x)
def LocalVar1(x):
调用LocalVar2()
print('LocalVar1中x的值为:',x)
程序输出结果:
x=100 #将x的值修改为100 LocalVar2中调用LocalVar1前x的值为: 10
print('LocalVar1中x修改后的值为:',x) LocalVar1中x的值为: 15
LocalVar1中x修改后的值为: 100
y=20 #定义局部变量y,将其赋值为20 LocalVar1中y的值为: 20
LocalVar2中调用LocalVar1后x的值为: 10
print('LocalVar1中y的值为:',y)
在不同的函数中可以定义相同名字的变量,二者
不会冲突,虽然同名但代表不同的变量,所以可以存
储不同的数据。
def GlobalVar1():
在所有函数外 print('GlobalVar1中x的值为:',x)
定义的变量就是 def GlobalVar2():
全局变量,在其 x=100 #将x赋为100
print('GlobalVar2中x的值为:',x)
定义之后的函数
中都可以使用。 x=20 #定义在所有函数之外x是全局变量
GlobalVar1() #输出x为20
GlobalVar2() #输出x为100
GlobalVar1() #输出x为20
在一个函数中使用global关键字,可以声
明在该函数中使用的是全局变量,而非局部变量。
def GlobalVar1(): #定义函数GlobalVar1
print('GlobalVar1中x的值为:',x) #输出全局变量x
def GlobalVar2(): #定义函数GlobalVar2
global x #通过global声明在函数中使用的是全局变量x
x=100 #将全局变量x赋为100
print('GlobalVar2中x的值为:',x) #输出全局变量x
x=20 #定义在所有函数之外,x是全局变量
GlobalVar1() #输出x为20
GlobalVar2() #输出x为100
GlobalVar1() #输出x为100
函数的定义可以嵌套。通过nonlocal关键字,可以使内
层的函数直接使用外层函数中定义的变量。

def outer(): #定义函数outer


x=10 #定义局部变量x并赋为10
def inner(): #在outer函数中定义嵌套函数inner
x=20 #将x赋为20
print('inner函数中的x值为:’,x)
print('开始’)
inner() #在outer函数中调用inner函数
print('outer函数中的x值为:',x) 开始
inner函数中的x值为: 20
outer() #调用outer函数 outer函数中的x值为: 10
def outer(): #定义函数outer
x=10 #定义局部变量x并赋为10
def inner(): #在outer函数中定义嵌套函数inner
nonlocal x #nonlocal声明
x=20 #将x赋为20
print('inner函数中的x值为:',x)
inner() #在outer函数中调用inner函数
print('outer函数中的x值为:’,x)
inner函数中的x值为: 20
outer() #调用outer函数 outer函数中的x值为: 20
def f1():
name = 'f1'
def f2():
name = 'f2'
def f3(): nonlocal可以
#nonlocal 修改外函数的变量,即f2()的name 使用最近的一个
外函数已声明的
nonlocal name
变量(引用同一
print(name) #输出f2,使用的是f2中的name 个内存地址)
name = 'f3' #对f2中的name修改
print(name) #输出f3 修改成功
f3()
print(name)#输出f3,虽然是f2中的name,但是在f3中修改了
f2()
print(name)#输出f1,f1的name,没有被使用
f1()
def add_a():
global a
a=3
add_a()
print(a)
def add_b(): def add_b():
global b #global b
b = 42 b = 42
nonlocal不
def do_global(): def do_local(): 能引用 全
global b nonlocal b 局变量

b = b + 10 b = 10
print(b) print(b)
no binding for nonlocal ‘b’ found
do_global() do_local()
print(b) print(b)
add_b() add_b()
1 变量的作用域

2 匿名函数

3 递归函数

课程目录 4 闭包
Course catalogue
lambda表达式用来声明匿名函数,即没有函数名称的
临时使用的函数,尤其适合需要一个函数作为另一个函数参数
的场合。

[函数名=] lambda 参数1,参数2,…,参数n : 表达式


[函数名 = ] lambda 参数1,参数2,…,参数n : 表达式

➢函数名是可选项。没有函数名,表示是一个匿名函数。
➢可以接收多个参数,但只能包含一个表达式。
➢lambda表达式相当于只有一条return语句的函数,表达式
的值作为函数的返回值。
• 函数与lambda表达式
def my_add(x, y):
return x + y
my_add = lambda x, y : x + y

• 调用lambda表达式

my_add(3,5) # 结果:8
my_add('hello ', 'world') # 结果:'hello world'
def s(x):
if x==1:
return "yes" s=lambda x:"yes" if x==1 else "no"
else: print(s(0))
return "no" print(s(1))

print(s(0))
print(s(1))
lambda表达式尤其适合需要一个函数作为另一个函数参
数的场合。
lambda函数+map函数
Python中的map()函数是一个将给定的序列的值依次在所定义的函
数关系中迭代。

my_list = [2,3,4,5,6,7,8]
new_list = list(map(lambda x:(x %2==0),my_list ))
print(new_list))

[True, False, True, False, True, False, True]


lambda函数+filter函数
filter()方法用于根据一定的条件对给定的序列进行过滤

my_list = [2,3,4,5,6,7,8]
new_list = list(filter( lambda x:(x %2==0),my_list))
print(new_list)

输出结果为:[2, 4, 6, 8]
x=10
a=lambda y:x+y lambda表达式中的x是
x=20 一个自由变量,在运行时
b=lambda y:x-y 绑定值,而不是在定义时
就绑定;
print(a(20),b(10))

输出结果:40 10
如果让某个匿名函数在定义时就捕获到值,可以给
参数设置默认值;

x=10
a=lambda y,x=x:x+y
输出结果:30 10
x=20
b=lambda y,x=x:x-y
print(a(20),b(10))
1 变量的作用域

2 匿名函数

3 递归函数

课程目录 4 闭包
Course catalogue
➢ 函数的递归调用是函数调用的一种特殊情况。函数反复的

自己调用自己,直到当某个条件满足的时候就不再调用
了,然后再一层一层地返回直到该函数第一次调用的位置。
➢ 把一个大型复杂的问题层层转化为一个与原问题相似的规模
较小的问题来求解。
递归函数的求解

➢分解之后待解决的子问题与原问题有着相同的特性和解法;
➢在问题规模上与原问题相比有所减小;
➢每调用一次自身,相当于复制一份该函数,只不过参数有
变化,参数的变化,就是重要的结束条件;
➢一定要注意结束条件。
例如,计算n!的问题
➢可以将其分解为:n! = n*(n-1)!
➢分解后的子问题(n-1)!与原问题n!的计算方法完全一样,只是
规模有所减小;
➢(n-1)!这个子问题又可以进一步分解为(n-1)*(n-2)!,(n-2)!可
以进一步分解为(n-2)*(n-3)!…
➢直到要计算1!时,直接返回1。
fac(5)的计算过程如下:
fac(5)=>5*fac(4)
def fac(n): =>5*(4*fac(3))
if n==1: =>5*(4*(3*fac(2)))
return 1 =>5*(4*(3*(2*fac(1))))
return n*fac(n-1)
=>5*(4*(3*(2*1)))

print(fac(5)) =>5*(4*(3*2))
=>5*(4*6)
=>5*24
=>120
def gcd(a,b):
r = a%b
求最大公约数 if r == 0:
return b
else:
return gcd(b,r)
Demo:输出下面列表中的数字
ls=[1, 2, [3, [4, 5, 6, [7, 8, [9, 10, [11,
12, 13, [14, 15,[16,[17,]],19]]]]]]]

def search(ls):
for item in ls:
if type(item) is list:
search(item)
else:
print(item)

search(ls)
1 变量的作用域

2 匿名函数

3 递归函数

课程目录 4 闭包
Course catalogue
输出:
def test(): testing
print("testing") <function test at
0x0000019C9BB901E0>
test() 分析:print(test)输出了test函数对
print(test) 象地址,但并没有调用test函数。
def test(): 输出:
print("testing") <function test at
0x00000211251F01E0>
testing
test2= test
print(test2) 分析:赋值成功,test2 指向
test2() 了test函数
在函数操作中,函数也可以当成一个参数或一个
返回值进行返回, 当程序内或程序外拿到函数的引
用后就可以直接使用这个函数。
如果内层函数使用了外层函数中定义的局
部变量,并且外层函数的返回值是内层函数的

引用,就构成了闭包。
<function outer.<locals>.inner at
def outer(x):
0x000001524E2735E0>
y=10
def inner(z): outer f=inner
return x+y+z x=5 x
return inner
y=10 y
f=outer(5)# f=inner inner z
print(f) Traceback (most recent call last):

print(inner(20))
File "C:\python\a.py", line 10, in <module>
print(inner(20))
NameError: name 'inner' is not
defined
outer f=inner
def outer(x): x=5 x
y=10 y=10 y
def inner(z): inner z=20
return x+y+z
return inner f(20)
->outer(5)(20)
f=outer(5) ->inner(20)#x=5,y=10,z=20
print(f(20)) f(20)的值为: 5+10+20=35
print(outer(5)(20)) 通过f函数访问了outer函数
的内部变量
outer f=inner
def outer(x):
y=10 x=5 x
def inner(z): y=50 y
return x+y+z inner z=20
y=50
return inner f(20)
->outer(5)(20)
f=outer(5) ->inner(20)#x=5,y=50,z=20
print(f(20))
f(20)的值为: 5+50+20=75
如果要修改外部变量的值,需要将变量声明为 nonlocal

def outer(x): outer f=inner


y=10 x=15 x
def inner(z): y=10 y
nonlocal x
inner z=20
x+=10
return x+y+z f(20)->outer(5)(20)
return inner
f=outer(5)
print('f(20)的值为:', f(20)) 15+10+20=45
def outer(x): outer f=inner
y=10 x=25 x
def inner(z):
y=10 y
nonlocal x
x+=10 inner z=20
print(x,y,z) 15 10 20
return x+y+z f(20)的值为: 45
return inner 25 10 20
f=outer(5) f(20)的值为: 55
print('f(20)的值为:', f(20)) 通过闭包函数保留了
print('f(20)的值为:', f(20)) outer函数的内部变量
闭包的两个作用
➢ 读取函数内部的变量;

➢ 让函数内部的局部变量始终保持在内存中;
Python闭包的__closure__属性
闭包比普通的函数多了一个 __closure__ 属性,
该属性记录着自由变量的地址。当闭包被调用时,系
统就会根据该地址找到对应的自由变量,完成整体的
函数调用。
print(f.__closure__)
(<cell at 0x000001D5D81993D0: int object at
0x000001D5D5B36C30>,
<cell at 0x000001D5D8199C70: int object at
0x000001D5D5B36A50>)
下面代码的功能是,采用闭包定义n 次幂函数,再得到计
算平方的函数my_square
def nth_power(n):
def exponent_of(num): num**n
return ________ exponent_of
return _________ 2
my_square(5)
#my_square为计算一个数的平方的函数
my_square = nth_power(_________)
#计算5的平方
print(____________________)
生成器函数利用关键字yield一次返回一个结果;每次请
求一个值,就会执行生成器中的代码,直到遇到一个yield。

def fibo():
g=fibo()
a, b = 1, 1
while True:
print(next(g)) 1
yield a print(next(g)) 1
a, b = b, a + b print(next(g)) 2

g.send() g.close()
1
1
g=fibo()
def fibo(): 2
for f in g: 3
a, b = 1, 1
print(f) 5
while True: 8
if f > 100:
yield a 13
g.close() 21
a, b = b, a + b
break 34
55
89
144
import turtle
import turtle import turtle
bob = turtle.Turtle()
bob = turtle.Turtle() bob = turtle.Turtle()
def square(t, n, length):
def square(t): def square(t, length):
angle = 360 / n
for i in range(4): for i in range(4):
for i in range(n):
t.fd(100) t.fd(length)
t.fd(length)
t.lt(90) t.lt(90)
t.lt(angle)
square(bob) square(bob,150)
square(bob,7,90)
turtle.mainloop() turtle.mainloop()
turtle.mainloop()
>>>def average(a, b, c):
"""
该函数用于计算三个数的平均值,并返回一个结果
:param a: int_第一个数
:param b: int_第二个数 >>>print(average.__doc__)
:param c: int_第三个数 该函数用于计算三个数的平均
:return: 返回一个计算结果 值,并返回一个结果
""" :param a: int_第一个数
d = (a + b + c) // 3 :param b: int_第二个数
print("平均数为:", d) :param c: int_第三个数
return d :return: 返回一个计算结果
>>>help(average)
注释信息作为函数的帮助说明。
def gcd(a,b):
if not isinstance(a, int):
print('a is not a integer.')
return None
elif not isinstance(b, int):
print('b is not a integer.')
return None
elif a<=0 or b<=0:
print('a or b is not a negative integer.')
return None
r = a%b
if r == 0:
return b
else:
return gcd(b,r)
(1)变量作用域规定了变量起作用的代码范围。通常,在函数体中使用的变量为
局部变量,在函数体外使用的变量为全局变量。通过global关键字,可以在函数
内定义或者使用全局变量。

(2)lambda表达式相当于只有一条return语句的函数,作为另一个函数的参数。

(3)递归调用是函数调用自身的一种特殊应用。递归必须要有边界条件,即递归
终止的条件。

(4)闭包是由函数及其相关的引用环境组合而成的实体,是引用了自由变量的函
数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环
境也不例外。
print([f() for f in [lambda: d for d in [1,2]]])

print([f() for f in [lambda x=d: x for d in [1,2]]])


def foo():
a=1
def bar():
a=a+1
return a
return bar

You might also like