函数二

  1.命名空间和作用域

  2.函数嵌套级作用域链

  3.函数名的本质

  4.闭包

1.命名空间和作用域

  命名空间本质 : 存放名字与值的绑定关系

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

python之禅
View Code

命名空间一共分为三种:

  全局命名空间

    代码在运行开始,创建的存储'变量名与值的关系'叫做全局命名空间

  局部命名空间

    在函数的运行中开辟的临时的空间叫做局部命名空间

  内置命名空间

    存放了python解释器为我们熟悉的,print input len拿过来就可以使用的方法

三种命名空间之间的加载与取值顺序:

  加载顺序:内置命名空间(程序运行前加载) - > 全局命名空间(程序运行中:从上到下加载) - > 局部命名空间(程序原型中: 调用时才加载)

取值:

  在局部调用:局部命名空间 - > 全局命名空间 - > 内置命名空间

x = 1
def f(x):
    print(x)

print(10)

  在全局调用: 全局命名空间 - > 内置命名空间

x = 1
def f(x):
    print(x)

f(10)
print(x)

在全局引用内置max
print(max)

作用域

  作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域

  全局作用域:包含内置名称空间,全局名称空间,在整个文件的任意位置都能被引用,全局有效

  局部作用域:局部名称空间,只能在啊局部范围内生效

  global和nonlocal方法

print(globals())
print(locals())

 

def func():
    a = 12
    b = 20
    print(locals())
    print(globals())

func()

在局部调用globals和locals

关键字global

a = 10
def func():
    global a
    a = 20

print(a)
func()
print(a)

global关键字

函数的嵌套和作用域链

函数的嵌套调用

def max2(x,y):
    m  = x if x>y else y
    return m

def max4(a,b,c,d):
    res1 = max2(a,b)
    res2 = max2(res1,c)
    res3 = max2(res2,d)
    return res3

# max4(23,-7,31,11)

函数的嵌套调用

函数的嵌套定义

def f1():
    print("in f1")
    def f2():
        print("in f2")

    f2()
f1()

函数的嵌套定义(一)
def f1():
    def f2():
        def f3():
            print("in f3")
        print("in f2")
        f3()
    print("in f1")
    f2()
    
f1()

函数的嵌套定义(二)

函数的作用域链

def f1():
    a = 1
    def f2():
        print(a)
    f2()

f1()

作用域链(一)
def f1():
    a = 1
    def f2():
        def f3():
            print(a)
        f3()
    f2()

f1()

作用域链(二)
def f1():
    a = 1
    def f2():
        a = 2
    f2()
    print('a in f1 : ',a)

f1()

作用域链(三)

nonlocal关键字

1.外部必须有这个变量

2.在内部函数声明nonlocal变量之前不能再出现同名变量

3.内部修改这个变量如果想在外部有这个变量的第一层函数中生效

def f1():
    a = 1
    def f2():
        nonlocal a
        a = 2
    f2()
    print('a in f1 : ',a)

f1()

nonlocal关键字

函数名的本质

函数名本质上就是函数的内存地址

1.可以被引用

def func():
    print('in func')

f = func
print(f)

2.可以被当做容器类型的元素

def f1():
    print('f1')


def f2():
    print('f2')


def f3():
    print('f3')

l = [f1,f2,f3]
d = {'f1':f1,'f2':f2,'f3':f3}
#调用
l[0]()
d['f2']()

函数被当作容易类型的元素

3.可以当做函数的参数和返回值

第一类对象(first-class object)指
1.可在运行期创建
2.可用作函数参数或返回值
3.可存入变量的实体。

闭包

例子:

def func():
    name = 'eva'
    def inner():
        print(name)

闭包函数

内部函数包含对外部作用域而非全局作用域名字的引用,该内部函数称为闭包函数

函数内部定义的函数称为内部函数

闭包函数的用法:

def func():
    name = 'eva'
    def inner():
        print(name)
    return inner

f = func()
f()

判断闭包函数的方法__closure__

#输出的__closure__有cell元素 :是闭包函数
def func():
    name = 'eva'
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f = func()
f()

#输出的__closure__为None :不是闭包函数
name = 'egon'
def func2():
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f2 = func2()
f2()

闭包嵌套

def wrapper():
    money = 1000
    def func():
        name = 'eva'
        def inner():
            print(name,money)
        return inner
    return func

f = wrapper()
i = f()
i()

 闭包嵌套

闭包函数获取网络应用

from urllib.request import urlopen

def index():
    url = "http://www.xiaohua100.cn/index.html"
    def get():
        return urlopen(url).read()
    return get

xiaohua = index()
content = xiaohua()
print(content)

闭包函数获取网络应用

小总结:

1.命名空间一共有三种从大到小的范围顺序:内置命名空间,全局命名空间,局部命名空间

2.作用域(包含函数的作用域链):

  1.小范围可以用大范围的

  2.但是大范围的不能用小范围的

  3.范围从小到大

  4.从小范围内如果要用一个变量,是当前这个小范围有的,就用自己的

  5.如果在小范围内没有,就用上一级的,上一级没有就用上上一级的,以此类推

  6.如果没有就报错

3.函数的嵌套:

  1.嵌套调用

  2.嵌套定义:定义在内部的函数无法直接在全局被调用

4.函数名的本质:

  就是一个变量,保存了函数所在的内存地址

5.闭包:

  内部函数包含外部作用域而非全局作用域名字的引用,该内部函数称为闭包函数

原文地址:https://www.cnblogs.com/LLBFWH/p/9916210.html