一、函数的对象
函数时第一类对象,指的是函数名指向的值(函数)可以被当做数据去使用
def func():# func=函数的内地址 print('from func') print(func) age=10 #1. 可以被引用 x=age print(x,age) f=func print(f) f() #2. 可以当作参数传给另外一个函数 def bar(x): print(x) bar(age) bar(func) #3. 可以当作一个函数的返回值 def bar(x): return x res=bar(age) print(res) res=bar(func) print(res) #4. 可以当作容器类型的元素 l=[age,func,func()] print(l)
二、函数的嵌套
1.函数嵌套分为两大类
1.1函数的嵌套调用:在调用一个函数过程中,其内部代码又调用了其他函数
def max2(x,y): if x > y: return x else: return y def max4(a,b,c,d): res1=max2(a,b)#2 res2=max2(res1,c)#3 res3=max2(res2,d)#4 return res3 print(max4(1,2,3,4))#4
1.2函数的嵌套定义:一个函数内部又定义了另外一个函数
案例一
def outter(): x=1 print('from outter') def inner(): print('from inner') print(x) print(inner) outter() #from outter #1 #<function outter.<locals>.inner at 0x000001D175B7CB70> inner()#
案例二
def f1(): print('from f1') def f2(): print('from f2') def f3(): print('from f3') f3() f2() f1() #from f1 #from f2 #from f3
案例三
from math import pi print(pi)#3.141592653589793 def circle(radius,action=0): """ 圆形相关运算 :param radius: 半径 :param action: 0代表求面积,1代表求周长 :return: 面积或者周长 """ def area(radius): return pi * (radius ** 2) def perimiter(radius): return 2 * pi * radius if action == 0: res=area(radius) elif action == 1: res=perimiter(radius) return res print(circle(10,0))#314.1592653589793 print(circle(10,1))#62.83185307179586
三、名称空间与作用域
1 什么是名称空间namespace
名称空间就是名字和值内存地址绑定关系的地方(内存空间)
age=18
但凡查找值一定要通过名字,访问名字必须去查找名称空间
2 名称空间分为三大类
2.1内置名称空间
存放的是python解释器自带的名字
例如:
len
max
print
2.2全局名称空间
存放的是文件级别的名字
例如:以下名字中x\y\z\b\foo都会存放于全局名称空间中
x=1 y=2 if x == 1: z=3 while True: b=4 break def foo(): m=3
2.3局部名称空间
在函数内定义的名字
例如:
foo内的m这个名字一定是存放于一个局部名称空间中
2.4生命周期
内置名称空间:在解释器启动时则生效,解释器关闭则失效
全局名称空间:在解释器解释执行python文件时则生效,文件执行完毕后则失效
局部名称空间:只在调用函数时临时产生该函数的局部名称空间,改函数调用完毕则失效
2.4加载顺序
内置->全局->局部
2.5查找名字的顺序
基于当前所在位置往上查找
假设当前站在局部,查找顺序:局部->全局->内置
假设当前站在全局,查找顺序:全局->内置
len=111 def foo(): len=222 print(len) foo() print('站在全局找len: ',len)
案例二
x=111 def f1(): x=222 def f2(): def f3(): x=444 print(x)#444 x=333 f3() f2() f1()
******)名字的查找顺序,在函数定义阶段就已经固定死了(即在检测语法时就已经确定了名字的查找顺序),与函数的调用位置无关,也就是说无论在任何地方调用函数,都必须回到
当初定义函数的位置去确定名字的查找关系
案列三:
x=111 def outer(): def inner(): print('from inner',x) # x访问的时全局名称空间中x return inner f=outer() x=222 f()#222
案列四:
x=111 def outer(): def inner(): print('from inner',x) # x访问的时全局名称空间中x return inner f=outer() # x=222 def func(): x=333 f() x=444 func()#444
案列五:
x=111 def outer(): def inner(): print('from inner',x) # x是来自于当前层的名字,但是此时的x并未定义 x=2222222222 return inner f=outer() f()
3.作用域:
域指的是范围,作用域指的就是作用的范围,分为两种
全局作用域:包含的是内置名称空间与全局名称空间中的名字
特点:全局有效,全局存活
局部作用域:包含的是局部名称空间中的名字
特点:局部有效,临时存活
案例一
x=1#全局存活 def foo(): y=2 print(x)#1 def bar(): print(x)#1 foo() bar()
案例二
l=[]#这个l是存放在全局空间 def foo(): l.append(1)#报错,在局部名称空间中没有l l=33333 foo() print(l)
global:在局部声明一个名字是来自于全局作用域的,可以用来在局部修改全局的不可变类型
x=1 def foo(): global x x=2 foo() print(x)#2
nonlocal:声明一个名字是来自于当前层外一层作用域的,可以用来在局部修改外层函数的不可变类型
x=0 def f1(): x=111 def f2(): nonlocal x#只能修改当前函数的外面一层而已 x=222 f2() print(x)#222 f1() print(x)#0
四、闭包函数
1 什么是闭包函数
闭:指的是闭包函数是定义在一个函数内部的函数
包:该内部函数包含对外层函数作用域名字的引用
a 必须有一个内嵌函数
b 内嵌函数必须引用外部函数中的变量
c 外部函数的返回值必须是内嵌
需要结合函数对象的概念将闭包函数返回到全局作用域去使用,从而打破函数的层级限制
def outter(): x=111 def inner(): print(x) return inner f=outter() #f=outter内的inner
2 为何要用闭包函数
闭包函数提供了一种为函数体传值的解决方案
3 如何用闭包函数
为函数体传值的方式一:参数
def func(x,y): print(x+y) func(1,2)
为函数体传值的方式二:闭包
def outter(x,y): def func(): print(x+y) return func f=outter(1,2) f()
案例
def get(): response=requests.get(url) if response.status_code == 200: print(response.text)
解决方案一:参数
pip3 install requests import requests def get(url): response=requests.get(url) if response.status_code == 200: print(len(response.text)) get('https://www.baidu.com') get('https://www.baidu.com') get('https://www.baidu.com') get('https://www.tmall.com') get('https://www.tmall.com') url1='https://www.baidu.com' url2='https://www.tmall.com' get(url1) get(url1) get(url1) get(url2) get(url2) get(url2)
解决方案二:闭包
def outter(url): # url='https://www.baidu.com' def get(): response=requests.get(url) if response.status_code == 200: print(len(response.text)) return get baidu=outter('https://www.baidu.com') tmall=outter('https://www.tmall.com')