一、函数变量
函数名是变量,它在创建的时候绑定一个函数,绑定在后面的代码块
python中的变量不分类型,每个变量记录对象的内存地址或id
xxxx():函数调用
xxxx :函数变量,绑定在函数对象,保存函数的入口地址
示例一:
def fun(L = []):
print("函数fun被调用")
print(fun)
fun([1,2,3])
fun = None
执行结果:
<function fun at 0x000001A1DBA94730>
函数fun被调用
#从上述的执行结果可以看出,fun是个函数变量,存储着这个函数的地址0x000001A1DBA94730
#从上面的基础上继续执行下面语句:
fun()
执行结果:
fun()
TypeError: 'NoneType' object is not callable
示例二:
def fun1(L = []):
print("函数fun1被调用")
print(fun1)
def fun2(L = []):
print("函数fun2被调用")
print(fun2)
fun2 = fun1 #其实就是将fun1变量绑定的fun1函数的入口地址给了fun2
fun2()
fun1()
执行结果:
<function fun1 at 0x000001EDD0AD4730>
<function fun2 at 0x000001EDD0AD49D8>
函数fun1被调用
函数fun1被调用
示例三:
def fun(L = []):
print("函数fun被调用")
print(fun)
del fun #删除函数变量,这个函数的引用计数-1,所以这个函数的内存可能会马上被回收
fun()
执行结果:
<function fun at 0x0000024C6BAD4730>
File "C:/Users/32191/PycharmProjects/mypythonpro2/function2.py", line 9, in <module>
fun()
NameError: name 'fun' is not defined
def fun(L = []):
print("函数fun被调用")
print(fun)
f = fun #f去绑定记录这个函数的地址
del fun #删除fun变量
f() #可以调用
fun() #此时fun为无效的
执行结果:
<function fun at 0x00000250C4D24730>
函数fun被调用
File "C:/Users/32191/PycharmProjects/mypythonpro2/function2.py", line 10, in <module>
fun()
NameError: name 'fun' is not defined
实际上一个函数可以上面红色、绿色和缺省部分:
1.红色部分:函数名fun = 函数对象,函数名就是个变量,用这个变量和函数对象捆绑在一起
2.绿色部分:这个是函数对象的实体部分。函数变量就是绑定的这个参数。
3.缺省参数部分:在我们def这个函数的时候,列表的内存就存在了。而不是运行时才给的
示例四:
def f1():
print("f1被调用了")
def f2():
print("f2被调用了")
f1,f2 = f2,f1 #交换了俩个变量绑定着的函数的入口地址
f1()
f2()
执行结果:
f2被调用了
f1被调用了
python中一切皆对象,每个对象对应着一个或者多个变量,被变量绑定,或者可以叫引用关系
当对象的引用为0后,该对象会被python的内存回收的对象回收。
二、一个函数可以作为另一个函数的实参(参数)来传递,相当于将函数的入口地址给另外一个函数,就可以在另外一个函数中调用
def f1():
print("我是f1")
def f2():
print("我是f2")
def fn(fx):
fx()
print("我是fn")
fn(f1) #在fn中调用f1
fn(f2) #在fn中调用f2
执行结果:
我是f1
我是fn
我是f2
我是fn
*************************************************************************
假如我们这样调用fn( f1() )
调用过程:
先调用f1,然后打印
print默认返回None,最后相当于成为fn(None)
None类型的对象的是不能调用的
三、函数可以做为另外一个函数的返回值:函数可以返回另外一个函数
这里举例子返回max、min和sum等函数的变量
def get_op():
s = input("请输入你想要选择的操作: ")
if s == "求最大值":
return max
elif s == "求最小值":
return min
elif s == "求和":
return sum
L = [1,2,3,4,5]
f = get_op() # f最终会绑定三个函数中的一个,由用户输入决定
print(f(L))
执行结果:
请输入你想要选择的操作: 求最大值
5
请输入你想要选择的操作: 求最小值
1
请输入你想要选择的操作: 求和
15
四、函数的嵌套定义 动态的创建函数
def 语句是用来创建一个函数
def 语句可以写在函数内部,再函数执行时可以动态的创建一个函数
示例:
def get_fun(value):
if value == 1:
def myadd(x,y):
return x+y
return myadd #返回函数变量
elif value == 2:
def mysub(x,y):
return x-y
return mysub #返回函数变量
fx = get_fun(1)
print(fx(100,200))
fx = get_fun(2)
print(fx(10,2999))
执行结果:
300
-2989
五、局部变量和全局变量
局部变量:
定义在函数内部的变量称为局部变量,函数的形参也是局部变量
局部变量只能再在函数内部使用
局部变量在函数调用时才能创建,在函数调用后才进行销毁
全局变量:
定义在函数外部,模块内部的变量称为全局变量
全局变量所有函数都可以访问(单函数内部不能直接修改全局变量的绑定关系)
示例:
a = 100
b = 200 #全局变量
def fn(c):
d = 300 #c d 局部变量,都是临时创建
print(b,c,d)
a = 999 #试图在函数中修改全局变量 a的绑定
print(a,b,c,d)
fn(300)
#函数调用完全局变量不销毁,在函数中无法改变全局变量的绑定
print('a = ',a)
print('b = ',b)
执行结果:
200 300 300
999 200 300 300
a = 100
b = 200
局部变量说明:
1.在函数内首次对变量赋值时创建,再次赋值是修改绑定关系
2.在函数内部的赋值语句不会对全局变量造成影响
六、python中的作用域(命名空间,含义同C++):四个作用域
是访问变量查找变量名的范围空间
局部作用域 Local (function) L
外部嵌套函数作用域 Enclosing function locals E
函数定义所在模块的作用域 Gobal(module) G
python内置模块的作用域 Buitin(python) B
注:黑体部分是python相对于c特有的作用域
示例一:
v = 100
def fun1():
v = 200
print('fun1中的v的值是:',v)
fun1()
print("全局的v = ",v)
执行结果:
fun1中的v的值是: 200
全局的v = 100
#说明python中学着内存中的变量是由内而外的寻找或者叫由近及远的寻找,和c++其实是一致的
示例二:
#还可以这样验证
v = 100
def fun1():
v = 200
print('fun1中的v的值是:',v)
def fun2():
v = 300
print("fun2里的v = ",v) #这里的v也是由内向外的寻找
fun2()
fun1()
print("全局的v = ",v)
执行结果:
fun1中的v的值是: 200
fun2里的v = 300
全局的v = 100
示例三:
我们知道,我们常用的max() min() len()等函数是内建函数,他是属于我们python内建模块作用域中,
所以我们无法在比他小的范围内修改函数变量的绑定关系
---------------------------------------------------------------------------
>>> #我们在全局范围内调用max函数,实际我们并没有定义这个函数,他会自动向外作用域找这个函数,也就是调用的是python内建模块作用域下的max函数
>>>
>>> max(100,2222,99999)
99999
>>> #我们在全局定义这样一个max变量,这是在全局范围内创建的一个变量
#而不是修改python自建模块作用域中的max绑定关系
>>> max = None
>>> max(1,23)
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
max(1,23)
TypeError: 'NoneType' object is not callable
>>> #删除掉全局作用域下的max变量,又会去自动知道外层作用域里的max函数
>>> del max
>>> max (99,9999,0,4,1234567)
1234567
>>>
几种作用域的包含关系:
变量的名的查找规则(顺序)
1.查找本地变量
2.查找当前函数的外层函数中的内部变量
3.全局变量
4.内置变量
七、globals() / locals() 函数
globals() :返回全局作用内变量的字典
locals() :返回局部作用域内变量的字典
示例:
b = 200
def fx(b,c):
print(a,b,c)
#这里能不能将a获取到并打印?
g = globals()
print("全局变量的字典是: ",g)
l = locals()
print("局部变量的字典是: ",l)
fx(300,400)
执行结果:
100 300 400
全局变量的字典是: {'fx': <function fx at 0x0000015ED1384730>, '__cached__': None, '__builtins__': <module 'builtins' (built-in)>, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000015ED12F8A20>, '__spec__': None, '__name__': '__main__', '__file__': 'C:/Users/32191/PycharmProjects/mypythonpro2/function2.py', '__doc__': None, '__package__': None, 'a': 100, 'b': 200}
局部变量的字典是: {'c': 400, 'b': 300, 'g': {'fx': <function fx at 0x0000015ED1384730>, '__cached__': None, '__builtins__': <module 'builtins' (built-in)>, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000015ED12F8A20>, '__spec__': None, '__name__': '__main__', '__file__': 'C:/Users/32191/PycharmProjects/mypythonpro2/function2.py', '__doc__': None, '__package__': None, 'a': 100, 'b': 200}}
一般来说我们可以用globals()函数在局部作用域里指定访问全局的变量:
用法:
globals()[‘全局变量名’]
#globals() 函数返回回来是个字典。然后用[]访问键值对应的value。
示例:
a = 100
b = 200
def fx(b,c):
print(a,b,c)
#这里能不能将a获取到并打印?
g = globals()['a']
print("函数中访问到全局变量a是: ",g)
h= globals()['b']
print("函数中访问到全局变量b是: ", h)
fx(300,400)
执行结果:
100 300 400
函数中访问到全局变量a是: 100
函数中访问到全局变量b是: 200
练习题1:
1.实现一个mysum函数,给定一个数n,要求返回
0+1+2+3+4+…+n
def mysum(n):
sum = 0
i = 0
while i <= n:
sum += i
i+=1
else:
return sum
print(mysum(100))
执行结果:
5050
八、global语句在内部作用域修改外部作用域
1.作用:
告诉解释执行器,global语句声明的一个或多个变量,这些变量的作用域为模块级的作用域下的变量,也称全局变量
2.全局声明(global)
将赋值变量映射到模块文件内部的作用域
3.语法
global 变量1,变量2…
4.示例:
global a,b,c
global d
# 如果我想在局部作用域中去修改全局变量怎么实现
#global语句
v = 100
def fn():
print("修改前全局作用域的v = ",globals()['v'])
#修改语句
global v # global声明,告诉执行器我要操作的是全局的v变量
v = 999 # 进行修改
fn()
print("修改后全局作用域的v = ", globals()['v'])
执行结果:
修改前全局作用域的v = 100
修改后全局作用域的v = 999
global说明:
1.全局变量如果想要在函数内部被赋值,则必须经过全局声明(否则会被认为是局部变量)
2.全局变量在函数内部不经过声明就可以直接访问,修改需要
3.不能先声明局部变量,再用global声明为全局变量,这样不符合规则
4.global变量列表里的变量名不能出现在此作用域内的形参列表中
九、nonlocal 语句
作用:
告诉解释器,nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量
语法:
nonlocal 变量1,变量2…
示例:
v = 100
def outter():
v = 200
print("outter中的v = ",v)
def inner():
nonlocal v #告诉解释器我们要操作的是外部嵌套函数中的 v
v+=1
print("我用的是inner函数中的v",v)
inner()
print('调用inner后,outter中的v = ',v)
outter()
print("全局的v = ",v)
执行结果:
outter中的v = 200
我用的是inner函数中的v 201
调用inner后,outter中的v = 201
全局的v = 100
nonlocal说明:
1.nonlocal语句只能在被套函数内部使用
2.访问nonlocal变量将对外部嵌套函数作用域内的变量进行操作
3.当有俩层或俩层以上的函数嵌套后,访问nonlocal变量只对最近一层的变量进行操作()
示例:
def f1():
v = 100
def f2():
v =1000
def f3():
nonlocal v
print(v)
#f3中的v讲使用f2中的v
4.nonlocal语句的变量列表的变量名不能出现在函数的参数列表