zoukankan      html  css  js  c++  java
  • 函数对象、嵌套、名称空间与作用域以及闭包函数

    目录:

      函数对象

      函数嵌套

      名称空间/作用域

      闭包函数

      global

    一、函数对象

    函数是第一类对象:指的是函数的内存地址可以像一个变量值一样去使用。(函数的内存地址指向的就是变量值)

    def foo(): #foo=函数的内地址
        print('from foo')

    1.变量值可以被引用

    x=1    #foo=函数的内存地址
    y=x    #将变量值1的地址给y
    
    f=foo
    print(f)       #打印函数的内存地址       
    f()              #调用函数    

    2.变量值可以当做参数传给另外一个函数

    def bar(x):
        print(x)     #打印地址
        x()            #调用foo函数
    
    #foo=函数的内存地址
    bar(foo)  #将foo的内存地址传入bar函数

    3.变量值可以当做函数的返回值

    def func(x):
        return x
    
    f=func(foo)
    print(f)

    4.变量值可以当做容器类型的元素

    l=[foo,]
    print(l)      #[<function foo at 0x0000000002061E18>]
    l[0]()        #调用foo函数
    
    dic={'1':foo}
    print(dic)   #{'1': <function foo at 0x0000000001D11E18>}
    dic['1']()   #调用foo函数 

    变量值当做容器类型元素的应用:

     1 def register():
     2     print('注册....')
     3 
     4 def login():
     5     print('登录....')
     6 
     7 def pay():
     8     print('支付....')
     9 
    10 def transfer():
    11     print('转账....')
    12 
    13 func_dic={
    14     '1':register,
    15     '2':login,
    16     '3':pay,
    17     '4':transfer
    18 }
    19 
    20 # func_dic['1']()
    21 
    22 while True:
    23     print("""
    24     0 退出
    25     1 注册
    26     2 登录
    27     3 支付
    28     4 转账
    29     """)
    30     choice=input('请输入你的操作: ').strip()
    31     if choice == '0':break
    32 
    33     if choice not in func_dic:
    34         print('输错的指令不存在')
    35         continue
    36 
    37     func_dic[choice]()
    View Code

     二、函数的嵌套

    1.函数的嵌套调用:在一个函数的内部又调用其他函数

    #比较1,2,3,4的大小
    def max2(x,y):
        if x > y:
            return x
        else:
            return y
    
    def max4(a,b,c,d):
        res1=max2(a,b)
        res2=max2(res1,c)
        res3=max2(res2,d)
        return res3
    print(max4(1,2,3,4))

     2.函数的嵌套定义:在函数的内部又定义了其他函数

    def func():
        def foo():
            print('from foo')
        print(foo)   #打印foo的地址
        foo()         #调用内部函数
        x=1
        print(x)
    func()

    3.函数嵌套的应用:

    #定义一个关于圆的函数,可以计算面积和周长
    from math import pi
    def circle(radius,action):
        def cal_perimeter():
            return 2 * pi * radius
    
        def cal_area():
            return pi * (radius ** 2)
    
        if action == 1:
            res=cal_perimeter()
        elif action == 2:
            res=cal_area()
        return res
    
    res=circle(10,1)
    print(res)

     三、名称空间与作用域

    1.名称空间Namespaces:指的就是存放名字与值内存地址绑定关系的地方(在内存)

      

     2.名称空间分为三大类

    (1).内置命名空间:存放的是Python解释器自带的名字(变量名和函数名

        产生:python解释器的启动则产生

        销毁:Python解释器关闭则销毁

    (2).全局名称空间:在顶级定义的名字
    x=1    #全局
    if True:
        y=2#全局
    while True:
        while True:
            while True:
                z=3
    def func():
        pass

        产生:执行Python程序时产生

        销毁:Python程序执行完毕则销毁

    (3).局部名称空间:在函数内定义的名字
    def foo():
        m=100     #局部
    foo()

         产生:在函数调用时临时产生

        销毁:在函数调用完毕后则销毁

    3.三种名称空间的产生的先后顺序:内置-->全局-->局部

       查找名字的顺序:从当前位置往外一层一层的查找

          如果当前在局部名称空间:局部-->全局-->内置

          如果当前在全局名称空间:全局-->内置

    len=111
    def foo():
        len=222
        print(len)
    len=111
    foo()    #结果为222
    x=0
    def f1():
        x=1
        def f2():
            x=2
            def f3():
                x=3
                print(x)    #x=3
            f3()
        f2()
    f1()
    
    def foo1():
        def foo2():
            def foo3():
                print(x)    #x=0
         foo3()
      foo2()
    foo1()

     4.作用域:指的是作用范围

    全局作用域:包含内置与全局名称空间的名字

       特点:全局存活,全局有效

    局部作用域:包含局部名称空间的名字

       特点:临时存活,局部有效

    ******作用域的关系在函数定义阶段就已经固定死了,与调用位置无关

     示范一:

    #作用域在定义阶段就已经确定f1找的是全局名称
    def f1():
        print(xxx)
    xxx=111
    def f2():
        xxx=222
        f1()
    f2()
    
    #在定义阶段,f1在局部名称空间找到xxx.运行时候也只会在局部找,但是代码执行时逐行执行,先引用,后定义,所以报错
    def f1():
        print(xxx)#报错
        xxx=111
    def f2():
        xxx=222
        f1()
    f2()

     示范二:

    xxx=111
    def f1():
        print(xxx)#报错,定义时决定了作用域,不会去全局找。执行代码时逐行执行,先引用,后定义,所以报错
        xxx=222
    f1()

    四、闭包函数

    闭包函数=函数对象+函数嵌套定义+作用域

    闭:封闭,指的是该函数时定义一个函数内部的函数

    包:该内部函数包含对外层函数名字的引用

    闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域

    应用领域:延迟计算(原来我们是传参,现在我们是包起来)

    例如:
        从纽约向上海以寄快递的形式邮寄一个人,需要将人放在集装箱内(相当于闭),但是由于时间久,就必然要在集装箱内部提供水,食物等(相当于包)

     示例代码:

    def outter():
        x=1
        def inner():
            print('from inner',x)
        return inner
    f=outter() #相当于 f=inner
    
    def foo():
        # print(f)
        x=111111111111111111111111111111111111
        f()
    foo()    #结果为1

    为函数传值的两种方式:

    def foo():
    print('hello %s' %name)

    方式一:直接以参数形式传入

    def foo(name):
        print('hello %s' %name)
    foo('egon')
    foo('egon')
    foo('egon')

    方式二:闭包函数

    def outter(name):
        # name='egon'
        def foo():
            print('hello %s' %name)
        return foo
    
    f=outter('egon')
    # print(f)
    f()
    f()
    
    f1=outter('alex')
    f1()
    f1()

    爬取数据应用:

    pip3 install requests
    import requests
    
    问题
    def get():
        response=requests.get(url)
        if response.status_code == 200:
            print(response.text)
    
    解决方案一:
    def get(url):
        response=requests.get(url)
        if response.status_code == 200:
            print(response.text)
    
    get('https://www.baidu.com')
    get('https://www.baidu.com')
    get('https://www.baidu.com')
    
    解决方案二:
    def outter(url):
        # url='https://www.baidu.com'
        def get():
            response=requests.get(url)
            if response.status_code == 200:
                print(response.text)
        return get
    baidu=outter('https://www.baidu.com')
    cnblogs=outter('https://www.cnblogs.com')
    baidu()
    baidu()
    baidu()
    cnblogs()
    cnblogs()
    cnblogs()

     五、global

    x=1
    def func():
       x=2    #从内存角度来说,函数内部的局部变量在内存中的地方和全局变量不在一个地方,所以不会发生变量值覆盖
    func()
    print(x)  #结果为1
    
    x=[]
    def func():
       x.append(1)  #从全局找x,x位可变类型,追加
       x.append(2)
       x.append(3)
    func()
    print(x)#结果[1,2,3]
    
    # global: 在局部声明变量是全局变量 x=1 def func(): global x x=2 func() print(x)#结果为2
    # nonlocal:在局部声明变量是外层函数的变量 x=333 def f1(): x=222 def f2(): x=111 def f3(): nonlocal x x=0 f3() print('f2内部的x: ',x)#0 f2() print('这是f1内部的x: ',x)#222 f1() print(x)#333
  • 相关阅读:
    有向图的强连通分量——tarjan
    最小生成树——Kruskal算法
    最小生成树——Prim算法
    递归的正确切入方法
    大整数类概述
    初涉算法——STL初步
    初涉算法——C++
    ACM常用模板
    ACM入门步骤(一)
    划分树
  • 原文地址:https://www.cnblogs.com/xuechengeng/p/9709136.html
Copyright © 2011-2022 走看看