欢迎来到Louis的博客

人生三从境界:昨夜西风凋碧树,独上高楼,望尽天涯路。 衣带渐宽终不悔,为伊消得人憔悴。 众里寻他千百度,蓦然回首,那人却在灯火阑珊处。
扩大
缩小

函数对象、函数嵌套、名称空间与作用域

一. 函数对象

#函数是第一类对象,函数是第一类对象可以被传递
1.可以被引用
2.可以当作参数被传递
3.返回值可以是函数
4.可以作为容器对象的元素
def func1():
    print("hello,world!")

f = func1
f()
函数被其他变量引用
def func1():
    print("hello,world!")

def func2(f):
    tmp_f = f
    tmp_f()

func2(func1)
函数作为参数传递
def outer():
    def inter():
        print("hello, world")
    return inter

b = outer()
b()
函数作为返回值传递
def outer():
    def inter():
        print("hello, world")
    return inter


a = [1,2,3, outer]
a[3]()()                #a[3]()得到inter函数,再加个括号就是调用inter
函数作为容器对象的元素

二. 函数的嵌套

1. 函数的嵌套调用

def sum_(lst):
    for i,v in enumerate(lst):
        lst[i] = v + 10

def is_num(lst):
    for i in lst:
        if not isinstance(i, int):
            return None
    else:
        sum_(lst)
    return lst


a = [1, 2, 3, 4, 5, 6]
print(is_num(a))




def max(x,y):
    return x if x>y else y

def max4(a,b,c,d):
    ret = max(a,b)
    ret2 = max(ret,c)
    ret3 = max(ret2,d)
    return ret3

print(max4(1,2,3,4))
函数嵌套调用

2. 函数的嵌套定义

def outer():
    def inner():        #二层嵌套
        print("inner")
        def inner2():   
            print("inner")
        inner2()
    inner()
嵌套定义

三. 名称空间和作用域

1.什么是名称空间

#名称空间:存放名字的地方,三种名称空间,内部名称空间,全局名称空间,局部名称空间,
(之前遗留的问题x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方)

#内置的命名空间-------python解释器
    就是Python解释器已启动就可以使用的名字,存储在内置命名空间中
    内置的名字在启动解释器的时候被加载进内存里
#全局命名空间--------在函数外定义的,
    是在程序从上到下被执行的过程中依此加载进内存的
    放置了我们设置的所有变量名和函数名
#局部命名空间---------函数
    定义在函数内部的名字
    当调用函数的时候,才会产生这个命名空间,随着函数的调用结束,这个命名空间就消失了。

2.名称空间加载顺序

python test.py
#1.python启动解释器,首先加载的是内置名称空间
#2.执行test.py,以文件为基础,加载全局名称空间
#3.程序运行时,加载函数,会临时加载局部名称空间

3.名字的查找顺序

#局部 > 全局 > 内置
在局部
    可以使用全局,内置命名空间中的名字
在全局
    可以使用内置命名空间中的名字,不能使用局部命名空间中的名字
在内置
    不能使用局部和全局命名空间中的名字

4.作用域

#1. 作用域就是范围
        - 全局范围(内置名称空间和全部命名空间属于这个范围):全局存活,全局有效
        - 局部范围(局部名称空间属于这个范围):函数调用时临时存活,结束销毁,局部有效

全局作用域-------------globals()#查看全局作用域的名字
    作用在全局,内置和全局命名空间中的名字都属于全局作用域
局部作用域------------locals() # 查看局部作用域的名字
    作用在局部,函数(局部命名空间中的名字属于局部作用域)

#2.注意事项
对于不可变数据类型,在局部可以查看全局作用域中的变量
但是不能直接修改
如果想要修改,需要在程序的一开始添加global声明
如果在一个局部(函数)内声明了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效。
不要随意使用gloabl!

#3、查看作用域:globals(),locals()
globals() 永远打印全局的名字
loacls() 输出什么,取决于loacls所在的位置。
LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
locals 是函数内的名字空间,包括局部变量和形参
enclosing 外部嵌套函数的名字空间(闭包中常见)
globals 全局变量,函数定义所在模块的名字空间
builtins 内置模块的名字空间

5. global和nonlocal关键字

global
#只会影响全部变量,不会影响局部变量
nonlocal
#只能用于局部变量,找上层中离当前函数最近一层的局部变量
#声明了nonlocal的内部函数的变量修改会影响到离当前最近一层的局部变量
a = 1
def outer():
    a = 2
    def inner():
        print("inner:",a)
        def inner2():
            nonlocal a      #nolocal关键字定义之后,会影响上层局部作用域中的a,如果上层中没有a,会继续往上层找。
            a+=1
            print("inner2:",a)
        inner2()
    inner()
    print("outer:",a)
outer()
print("global",a)

#结果
i#nner: 2
#inner2: 3
#outer: 3
#global 1
nonlocal实例
a = 1
print("global1:",a)
def func1():
    a = 2
    print("func1:",a)
    def func2():
        global a
        a += 3
        print("func2:",a)
    func2()
func1()
print("global2:",a)
global关键字实例

四. 闭包函数

1.什么是闭包

#内部函数包含外部作用域且非全局作用域的引用

def counter():
    n = 0
    def add():
        nonlocal n
        x = n
        n += 1
        return x
    return add

c = counter()
print(c())
print(c())
print(c())

2. 闭包的应用与意义

#闭包的意义,返回的函数对象,已经不仅仅是普通的对象了,该函数还包含着外层的一个作用域,使函数在何处调用都是使用自己外层包裹的作用域

from urllib.request import urlopen

def index(url):
    def get():
        return urlopen(url).read()
    return get

url = "http://www.baidu.com"
f = index("http://www.baidu.com")
print(f().decode("utf-8"))

posted on 2018-08-05 17:50  Louiszj  阅读(98)  评论(0编辑  收藏  举报

导航