函数对象
# 精髓:可以把函数当成变量去使用
# 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()
原文:https://www.cnblogs.com/ccTracy2021/p/14954729.html