python基础梳理(十一)函数function②

一、函数变量
函数名是变量,它在创建的时候绑定一个函数,绑定在后面的代码块
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语句的变量列表的变量名不能出现在函数的参数列表

猜你喜欢

转载自blog.csdn.net/KingOfMyHeart/article/details/88875239
今日推荐