函数对象与函数嵌套

函数对象:

  函数对象指的是函数可以被当作数据来处理,具体分为四个方面的使用:

1.函数的引用

def index():
    print('fuck')


a = index
a()

2.函数可以当作参数传递

def add(x,y):
    return x + y
def foo(x,y,add):
    return add(x,y)


foo(1,2,add)
print(foo(1,2,add))

3.函数的返回值可以是一个函数

def bar():
    return add


func = bar()
func(2,3)
print(func(2,3))

4.函数名可以当作容器类型的元素

def index():
    print('fuck')


l1 = [1,2,index,index()]
f = l1[2]

函数的嵌套

  在函数内调用函数

def index():
    print('hello')
def func():
    index()
    print('nmh')
    

func()
>>>hello
   nmh
def index():
    def home():
        print('hello')
    home()


index()
>>hello

比较大小

def func1(x,y):
    if x>y:
        return x
    else:
        return y
def func2(a,b,c,d):
    result = func1(a,b)
    result = func1(result,c)
    result = func1(result,d)
    return result


print(func2(123,321,53,1))
>>321

名称空间:

  存放名字的空间,如变量名,函数名

  在程序执行期间最多会存在三种名称空间:

    1.内置名称空间:python解释器提前定义完的名字,在解释器开启时生效,关闭时回收

    2.全局名称空间:存放于文件级别的名字,启动py文件时生效,当前页面代码执行结束后失效

       if,while,for内部定义的名字执行之后都存放于全局名称空间。

    3.局部名称空间:函数内部定义的名字,当调用当前函数时生效,函数体代码执行结束失效

x = 10   # 全局名称空间

def f1():
    x = 20   # 局部名称空间
    
    def f2():
        print('from f1',x)
    f2()
    
f1()
        
print('from file.py',x)   

  名称空间的查找顺序:

    局部:局部 ===》全局===》内置

    全局:全局 ===》内置  #内置找不到,报错

    函数内部使用的名字,在定义阶段已经定死了,与你的调用位置无关

x = 1
def inner():
    x = 2
    def wrapper():
        print(x)  #在局部找x
    wrapper()
x = 111
inner()   #结果为2
print(x) #在全局查找,结果为111

练习

x = 1
def index(arg = x):
    print(x)
    print(arg)

x = 2
index()
>>2
  1

作用域:

  分类:1.全局作用域:位于全局名称空间、内置名称空间中的名字属于全局范围,该范围内的名字全局存活(除非删除)、全局有效(任何位置可用);

     2.局部作用域:位于局部名称空间中的名字属于局部范围。该范围内的名字临时存活(在函数调用时临时生成,结束后释放)、局部有效(只能在函数内使用)。

名字查找的优先级: 在全局作用域查找名字时,起始位置是全局作用域,先查全面名称空间,再找内置名称空间,都没有会抛出异常。

          在局部作用域查找名字时,起始位置时局部作用域,先查找局部名称空间,再去全局作用域查找:全局名称空间》》内置名称空间, 都找不到会抛出异常。

在内嵌的函数查找名字时,会优先查找自己局部作用域的名字,然后由内而外一层层查找外部嵌套函数定义的作用域,没有找到,则查找全局作用域

x = 1
def outer():
    x = 2
    def inner():
        x =3
        print('inner x:%s' %x)
    inner()
    print('outer x:%s' %x)
outer()
结果为:inner x:3
      outer x:2

在函数内,无论嵌套多少层,都可以看到全局作用域的名字,若要在函数内修改全局名称空间中名字的值,当值为不可变类型时,需要用到global

global

x = 1
def foo():
    global x #声明x为全局变量
    x = 2
foo()
print(x)
>>2

当实参的值为可变类型时,函数体内对该值的修改会直接反应到原值

l1 = [1,2,3]
def index(a):
    l1.append(a)
    print(l1)
index(5)
>>[1,2,3,5]

对于嵌套多层的函数,使用nonlocal可以将名字声明为来自外部嵌套函数定义的作用域(非全局)

def f1():
    x = 2
    def f2():
        nonlocal x
        x = 3
    f2() #调用f2(),修改f1作用域中名字x的值
    print(x) # 在f1作用域查看x


f1()
>>3

nonlocal x会从当前函数的外层函数开始一层层去查找名字x,若是一直到最外层都找不到,则会抛出异常。

原文地址:https://www.cnblogs.com/littleb/p/11835368.html