第十章 高阶函数

一、名称空间和作用域

可以简单理解为存放变量名和变量值之间绑定关系的地方。

1. 名称空间

在 Python 中有各种各样的名称空间:

  • 全局名称空间:每个程序的主要部分定义了全局的变量名和变量值的对应关系,这样就叫做全局名称空间

  • 局部名称空间:在函数的运行中定义的临时的空间叫做局部名称空间,只可以被这个函数所有。函数运行结束后,这个局部的名称空间就会销毁。

  • 内置名称空间:内置名称空间中存放了python解释器为我们提供的名字:input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法。

三种名称空间之间的加载顺序

python3 test.py

# 1、python解释器先启动,因而首先加载的是:内置名称空间
# 2、执行test.py文件,然后以文件为基础,加载全局名称空间
# 3、在执行文件的过程中如果调用函数,则临时产生局部名称空间

名字的查找顺

当我们要使用一个变量时,先从哪里找?

局部使用:局部名称空间——>全局名称空间——>内置名称空间

x = 1
def f1():
    x = 10
    print(x)

f1()  # 输出 10

全局使用:全局——>内置

#需要注意的是:在全局无法查看局部的,在局部可以查看全局的,如下示例

x = 1
def f1():
    x = 10
    print(x)

print(x)  # 输出  1

2. 作用域

作用域就是变量名的生效范围

分为: 全局作用域 和 局部作用域

a. 全局作用域

内置的名称空间中的名字和全局名称空间的名字属于这个全局作用域。

  • 全局作用域中的名字,在整个文件的任意位置都能被引用,全局存活,全局内都有效。

b. 局部作用域

局部名称空间的名字属于局部作用域。

  • 局部作用域中的名字只能在其本地局部生效和使用。

  • python 中局部作用域就是函数内定义或生成的名字,临时存活,随着函数调用的结束而消失。



二、 高阶函数

特点

  • 把一个函数的函数名当做实参传给另一个函数
  • 函数本身可以作为另外一个函数的返回值
def foo():
       return 10

def func(bar):
        print(id(bar), bar)

# 直接打印原函数的 id
print(id(foo))

# 调用函数 并把 foo 作为实参传递进去,查看传输的函数的 id
func(foo)

在调用函数 func(foo) 时,如下图:

image

可以看出被传入的函数和原函数是一个对象



三、内部函数

在一个函数内部定义的函数

def outer():
    def inner():
        x = 10

函数 inner 就是一个内部函数



四、 闭包

是另一个函数动态生成的函数,并且返回一个 包含了外部作用域而非全局作用域变量名称的 函数。这个函数可以使用外部作用域的变量。

def outer(f):
    def inner():
        print(f)
    return inner

really_inner = outer(10)

really_inner()

上面的 f 可以是任何的 python 对象,当然也可以是给函数。

def foo():
    pass

def outer(f)
    def inner():
        print(f)
    return inner

really_inner = outer(foo)

此时, really_inner 就是闭包, 其本质就是 inner 函数对象, 并且包含了 foo 这个函数对象。



五、 装饰器

原始方式实现(老的方式)

def outer(arg):
    def inner():
        print("*" * 20)
        arg()
        print("*" * 20)

    return inner

def echo():
    print('欢迎来到千锋云计算')

echo = outer(echo)   # inner

echo()

语法糖实现(目前使用此种方式)

def outer(arg):
    def inner():
        print("*" * 20)
        arg()
        print("*" * 20)

    return inner

@outer   # echo = outer(echo)   # inner
def echo():
    print('欢迎来到千锋云计算')

echo()

使用装饰器的理由

在软件开发领域有个规则:

在开发时,需要遵循 开放封闭原则,就是对扩展开放,对修改封闭。

扩展开放,就是可以对原来的函数功能进行扩展。

修改封闭,就是给原来的函数添加功能的时候,不可以直接修改原来的函数。

装饰器的作用是什么

装饰器时装饰其他对象的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。

强调装饰器的原则:

  1. 不修改被装饰对象的源代码
  2. 不修改被装饰对象的调用方式

装饰器的目标:

在遵循1和2的前提下,为被装饰对象添加上新功能

补充内置函数 枚举 enumerate

li = ["hello","world", 'len', 'network']
#
# for idx, item in enumerate(li):
#     print(idx, item)

# for idx, item in enumerate(li, 1):
#     print(idx, item)

你可能感兴趣的:(第十章 高阶函数)