zoukankan      html  css  js  c++  java
  • 函数嵌套及作用域

    一、函数对象

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

    1、变量值可以被引用,例如 x = 1,y = x

    def foo():
        print('from foo')
    
    f = foo     # 变量值(函数名)被引用
    print(f)
    f()

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

    def foo():
        print('from foo')
    
    def bar(x):
        print(x)
        x()
    
    bar(foo)    # 函数名当作参数传给另外一个函数

    3、变量值可以当作函数的返回值

    def foo():
        print('from foo')
    
    def func(x):
        return x
    
    f = func(foo)   # 函数名当作函数的返回值
    print(f)

    4、变量值可以当作容器类型的元素

    def foo():
        print('from foo')
    
    li = [foo, ]    # 函数名当作列表的元素
    print(li)
    li[0]()
    
    dic = {'1': foo}   # 函数名当作字典的元素
    print(dic)
    dic['1']()

    二、函数嵌套

    1、函数的嵌套定义:在函数内又定义了其他函数

    def func():
        def foo():
            print('from foo')
    
        foo()
        x = 1
        print(x)
    
    func()

    2、函数嵌套调用:在一个函数内部又调用其他函数

    # 比较四个数的大小
    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))
    # 计算圆的面积和周长
    
    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(5, 1)
    print(res)
    计算圆的面积和周长

    三、名称空间

    1、定义:存放名字与值的内存地址绑定关系的地方

    2、名称空间分为三大类:

      内置名称空间:存放的是 Python 解释器自带的名字,Python 解释器的启动则产生,关闭则销毁

      全局名称空间:创建的存储 “变量名与值的关系” 的空间,是在顶级定义的,Python程序执行时产生,程序执行完毕后则销毁

      局部名称空间:在函数的运行中开辟的临时的空间,是在函数内部定义的,在函数调用时临时产生,调用完毕后则销毁

    三种名称空间的加载顺序和取值顺序:

    加载顺序:内置(程序运行前加载)-->全局(从上到下顺序加载进来的)-->局部(调用的时候加载)--->内置

    取值:

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

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

    使用:全局不能使用局部的,局部的可以使用全局的

    四、作用域:就是作用范围

    1、全局作用域

    定义:包含内置与全局名称空间的名字

    特点:在整个程序的任意位置都能被引用,全局有效

    2、局部作用域

    定义:包含局部名称空间的名字

    特点:临时存活,只能在局部范围内生效

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

    # 示范一:
    def f1():
        print(xxx)
    xxx = 111
    
    def f2():
        xxx = 222
        # 不管f1在哪调用, 都是去找定义阶段的作用域关系,
        # 与上面的xxx=222没有任何关系
        f1()
    
    f2()    # 执行结果:111
    # 示范二:
    xxx = 111
    def f1():
        '''
        函数定义阶段只检测语法, 不执行代码
        这里先输出xxx, 先从局部找xxx, 找到了x=222但是却定义在了输出的下面
        语法上这种写法是错误的
        '''
        print(xxx)
        xxx = 222
    
    f1()    # 执行结果报错

    五、闭包函数

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

    包:该内部函数包含了对外层函数作用域中变量的引用 

    def outter():
        x = 1
        def inner():
            print("from inner", x)
        return inner
    
    f = outter()    # 通过外部函数拿到了内部函数的地址
    
    def foo():
        print(f)
        f()
    
    foo()

    为函数体传值的两种方式:

      def foo():

        print('hello %s' %name)

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

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

    这种方式要想多次传值,每次都要手动添加参数

    方式二:闭包含数

    def outter(name):
        def foo():
            print("hello %s" %name)
        return foo
    
    f = outter('qiu')
    f()
    f()
    f()

    要想多次传值只需要多次调用函数即可

    应用:获取一个网页的信息

    # 解决方案一: 以参数的形式传入
    
    def get(url):
        response = requests.get(url)
        if response.status_code == 200:
            print(response.text)
    
    # 要想多次获取信息只能多次传入
    get('https://www.baidu.com')
    get('https://www.cnblogs.com')
    # 解决方案二: 闭包函数无需多次传入
    
    def outter(url):
        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()
    cnblogs()
  • 相关阅读:
    CSRF 攻击原理及防护
    XSS 攻击原理及防护
    git 基础命令大全
    vue3.0 VS vue2.0
    Android eMMC Booting[wiki百科]
    Android Fastboot[wiki百科]
    Android View.onMeasure方法的理解[转]
    某android游戏逆向小记
    Android网络编程—同时上传参数和文件到服务器 [转载]
    apk自我保护的一种实现方式——运行时自篡改dalvik指令【转载】
  • 原文地址:https://www.cnblogs.com/qiuxirufeng/p/9709762.html
Copyright © 2011-2022 走看看