zoukankan      html  css  js  c++  java
  • 函数对象

    函数对象

    函数是第一类对象:即函数可以被当做数据处理。

    def func():
        print('from func')
    
    print(func)
    
    <function func at 0x00B46858>
    

    一、函数对象的四大功能

    1、函数名可以被引用

    def func():
        print('from func')
    
    f = func  # 函数名被引用
    f()  # from func
    

    2、函数名可以被当做参数传递给其他函数

    def func():
        print('from func')
    
    def deco(args):
        print(args)  # <function func at 0x00D66858>
        args()  # from func
        print('from index')  # from index
    deco(func)  # 当做参数传递
    

    3、函数名可以当做其他函数的返回值

    def deco():
        print('from deco')
    
    def func():
        print('func')  
        return deco
    res = func()  # func
    print(res)  # <function deco at 0x00CF6858>
    res()  # from deco
    

    4、函数名可以当做容器类型的元素

    def func():
        print('from func')
    
    print(func())  # None
    
    
    l = [1,2,func,func()]
    print(l)  # [1, 2, <function func at 0x01776858>, None]
    
    def register():
        username = input('username>>>:').strip()
        pwd = input('password>>>>:').strip()
        print(username,pwd)
        print('register....')
    
    def login():
        print('login...')
    
    def transfer():
        print('transfer...')
    
    def shopping():
        print('shopping...')
    
    def pay():
        print('pay....')
    
    func_msg = """
    1 注册
    2 登录 
    3 转账
    4 付款
    q 退出
    """
    func_dict = {
        '1':register,
        '2':login,
        '3':transfer,
        '4':pay,
    }
    while True:
        print(func_msg)
        choice = input('请选择你想要的功能').strip()
        if choice == 'q':
            break
    
        func = func_dict.get(choice)
        if func:
            func()
        else:
            print('你想要的功能暂时没有')
    

    函数的嵌套调用

    函数的调用

    在函数内部调用其他函数,是为了使用函数的功能,将复杂的逻辑简单化。

    def index():
        func()
        print('index')
    def func():
        print('func')
    
    index()
    
    def my_max(x,y):
        if x > y:
            return x
        return y
    
    def my_max4(a,b,c,d):
        res1 = my_max(a,b)
        res2 = my_max(res1,c)
        res3 = my_max(res2,d)
        return res3
    
    print(my_max4(1,6,8,0))  # 8
    

    函数的嵌套

    函数的嵌套是为了用户通过一个函数的操作,实现不同的功能。比如ATM自动取款机。

    def outer():
        x = 1
        print('outer')
        def inner():
            print('inner')
        return inner
    
    res = outer()  # outer
    res()  # inner
    
    func_msg = {
        0:'注册',
        1:'登录',
        2:'购物',
    }
    def all_func(number):
    
        def register():
    
            print('register')
    
        def login():
    
            print('login')
    
        def transfer():
    
            print('shopping')
        func_dict = {
            0:register,
            1:login,
            2:transfer,
        }
        fun_choice = func_dict.get(choice)
        fun_choice()
    while True:
        print(f'请选择{func_msg}')
        choice = int(input('请输入你的选择?>>>>').strip())
        all_func(choice)
    

    名称空间与作用域

    函数内部的函数只能在函数内部调用,不能在函数外部调用。

    def deco():
        def func():
            print('from func')
    
        func()
    
    func()  # name 'func' is not defined
    

    一、名称空间

    简单来说就是存放名字的地方。

    名称空间就是存放变量名与变量值的内存地址的绑定关系的地方。

    要想访问一个变量的值,必须先去名称空间中拿到对应的名字,才能够访问变量的值

    1.1、 内置名称空间

    python解释器提前给你定义好的名字(已经存放到内置名称空间中了),如len、print、int

    生命周期:只要python解释器启动就会生效,关闭python解释器时失效。

    1.2、 全局名称空间

    文件级别的代码

    x = 1
    if 1==1:
        y == 2
    print(y)
    while True:
        z = 3
    

    x,y,z都会放到全局名称空间,if for while,无论嵌套多少层,它们内部创建的名字都是全局名称空间的。

    生命周期:py文件执行时生效,在py文件执行结束后失效。

    1.3、局部名称空间

    函数体内部创建的名字都属于局部名称空间

    生命周期:函数被调用的时候生效,函数运行结束失效。

    1.4、程序的执行顺序(加载顺序)

    名称空间的执行顺序为:内置——全局——局部

    1.5、查找顺序

    查找顺序为:从当前的所在位置开始查找,如果当前所在的位置为局部名称空间,则顺序为:局部——全局——内置

    x = 111
    def f1():
        x = 222
        def f2():
            x = 333
            def f3():
                # x = 444
                def f4():
                    # x = 555
                    print(x)
                # x = 777
                f4()
                x = 777
            f3()
        f2()
    f1()  # free variable 'x' referenced before assignment in enclosing scope
    # x先从f4函数内部开始找,发现没有,就到f3函数内部开始找,发现f4里面有一个x = 777,但是要想传递给x,必须得先执行f4()函数,f4函数内部没有x,就会往外部寻找,一直循环,知道报错。(能看到葡萄但是吃不到葡萄)
    

    函数在定义阶段查找名字的顺序已经被固定了,不会因为函数的调用位置变化而改变。

    x = 111
    def outer():
        def inner():
            print('from inner',x)
        return inner
    f = outer()
    x = 222
    f()  # from inner 222
    # x的查找顺序,先在inner函数内部开始查找,发现没有,之后在外部开始查找,这个外部是x=222
    
    x = 111
    def outer():
        def inner():
            print('from inner',x)
        return inner
    f = outer()
    def func():
        x = 333
        f()
    func()  # from inner 111
    # x的查找顺序,就是outer函数和inner函数执行后,x的查找顺序,发现在外部,x=111
    
    x = 111
    def outer():
        def inner():
            print('from inner',x)
            x = 666666
        return inner
    f = outer()
    f()  # UnboundLocalError: local variable 'x' referenced 
    # x的查找顺序,先从本身开始查找,发现有x=66666,但是取不到。会提示报错
    

    二、作用域

    2.1、全局作用域

    全局作用域:全局有效,全局存活,包含内置名称空间和全局名称空间。

    2.1、局部作用域

    局部作用域:局部有效,临时存储,只包含局部名称空间。

    2.3、注意点

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

    x = 1
    def f1():
        print(x)  # 函数定义阶段,x=1,就已经被固定了。
    
    def f2():
        x = 10
        f1()  # 所以函数无论被如何调用,都是一个整体
    
    f2()
    

    global、nonlocal关键字

    global在局部修改全局的变量、修改的是不可变数据类型。可变数据类型会自动修改,不要用global。

    # 可变数据类型可直接在局部修改全局的变量
    x = []
    def func():
        x.append('嘿嘿嘿')
    
    func()
    print(x)  # ['嘿嘿嘿']
    
    # global 修改局部变量为全局变量
    x = 1
    username = 'jason'
    def func():
        global x,username  # 将局部变量x,username的值999,'egon',修改为全局变量x,username的值
        x = 999
        username = 'egon'
    func()
    print(x)  # x = 999
    print(username)  # username = 'egon'
    
    # nonlocal 修改局部变量为局部变量
    def func():
        x = 1
        def index():
            nonlocal x  # 将局部变量index函数内部的x的值2,修改为局部变量fun函数的x的值
            x =2
        index()
        print(x)
    func()
    

    global:局部修改全局,如果想修改多个,用逗号隔开

    nonlocal:局部修改局部,如果想修改多个,用逗号隔开

    Never,Never,Never give up.
  • 相关阅读:
    单例
    淘宝在数据处理领域的项目及开源产品介绍 | 岭南六少
    数据库垂直拆分,水平拆分利器,cobar升级版mycat
    基于Gtid的mysql主从复制 和 mysql-proxy 读写分离
    几行lua代码计算http包总长度_指甲锉_新浪博客
    使用Lua和OpenResty搭建验证码服务器
    测试比json更快更小的二进制数据传输格式Msgpack [pythono MessagePack 版本]
    使用 HAProxy, PHP, Redis 和 MySQL 轻松构建每周上亿请求Web站点
    nginx+lua+redis实现验证码防采集
    OpenResty(Nginx)+Lua+GraphicsMagick实现缩略图功能 | 琥珀志
  • 原文地址:https://www.cnblogs.com/zuihoudebieli/p/11166470.html
Copyright © 2011-2022 走看看