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

    1、函数对象

    #函数是第一类对象的含义是函数可以被当作数据处理----------所以函数即变量这么一说
    
    # def func(): #func=<function func at 0x0584BA50>  #变量名对应的就是一个内存地址
    #     print('from func')
    #
    # print(func)
    
    #
    # x='hello'
    # #1、引用
    # y=x         #变量x可以被y引用
    # f=func      #函数名func也类似于变量名可以被f引用
    # print(f)
    # f()         #f对应的是内存地址,所以加括号就会被调用
    
    
    #2、当作参数传给一个函数
    # len(x)
    # def foo(m):
    #     print(m)  #打印的是函数的变量名即该函数的内存地址,<function func at 0x000001FDC6813BF8>
    #     m()         #内存地址传给m,所以加括号即能被调用
    #
    # foo(func)
    
    
    #3、可以当作函数的返回值
    def foo(x): #x=func
        return x #return func   #当调用函数foo时,会将函数名func返回,即func的内存地址返回
    
    res=foo(func)
    print(res)
    res()
    
    #4、可以当作容器类型的元素
    # l=[x,]         #变量名可以放进一个容器中
    # l=[func,]      #韩说明同样可以刚入到一个容器中
    # # print(l)
    #
    # l[0]()       #从容器中取出函数名,加括号即调用该函数
    
    
    # 函数对象的应用场景
    def pay():
        print('支付。。。')
    
    def withdraw():
        print('取款。。。')
    
    def transfer():
        print('转账。。。')
    
    def check_balance():
        print('查看余额。。。')
    
    
    def shopping():
        print('购物。。。')
    #将函数名放到容器中
    func_dic={
        '1':pay,
        '2':withdraw,
        '3':transfer,
        '4':check_balance,
        '6':shopping
    }
    
    while True:
        msg="""
        1 支付
        2 取款
        3 转账
        4 查看余额
        5 退出
        6 购物
        """
        print(msg)
        choice=input('>>: ').strip()
        if choice == '5':break
        if choice not in func_dic:
            print('输入的指令不存在傻叉')
            continue
        func_dic[choice]()

    2、函数嵌套

    #函数的嵌套定义
    # def f1():
    #     def f2():        #在函数内部在嵌套一个或多个函数
    #         print('from f2')
    #     f2()
    # f1()
    
    
    
    #函数嵌套的应用
    
    # from math import pi
    #定义一个圆的函数,嵌套的好处,每次想只想圆相关的功能(算圆的面积和圆的周长),直接调用圆就可以了
    # def circle(radius,action='area'): #radius=10
    #     def area():
    #         return pi * (radius ** 2)
    #
    #     def perimeter():
    #         return 2 * pi * radius
    #
    #     if action == 'area':
    #         return area()    #外层函数调用直接拿到计算面积函数名并调用,通过返回值调用计算面积的函数,并拿到计算面积的最终结果
    #     elif action == 'perimeter':
    #         return perimeter()
    
    # print(circle(10))
    # print(circle(10,action='perimeter'))
    
    
    
    
    
    #函数的嵌套调用
    # def max2(x,y):
    #     if x > y:
    #         return x
    #     else:
    #         return y
    #
    # def max4(a,b,c,d):       #每次计算两个值得大小,不用重新写if判断,减少代码冗余
    #     res1=max2(a,b)       #将函数嵌套在max4中进行调用,通过调用max4间接的调用max2函数进行比较大小
    #     res2=max2(res1,c)    #拿到两者中较大的值,在与下一个值进行一决高下
    #     res3=max2(res2,d)
    #     return res3          #要通过return将比较大小中最大的结果返回,否则调用的时候结果为None
    #
    # print(max4(1,2,3,4))

    3、函数的名称空间与作用域

    '''
    
    
    1、名称空间namespaces
        存放名字与值绑定关系的地方
    
    2、名称空间分为三大类
        内置名称空间:
            作用:存放python解释器自带的名字
            生命周期:
                在解释器启动时生效,在解释器关闭时失效
    
        全局名称空间:
            作用:除了内置的与局部的名字外,其余都是全局名字
            生命周期:
                在文件执行时生效,在文件执行完毕时失效
    
            例如:x,func,y,l,z都是
                x=1
                def func():
                    a=1
    
                y=2
                l=[1,2]
    
                if 3 > 2:
                    if
                        if
                            if
                                z=3  #if内套一万层其也是全局名称空间。。。。。。
        局部名称空间:
            作用:用于存放函数调用期间函数体产生的名字
            生命周期:
                在文件执行过程
                如果调用了某个函数才会临时生效,在函数执行完毕后失效
    
        三种名称空间的加载顺序是:
            内置-》全局-》局部
    
        名称空间就是用来存放名字与值的绑定关系的,所以但凡要查找名字
        一定是从三者之一找到,查找顺序:
            从当前所在的位置倒着查找,如果当前所在的位置是局部名称空间,
            则查找顺序是:
                局部-》全局-》内置
    
    3、作用域: #----------------本质就是对名称空间的进一步的分类,并没有增加新的知识点
        域指的是区域、范围,作用域即作用的范围
    
        全局作用范围,全局作用域(内置名称空间与全局名称空间)
            全局有效,全局存活
        局部作用范围,局部作用域(局部名称空间)
            局部有效,临时存活
    
    '''
    
    x=1
    # len=100
    def func():
        y=2
        # len=1000
        print(len)  #从当前开始找,有会打印en=1000,将len=1000注释掉,局部没有回去全局找len=100,全局注释掉会去内置找,内置有会打印<built-in function len>
        # print(a)  #从当亲开始找,一直找到内置都没有找到,就会报错-------NameError: name 'a' is not defined
    # func()
    
    # print(len)      #全局直接打印,会到内置中去找,结果是<built-in function len>
    
    
    # def func():
    #     y=2
    #     print(x)
    #
    # x=1           #全局名称空间,存放全局的名字与全局值得绑定关系的地方,值有存放的地方,名字也有自己存放的地方
    # func()        #在函数定义阶段,x=1已经被定义,所以调用func时,局部没有回到全局找,最终调用打印结果为1
    # x=10
    
    
    
    # x=1
    # def f1():
    #     def f2():
    #         def f3():
    #             zzz=333
    #             print(x)   #自己没有,从自己开始往上找,f2中有所以就不会再往上找,所以打印结果是22222
    #         x = 22222
    #         f3()
    #     # x=111111
    #     f2()
    # #
    # def bar():
    #     print(x)     #自己没有去全局找,所以打印结果是1
    #
    # f1()
    # bar()
    
    
    # 作用域关系是在函数定义阶段就固定死了,但凡调用函数都需要跑到定义阶段去找作用域关系
    # x=1
    # def f1():
    #     print(x)  #在调用函数f1时,x已经被改成了x=1000000000000000000000000000000,所以调用结果为x=1000000000000000000000000000000
    #
    # f1()
    # x=1000000000000000000000000000000
    # def f2():
    #     # print(f1)
    #     x=11111111111111111
    #     f1()
    #
    # f2()
    
    
    
    #函数对象+作用域:******----------(***重点***)
    def f1():
        x=1
        def inner():
            print('from inner',x)
        return inner     #函数对象可以当做返回值,将内部的函数名返回到外部,打破层级的限制
    
    f=f1()   #调用f1拿到返回的结果即内部函数inner即inner的内存地址,内存地址加括号就可以被调用
    print(f) #打印的是f1内部函数inner的内存地址------------<function f1.<locals>.inner at 0x000002709B7C3BF8>
    def bar():
        x=111111111111111111111111111111111111111111111
        f()     #打破层级的限制,函数f1外部,即bar函数内部调用f1内部的函数inner,f本质就是inner,加括号即调用,但凡调用都要回到定义阶段去找定义关系
    
    bar()
    
    
    #
    # x=1
    # def foo():
    #     global x #将x声明为全局变量,会将全局的变量x=1改为x=2
    #     x=2
    #
    # foo()
    # print(x)      #已经将x=1声明为x=2了,所以调用后打印结果即为2
    
    
    #
    # x=1           #x为不可变的全局变量,如果要想修改他,就需要借助glabal将函数内部的x声明为全局变量
    # def f1():
    #     def f2():
    #         x=22222222
    #         def f3():
    #             global x     #任然是将x=11111111111111111声明为全局变量,所以并不会影响到局部其他的变量x的值
    #             x=11111111111111111
    #         f3()
    #     f2()
    #
    # f1()
    # print(x)                #打印结果任然为11111111111111111
    
    
    # x=1
    # def f1():
    #     # x=33333
    #     def f2():
    #         # x=22222222               #没有被注释时,会被声明为 x=2000000000
    #         def f3():
    #             nonlocal x           #将局部变量  x=20000000000声明为局部的名称空间,如果局部没有与之对应放入变量就会报错,即# x=22222222和  # x=33333就会报错
    #             x=20000000000
    #         f3()
    #         print(x)
    #     f2()
    #
    # f1()
    # print(x)
    
    
    
    # 在局部如果想要修改全局的可变类型,不需要借助任何声明,可以直接修改
    # 在局部如果想要修改全局的不可变类型,需要借助global声明,声明为全局的变量就可以直接修改了
    
    # x=[]
    # def f1():
    #     x.append(1)    #修改全局的可变类型x=[],不需要借助任何声明,就可以完成对x=[]的修改
    # f1()
    # f1()
    # print(x)
  • 相关阅读:
    convex hull
    不努力,你就没有资格谈天赋
    “数数”的感悟
    平行四边形法则的感悟
    ansys 15 Linux 安装问题
    SHV-E210S 刷4.3
    fedora 安装 Oracle11g 遇到的问题
    ObjectArx开发常用资料
    MFC入门(二)
    MFC入门(三)
  • 原文地址:https://www.cnblogs.com/sui776265233/p/9150995.html
Copyright © 2011-2022 走看看