python基础—函数嵌套与闭包

python基础—函数嵌套与闭包

 

1、名称空间与作用域

 

 1 名称空间分为:

 

   1 内置名称空间   内置在解释器中的名称

 

   2 全局名称空间   顶头写的名称

 

   3 局部名称空间

 

2 找一个名称的查找顺序:先在局部名称空间找,再到全局名称空间找,再到内置名称空间

 

3 Globals()  查看全局名称空间的内容

 

  Locals()   查看局部名称空间的内容

 

4 全局作用域包含内置名称空间和全局名称空间

 

   局部作用域包含局部名称空间

 

 

1 查看内建名称空间的内容:

 

 

2 作用域

1
2
3
4
5
6
x=1
def foo():
    x=100
    print(x)
foo()
print(x)

输出结果:

1
2
100
1

 

3 一定要注意函数要先定义,后使用

1
2
3
4
5
6
def foo():
    print("from foo")
    bar()
def bar():
    print("from bar")
foo()

输出结果:

1
2
from foo
from bar

 

1
2
3
4
5
6
def foo():
    print("from foo")
    bar()
foo()
def bar():
print("from bar")

输出结果:

1
NameError: name 'bar' is not defined  #报错

 

4 Globals()  查看全局名称空间的内容

  Locals()   查看局部名称空间的内容

1
2
3
4
5
6
7
8
9
x=1
def func():
    print("from func")
    x=2
    print(globals())
    print(locals())
func()
print(globals())
print(locals())

输出结果:

