内容概要
- 函数对象
- 函数嵌套
- 名称空间与作用域
- global与nonlocal
- 闭包函数
内容详细
-
函数对象
# 精髓:可以把函数当成变量去使用 # func = 内存地址 # def func(): # print(‘from func‘) # 1.可以赋值 # f = func # print(f,func) # <function func at 0x0000019ED9B7F160> <function func at 0x0000019ED9B7F160> # f() # from func # 2.可以当作函数的参数传给另外一个函数 # def foo(x): # x() # foo(func) # from func 这里调用函数foo(func),这里的函数func相当于参数传给x,x()=func() # 3.可以把函数当作另一个函数的返回值 # def foo(x): # return x # res = foo(func) # print(res) # <function func at 0x0000014696C5F160> # res() # from func # 4.可以当作容器类型的一个元素 # l = [func,] # print(l) # l[0]() # from func # # dic = {‘k1‘:func,} # print(dic) # dic[‘k1‘]() # from func # eg: def register(): priint(‘注册功能实现===》‘) def login(): print(‘登录功能实现===》‘) def withdraw(): print(‘提现功能事项===》‘) func_dic = { ‘0‘:‘退出‘, ‘1‘:[‘注册‘,register], ‘2‘:[‘登录‘,login], ‘3‘:[‘提现‘,withdraw] } while True: choice = input(‘请输入命令编号:‘) for i in func_dic: print(‘%s %s‘%(i,func_dic[i][0])) if choice == ‘0‘: break elif choice in func_dic: dic_func[choice][1]() else: print(‘编号输入错误,请重新输入‘)
-
函数嵌套
# 函数嵌套 # 1.函数的嵌套调用:在调用一个函数的过程中又调用另一个函数 # 取四个值中最大的值 def max2(x,y): if x > y: return x elif x < y: return y def max4(a,b,c,d): # 比较a,b,大的值赋值给res1 res1 = max2(a,b) # 比较res1,c,大的值赋值给res2 res2 = max2(res1,c) # 比较res2,d,大的值赋值给res3 res3 = max2(res2,d) return res3 res = max4(1,2,3,4) print(res) # 2.函数的嵌套定义:在函数内定义函数 # 求圆的面积和圆的周长 # 定义圆的面积 pi*(radius**2) from math import pi def circle(radius,mode = 0): def perimimter(radius): return 2 * pi *radius def area(radius): return pi * (radius ** 2) if mode == 0: return 2 * pi *radius elif mode == 1: return pi * (radius ** 2) res = circle(30,0) print(res)
-
名称空间与作用域
# 一、名称空间namespaces,存放名字的地方,是对栈区的划分 # 有了名称空间之后,就可以在栈区中存放相同的名字 # (1)详细的名称空间分为3种: # 1.内置名称空间: # 存放的名字:存放的python解释器的名字: ‘‘‘ >>> print <built-in function print> >>> input <built-in function input> ‘‘‘ # 存活的周期:python解释器启动则产生,关闭则销毁 ‘‘‘python解释器启动==>将文件内容当作普通的文本内容读到内存 ==>开始识别python语法,也就是开始运行python代码,识别函数名、模块名等 ‘‘‘ # 2.全局名称空间: # 存放的名字:运行*代码所产生的名字,不是函数定义,也不是内置的,剩下的都是全局名称空间 # 存活的周期:python文件执行则产生,运行完毕则销毁 # import os # x=4 # if x>3: # y=20 # if 3==3: # c=2 # def func(): # a=1 # class foo: # pass # 以上除了 a=1,pass都是*代码 # 3.局部名称空间: # 存放的名字:在调用函数时,运行函数体代码过程种产生的函数内得名字 # 存活得周期:在调用函数时存活,函数调用完毕时则销毁 def func(): a = 1 func() # 在此时调用函数时才存活,产生名字,且调用几次产生几个名字 # (2) 名称空间运行顺序 # 1.名称空间的加载顺序: # 内置名称空间>全局名称空间>局部名称空间 # 2.名称空间的销毁顺序: # 局部空间名称>全局空间名称>内置名称空间 # 3.名称查找的优先级:当前所在位置向上一层一层查找 # 如果当前在局部名称空间: # 局部名称空间->全局名称空间->内置名称空间 # # input = 111 # def func(): # # input = 222 # print(input) # func() # 运行调用函数,1.先在局部名称空间找,结果为 222, # 2.注释掉input = 222,局部名称空间内未找到,去全局名称空间找,结果为 111 # 3.注释掉input =222,input = 111,局部名称空间和全局名称空间都未找到,去内置名称空间找:结果为 <built-in function input> # 如果当前在全局名称空间: # 全局名称空间->内置名称空间 (原因参照上述分析) # (3).案例 # 示范一: # def func(): # print(x) # x = 222 # func() # # 结果为222,x = 222为全局名称空间 # 示范二:名称空间的‘嵌套空间‘关系是以函数定义阶段为准,与调用位置无关 # x = 1 # def func(): # print(x) # def foo(): # x=222 # func() # foo() # # 结果为1,在定义阶段x=1, # 示范三: # 1.从此代码到依次注释掉333,222,111, 结果为333,222,111,<built-in function input> # input = 111 # def f1(): # input = 222 # def f2(): # input = 333 # print(input) # f2() # f1() # 2.结果 222 # input = 111 # def f1(): # def f2(): # # input = 333 # print(input) # input = 222 # f2() # f1() # 示范4 # x = 111 # def func(): # print(x) # x = 222 # func() # 报错 先定义后调用,以定义阶段为准。定义阶段:print(x),先去局部空间寻找,找到了x=222, # 定义阶段只要没有语法错误就不会报错,但当调用时,要输出x,但是x=222在print(x)之后, # 所以在x要输出时,发现未被定义,因此报错。 # 二、作用域 # 全局作用域:内置名称空间,全局名称空间 # 1.全局存活 # 2.全局有效:被所有函数共享 # 局部作用域:局部名称空间 # 1.局部存活 # 2.局部有效:函数内有效
-
global与nonlocal
# global # 示范一: # x = 111 # def func(): # x = 222 # # func() # print(x) # 输出结果:111 # 示范二:如果在局部想修改全局名称对应的值(值为不可变类型) # x = 111 # def func(): # global x # 声明x这个名字是全局的名字,不需要再造新的名字了 # x = 222 # 将全局名称空间的x赋值成222 # func() # print(x) # 222 # 示范三: # l = [2,3] # def func(): # l.append(4) # print(l) # func() # [2,3,4] # nonlocal(了解):修改函数外层的函数包含的名字对应的值(不可变类型) # 示范一: # x = 1 # def f1(): # x = 2 # def f2(): # nonlocal x # 将x = 2修改成x = 3 # x = 3 # f2() # print(‘f1内的x:‘,x) # f1() # 如果是可变类型的话就没必要定义nonlocal了 # 示范二: # x = 1 # def f1(): # x = [2] # def f2(): # x.append(3) # f2() # print(‘f1内的x:‘,x) # f1内的x: [2, 3] # f1()
-
闭包函数
# 一、大前提 # 闭包函数:名称空间与作用域+函数嵌套+函数对象 # 核心点:名字的查找关系是以函数的定义阶段为标准 # 什么是闭包函数: # ‘闭函数‘指的是该函数为内嵌函数 # ‘包函数‘指的是该函数包含对外层函数作用域名字的引用(不是对全局作用域) # 闭包函数:名称空间与作用域+函数嵌套 def f1(): x = 111 def f2(): x = 222 def f3(): print(x) f3() f2() x = 666 def f4(): x = 444 f1() def f5(): x = 555 f4() f5() # 闭包函数:函数对象 # def f1(): # x = 222 # def f2(): # print(‘from f2‘, x) # return f2 # 这里将f2从局部变成了全局,打破层级限制,可以在任意位置调用 # f = f1() # # print(f) # <function f1.<locals>.f2 at 0x000001A5753CC3A0> # def f3(): # x = 333 # f() # from f2 222 # 为何要有闭包函数==》闭包函数的应用 # 两种为函数体传参的方式 # 方式一:直接把函数体需要的函数定义为形参 # def func(x): # print(x) # func(1) # func(2) # func(3) # 方式二:闭包函数 def outter(x): def wrapper(): print(x) return wrapper wrapper = outter(111) # 这里为其传参 wrapper() # 爬网址案例 # 需要先去cmd导入模块 import requests ‘‘‘ https://www.baidu.com/ https://i.cnblogs.com/ https://www.zhihu.com/ ‘‘‘ # 方案一: # def get(url): # response = requests.get(url) # print(response.text) # get(‘https://www.baidu.com/‘) # get(‘https://i.cnblogs.com/‘) # get(‘https://www.zhihu.com/‘) # 方案二: # def website(url): # def get(): # response = requests.get(url) # print(response.text) # return get # baidu = website(‘https://www.baidu.com/‘) # baidu() # # cnblogs = website(‘https://i.cnblogs.com/‘) # cnblogs() # # zhihu = website(‘https://www.zhihu.com/‘) # zhihu()