一、函数对象
'''函数是第一类对象,函数是第一等公民'''
1.函数可以被赋值
def foo(): # foo -> 函数的内存地址
print('hello')
f = foo # <function foo at 0x000002A3B14F6280> 传递内存地址
print(f) # hello
f() # hello
2.函数可以当作参数传递给另外一个函数
# x = 1
# def func(a):
# print(a)
# func(x)
def foo(): # foo->函数的内存地址
print('hello')
def func(f)
print(f) # <function foo at 0x000001DB55436280> foo -> 函数的内存地址
f()
func(foo) # hello
3.函数可以当作函数的返回值
def foo(): # foo->函数的内存地址
print('hello')
def func(f)
return f # 返回foo 的内存地址
res = func(foo)
print(res) # <function foo at 0x00000263781D6280> foo->函数的内存地址
4.函数可以当作容器类型的元素
def foo(): # foo->函数的内存地址
print('hello')
l = [11, foo, 22]
print(l) # [11, <function foo at 0x000001E6839B6280>, 22]
l[0]() # hello
# 例子
def login():
pass
def register():
pass
def withdraw():
pass
def transfer():
pass
while True:
print("""
'0': 'Quit'
'1': 'Login'
'2': 'Register'
'3': 'Withdraw'
'4': 'Transfer'
""" )
choice = input('Input number>>>').strip()
if choice == '0':
break
elif choice == '1'
login()
elif choice == '2'
register()
elif choice == '3'
withdraw()
elif choice == '4'
transfer()
else:
print('Number was error!')
# 存在的问题:代码臃肿
# 解决方案:利用函数对象的特性
def login():
pass
def register():
pass
def withdraw():
pass
def transfer():
pass
func_dic={
'1': ['Login', login]
'2': ['Register', register]
'3': ['Withdraw', withdraw]
'4': ['Transfer', transfer]
}
while True:
print('0 Quit')
for i in func_dic:
print('%s %s' % (i, func_dic[i][0]))
choice = input('Input number>>>').strip()
if choice == '0':
break
elif choice in func_dic:
func_dic[choice][1]()
else:
print('Number was error!')
二、函数嵌套
1.函数嵌套调用:在调用一个函数的过程中,该函数内部又调用了其他函数-----》能将大功能拆解成几个小功能。
def bar():
print('hello')
def foo():
print('world')
bar()
foo() # world \n hello
# 例子
def max2(x, y):
if x > y:
# print(x)
return x # max4 需要返回值
else:
# print(y)
return y
def max4(a, b, c, d):
res1 = max2(a, b)
res2 = max2(res1, c)
res3 = max2(res2, d)
# print(res3)
return res3
# max4(11, 55, 66, 22) # 66
max = max4(11, 55, 66, 22)
print(max) # 66
2.函数的嵌套定义:在函数内又定义了其他函数-----》封闭,内部的代码外面看不见
def foo():
def bar():
print('hello')
# bar() # hello
x = 111
foo() # 无结果,并未调用内部函数bar
f = foo()
print(f) # None
bar() # 报错 name 'bar' is not defined foo() 函数的嵌套定义内部代码外面运行不到
print(x) # 报错 name 'x' is not defined foo() 函数的嵌套定义内部代码外面运行不到
# 例子:求圆的周长与面积
from math import pi
def circle(radius):
def perimiter(radius):
return 2 * pi * radius
def area(radius):
return pi * (radius ** 2)
circle(30)
# 升级需求:函数的嵌套定义内部只调用其中一个
# 知识回顾:f.seek(0, 0),控制指针移动,seek(字节个数, 模式),三种模式:mode = 0, 1, 2
from math import pi
def circle(radius, mode=0):
def perimiter(radius):
return 2 * pi * radius
def area(radius):
return pi * (radius ** 2)
if mode == 0:
return perimiter(radius)
elif mode == 1:
return pi * (radius ** 2)
res = circle(30,1)
print(res) # 2827.4333882308138
三、名称空间与作用域
1.名称空间Namespace:存放名字与内存地址绑定关系的地方
1.1 内置名称空间
含义:放置python自带的名字,print、len、input
生命周期:解释器启动则产生,解释器关闭则销毁
1.2 全局名称空间
含义:放置顶级的名字,如x、y、foo、
生命周期:运行python文件则立即产生,python文件运行完毕则结束
x = 10
if 10 > 3:
y = 996
def foo():
z = 997
1.3 局部名称空间
含义:放置函数的名字,如上z
生命周期:调用函数则产生,函数调用完毕则销毁
局部变量只能在定义它的函数中使用
# 重要结论
1)名称的查找优先级:局部-》全局-》内置,三者彼此之间无干扰,名称空间无嵌套关系
永远基于自己当前所在的位置向外查找:LEGB(local --> enclosing --> global --> built-in
local指一个函数或者方法的内部的名称空间,enclosing指的是闭包内部名称空间,global是全局 名称空间,而built-in是指内置名称空间)
len = 100
def foo():
len = 200
print(len) # print 站在局部
foo() # 200
print(len) # 100 站在全局
2)名称空间的嵌套关系是以函数定义为准生成的,与调用位置无关,定义时检测语法,不执行代码 体,确定位置和有没有参数,调用时检测逻辑错误,执行代码体
# 例1
def foo():
print(len) # 在局部,无len则往外的全局找
def bar():
len = 200
foo()
len = 100
bar() # 100
# 例2
x = 111
def foo():
print(x) # print在局部,局部有x,但存在语法错误,应当先定义后引用
x = 222
f1() # UnboundLocalError:local variable 'x' referenced before assignment
# 例3
x = 1
def f1():
x = 2
def f2():
x = 3
print(x)
f2()
f1() # 3
# 关键字
1)global关键字:
# 例1:不可变类型
x = 1
def foo():
global x # 声明此处的x升级为全局变量
x = 2
foo()
print(x)
# 例2:可变类型,影响全局
x = [11, 22, 33]
def foo():
x.append(444)
foo()
print(x) # [11, 22, 33, 44]
2)nonlocal关键字:指E空间,即外层函数,不包含全局,声明一个名字是来自外层函数,如果外层没有也不会找到全局,会报错
x = 1
def f1():
x = 2
def f2():
# global x
nonlocal x
x = 3
f2()
print(x) # 3
f1()
# print(x) # 3
2.作用域:发挥作用的范围,对名称空间的总结
2.1 全局作用域:全局存活,全局有效,伴随python运行始终,内置名称空间,全局名称空间
2.2 局部作用域:临时存活,局部有效,局部名称空间,只能在函数内用,调用完毕就结束
四、闭包函数
闭包函数 = 函数对象 + 函数嵌套定义 + 名称空间与作用域
1.闭函数:定义在函数内部的函数
def foo():
def wrapper():
pass
2.包函数:内部函数引用了一个外层函数的名字
def foo():
x = 111
def wrapper():
print(x)
return wrapper # 千万不要加括号,加了括号就运行函数代码
f = foo()
print(f)
def func()
x = 222
f()
func()
# 闭包函数的作用:是一种为函数体传参的方案
# 为函数体传参的方案一:直接使用形参(首选)
def wrapper(x)
print(x)
wrapper(11)
wrapper(22)
wrapper(33)
# 为函数体传参的方案二:闭包函数(括号内不能用参数时)
def outter(x):
# x = 111
def wrapper():
print(x)
return wrapper # 不能加括号
wrapper = outter(111) # 此处wrapper是变量
wrapper()