函数二----函数的进阶

一、命名空间(有三种)

  1.内置的命名空间   -----python解释器

    就是python解释器一启动就可以使用的名字存储再内置的命名空间中

    内置的名字在启动解释器的时候被加载进内存里。

  2.全局命名空间    -----我们写的代码,但不是函数中的代码

    是在程序从上到下被执行的过程中依次加载进内存的

    放置了我们设置的所有变量名和函数名

  3.局部命名空间   -----函数

    就是函数内部定义的名字

    当调用函数的时候,才会产生这个名称空间,随着函数执行的结束,这个命名空间就又消失了

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

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

#在局部:可以使用全局、内置命名空间中的名字
#在全局:可以使用内置命名空间中的名字,但是不能用局部中命名空间中的名字
#在内置:不能使用全局、局部命名空间中的名字
def func():
    a = 1
func()
print(a)   #因为全局没有a这个变量,它不可能去找func函数里的这个a变量,所以会报错
#在正常情况下,直接使用内置的名字
#当我们在全局定义了和内置名字空间中同名的名字时,会使用全局的名字
#当我自己有的时候,我就不找我的上级要了
#如果自己没有,就找上一级要,上一级没有再找上一级,如果内置的名字空间都没有,就报错
#多个函数应该拥有多个独立的局部命名空间,不互相共享
def input():
    print('in input now')

def func():
    # input = 1
    print(input)
func()    # <function input at 0x0000028967220378>  ---函数的内存地址()

#func  ---> 函数的内存地址
#函数名()  --->函数的调用
#函数的内存地址()   --->函数的调用

二、作用域

#全局作用域  ---作用在全局 ---内置和全局名字空间中的名字都属于全局作用域---globals()
#局部作用域 --- 作用在局部 --- 函数(局部名字空间中的名字属于局部作用域)---locals可以查看
a = 1
def func():
    return a
print(func())  # 1

a = 1
def func():
    global a
    a += 1
func()
print(a)  #2
func()
print(a)  #3

a = 1
def func(a):
    a = 2
    return a
a = func(a)
print(a)  #2
#对于不可变数据类型,在局部可以查看全局作用域中的变量,但是不能直接修改
#如果想要修改,需要在程序的一开始添加global声明
#如果在一个局部(函数)内声明了一个global变量,那么这个变量在局部的所有操作将对全局变量有效
a = 1
b = 2
def func():
    x = 'aaa'
    y = 'bbb'
    print(locals())  # {'x': 'aaa', 'y': 'bbb'}
    print(globals())

func()
print(globals())
print(locals())  #本地的,放在全局,全局就是本地;放在局部,局部就是本地
#globals  永远打印全局的名字
#locals 输出什么,根据locals所在的位置

三、函数的嵌套及作用域链

  函数的嵌套使用
def max(a,b):
    return a if a > b else b
def the_max(x,y,z):
    c = max(x,y)
    return max(c,z)
print(the_max(1,2,3))   # 3

  函数的嵌套定义

def outer():
    def inner():
        print('inner')
    inner()
outer()  #inner
 内部函数可以使用外部函数的变量
def outer():
    a = 1
    def inner():
        b = 2
        print(a)
        print('inner')
        def inner2():
            print(a,b)
            print('inner2')
        inner2()
    inner()
outer()
def outer():
    a = 1
    def inner():
        b = 2
        print(a)
        print('inner')
        def inner2():
            nonlocal a #声明了一个上面层离它最近的一个局部变量
            a += 1   #不可变数据类型的修改
            print('inner2')
        inner2()
    inner()
outer()

#nonlocal  只能用于局部变量,找上层中离当前函数最近一层的局部变量,内部声明了nonlocal的内部函数的变量修改会影响到离当前函数最近一层的局部变量
#nonlocal  对全局无效,对局部也只是对最近含有此变量的一层有影响
a = 1
def outer():
    a = 10
    def inner():
        # a = 20
        def inner2():
            nonlocal a
            a += 1
        inner2()
        print('**a** :',a)
    inner()
    print('##a## :',a)
outer()
print('全局:',a)
#在内部函数使用变量的时候,是从小局部到大局部到内置名字的过程,
# 一级一级往上找,找到最近的一个就使用----作用域链

四、函数名的本质

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

  1.可以被引用

def func():
    print('in func')
f = func
print(f)  #<function func at 0x0000017628CD0378>

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

def f1():
    print(1)
def f2():
    print(2)
def f3():
    print(3)
l = [f1,f2,f3]
d = {'f1':f1,'f2':f2,'f3':f3}
l[0]()  # 1
d['f3']()  # 3

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

def func():
    print(123)
def wahaha(f):
    f()
wahaha(func)   #函数名可以作为函数的参数


def func():
    print(123)
def wahaha(f):
    f()
    return f    #函数名可以作为函数的返回值
qqxing = wahaha(func)

五、闭包

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

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

  判断闭包函数的方法__closure__

  

def outer():
    a = 1
    def inner():
        print(a)
    print(inner.__closure__)
outer()
print(outer.__closure__)


# def outer():
#     a = 1
#     def inner():
#         print(a)
#     return inner
# inn = outer()
# inn()
import urllib #模块
from urllib.request import urlopen
def get_url():
    url = 'http://www.xiaohua100.cn/index.html'
    def inner():
        ret = urlopen(url).read()
        print(ret)
    return inner
get_func = get_url()
get_func()
View Code
原文地址:https://www.cnblogs.com/huangjm263/p/8125773.html