1
2
3
4
5
from func
{'x'1'__cached__'None...
{'x'2}
{'x'1'__cached__'None...
{'x'1'__cached__'None...

 

2、函数嵌套与静态嵌套域

嵌套调用

嵌套调用作用:将一个大的功能细化成各种小的函数功能并调用

1
2
3
4
5
6
7
8
9
10
def my_max(x,y):
    res=if x >y else y
    return res
print(my_max(10,100))
def my_max4(a,b,c,d):
    res1=my_max(a,b)
    res2=my_max(res1,c)
    res3=my_max(res2,d)
    return res3
print(my_max4(1,20,3,4))

输出结果:

1
2
100
20

 

在函数内定义的函数 在外面不能用到

1
2
3
4
5
6
7
def f1():
    def f2():
        def f3():
            pass
    print("---->f1")
    f2()
f2()

输出结果:

1
NameError: name 'f2' is not defined  #报错

 

#嵌套定义   

x找值的过程:先在局部名称空间找,再到上一级的局部名称空间找,再到全局名称空间找,再到内置名称空间

1
2
3
4
5
6
7
8
9
10
11
12
13
x=0
def f1():
    #x=1
    print("---f1---",x)
    def f2():
        #x=2
        print("---f2---",x)
        def f3():
            #x=3
            print("---f3---",x)
        f3()
    f2()
f1()

输出结果:

1
2
3
---f1--- 0
---f2--- 0
---f3--- 0

 

3、函数对象

 

函数被称为第一类对象,函数可以被当做数据传递

 

(1)函数可以被赋值

直接输出函数名的值: 就是函数在内存中的地址

1
2
3
def foo():
    print("foo")
print(foo)

输出结果: 

1
<function foo at 0x000000DD32CAAD90>

 

函数可以被赋值:将函数名代码的值赋给变量  

1
2
3
4
5
def foo():
    print("foo")
f=foo
print(f)
f()

输出结果:

1
2
<function foo at 0x0000003AEBEBAD90>
foo

 

(2)函数可以作为参数传递

函数可以作为参数传递

1
2
3
4
5
6
def foo():
    print("foo")
def bar(func):
    print(func)
    func()
print(bar(foo))

输出结果:

1
2
3
<function foo at 0x000000A351B4AD90>
foo
None

 

(3)函数可以作为返回值

函数可以作为函数的返回值

1
2
3
4
5
6
7
8
9
def foo():
    print("foo")
def bar(func):
    print(func)
    func()
    return func
f=bar(foo)
print(f)
f()

输出结果:

1
2
3
4
<function foo at 0x000000BFD82CAD90>
foo
<function foo at 0x000000BFD82CAD90>
foo

 

(4)函数可以作为容器类型的元素

函数作为字典的键的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def add():
    print("=======>function add")
def search():
    print("=======>function search")
def delete():
    print("=======>function delete")
def change():
    print("=======>function change")
def tell_msg():
    msg='''
    search:查询
    add:添加
    delete:删除
    change:修改
    create:新建
    '''
    print(msg)
def create():
    print('=======>function create')
 
cmd_dic={
    'search':search,
    'add':add,
    'delete':delete,
    'change':change,
    'create':create
}
while True:
    tell_msg()
    choice=input("please input your choice:")
    cmd_dic[choice]()

 

 

4、函数闭包

 

(1)函数闭定义

闭包:首先必须是内部定义的函数,该函数包含对外部作用域而不是全局作用域名字的引用

定义:内部函数的代码包含对外部函数的代码的引用,但一定不是对全局作用域的引用

闭包的基本形式是:

  在函数F1中,定义F2,F2只能引用F1定义的变量,之后F1函数返回F2的函数名字

  这样就保证了可以将F1的执行结果赋予给一个变量,该变量可以在之后的任何时刻随时可以运行 

使用闭包的好处:自带状态即变量,可以不用传参就用,方便。

闭包(closure)是函数式编程的重要的语法结构。不同的语言实现闭包的方式不同。Python以函数对象为基础,为闭包这一语法结构提供支持的 (我们在特殊方法与多范式中,已经多次看到Python使用对象来实现一些特殊的语法)。Python一切皆对象,函数这一语法结构也是一个对象。在函数对象中,我们像使用一个普通对象一样使用函数对象,比如更改函数对象的名字,或者将函数对象作为参数进行传递。

 

  

 (2)简单闭包举例

1
2
3
4
5
6
7
8
9
10
x=1000
def f1():
    x=1
    def f2():
        print(x)
    return f2
f=f1()
print(f)
x=123
f()

输出结果:

1
2
<function f1.<locals>.f2 at 0x000000C02BD1AF28>
1

 

(3)闭包的__closure__变量

闭包都有__closure__属性

__closure__对象会返回闭包应用外围作用域的变量信息。f.__closure__保存外围作用域的变量内存地址,f.__closure__[0].cell_contents存放的是外围作用域的变量的值。

对于那些不是闭包的函数对象来说,__closure__ 属性值为 None。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
x=1
def f1():
    x=1000
    y=2
    def f2():
        y
        print(x)
    return f2
f=f1()  #f ---> 内部的函数f2
f()
print(f.__closure__)
print(f.__closure__[0])
print(f.__closure__[0].cell_contents)
print(f.__closure__[1])
print(f.__closure__[1].cell_contents)

输出结果:

1
2
3
4
5
6
1000
(<cell at 0x000000429E165D68int object at 0x000000429E0A9EB0>, <cell at 0x000000429E165D98int object at 0x0000000059C0EF50>)
<cell at 0x000000429E165D68int object at 0x000000429E0A9EB0>
1000
<cell at 0x000000429E165D98int object at 0x0000000059C0EF50>
2

 

举例:__closure__ 属性值为 None

1
2
3
4
5
6
7
8
x=1
def f1():
    def f2():
        print(x)
    return f2
f=f1()  #f ---> 内部的函数f2
f()
print(f.__closure__)

 输出结果为:

1
2
1
None

 

(4)闭包应用

Windows中cmd中执行pip install requests 安装requests库件

 

爬baidu网站的程序

1
2
3
4
5
from  urllib.request import urlopen
def get(url):
    return urlopen(url).read()
print(get('http://www.baidu.com'))
print(get('http://www/python.org'))

将上面”爬百度”的程序修改成闭包模式:

1
2
3
4
5
6
7
8
9
from  urllib.request import urlopen
def f1(url):
    def f2():
        print(urlopen(url).read())
    return f2
baidu=f1('http://www.baidu.com')
python=f1('http://www.python.org')
baidu()
python()
posted @ 2017-06-19 16:22  云养猫  阅读(152)  评论(0编辑  收藏  举报