zoukankan      html  css  js  c++  java
  • DAY10-Python入门学习-函数的对象与嵌套、名称空间与作用域、闭包函数

    一、函数的对象

    函数是第一类对象,指的是函数名指向的值(函数)可以被当作数据去使用

    def func():# func=函数的内地址
      print('from func')
    
    print(func)
    
    age=10
    #1. 可以被引用
    x=age
    print(x,age)
    
    f=func
    print(f)
    f()
    
    #2. 可以当作参数传给另外一个函数
    def bar(x):
      print(x)
    
    bar(age)
    bar(func)
    
    #3. 可以当作一个函数的返回值
    def bar(x):
      return x
    
    res=bar(age)
    print(res)
    
    res=bar(func)
    print(res)
    
    #4. 可以当作容器类型的元素
    l=[age,func,func()]
    print(l)

    二、函数的嵌套

    1.函数嵌套分为两大类

    1.1函数的嵌套调用:在调用一个函数过程中,其内部代码又调用了其他函数

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

    1.2函数的嵌套定义:一个函数内部又定义了另外一个函数

    案例一

    def outter():
        x=1
        print('from outter')
        def inner():
            print('from inner')
        print(x)
        print(inner)
    
    outter()
    #from outter
    #1
    #<function outter.<locals>.inner at 0x000001D175B7CB70>
    
    inner()#无法在外部调用内部函数

    案例二

    def f1():
        print('from f1')
        def f2():
            print('from f2')
            def f3():
                print('from f3')
            f3()
        f2()
    f1()
    #from f1
    #from f2
    #from f3

    案例三

    from math import pi
    print(pi)#3.141592653589793
    
    def circle(radius,action=0):
        """
        圆形相关运算
        :param radius: 半径
        :param action: 0代表求面积,1代表求周长
        :return: 面积或者周长
        """
        def area(radius):
            return pi * (radius ** 2)
    
        def perimiter(radius):
            return 2 * pi * radius
    
        if action == 0:
            res=area(radius)
        elif action == 1:
            res=perimiter(radius)
    
        return res
    
    
    print(circle(10,0))#314.1592653589793
    print(circle(10,1))#62.83185307179586

    三、名称空间与作用域

    1 什么是名称空间namespace


    名称空间就是用来存放名字与值内存地址绑定关系的地方(内存空间)

    age=18
    但凡查找值一定要通过名字,访问名字必需去查找名称空间


    2 名称空间分为三大类


    2.1内置名称空间

    存放的是python解释器自带的名字
    例如:
    len
    max
    print

    2.2全局名称空间

    存放的是文件级别的名字
    例如:以下名字中xyzfoo都会存放于全局名称空间中

    x=1
    y=2
    if x == 1:
        z=3
    
    while True:
        b=4
        break
    
    def foo():
      m=3

    2.3局部名称空间

    在函数内定义的名字
    例如:
    foo内的m这个名字一定是存放于一个局部名称空间中


    2.4生命周期

    内置名称空间:在解释器启动时则生效,解释器关闭则失效
    全局名称空间:在解释器解释执行python文件时则生效,文件执行完毕后则失效
    局部名称空间:只在调用函数时临时产生该函数的局部名称空间,改函数调用完毕则失效

    2.4加载顺序

    内置->全局->局部

    2.5查找名字的顺序

    基于当前所在位置往上查找
    假设当前站在局部,查找顺序:局部->全局->内置
    假设当前站在全局,查找顺序:全局->内置

     案列一:

    len=111
    
    def foo():
        len=222
        print(len)
    
    foo()
    print('站在全局找len: ',len)

    案例二

    x=111
    
    def f1():
        x=222
        def f2():
            def f3():
                x=444
                print(x)#444
            x=333
            f3()
        f2()
    f1()    

    (******)名字的查找顺序,在函数定义阶段就已经固定死了(即在检测语法时就已经确定了名字的查找顺序),与函数的调用位置无关,也就是说无论在任何地方调用函数,都必须回到
    当初定义函数的位置去确定名字的查找关系

    案列三:

    x=111
    def outer():
        def inner():
            print('from inner',x) # x访问的时全局名称空间中x
        return inner
    f=outer()
    
    x=222
    f()#222

    案列四:

    x=111
    def outer():
        def inner():
            print('from inner',x) # x访问的时全局名称空间中x
        return inner
    
    f=outer()
    
    # x=222
    def func():
        x=333
        f()
    
    x=444
    
    func()#444


    案列五:

    x=111
    def outer():
        def inner():
            print('from inner',x) # x是来自于当前层的名字,但是此时的x并未定义
            x=2222222222
        return inner
    
    f=outer()
    
    f()


    3.作用域:

    域指的是范围,作用域指的就是作用的范围,分为两种
    全局作用域:包含的是内置名称空间与全局名称空间中的名字
    特点:全局有效,全局存活

    局部作用域:包含的是局部名称空间中的名字
    特点:局部有效,临时存活

    案例一

    x=1#全局存活
    
    def foo():
        y=2
        print(x)#1
    
    def bar():
        print(x)#1
    
    foo()
    bar()

    案例二

    x=1
    def foo():
        x=2#局部有效
    foo()
    print(x)#1

    案例三

    l=[]#这个l是存放在全局空间
    def foo():
        l.append(1)#报错,在局部名称空间中没有l
        l=33333
    foo()
    print(l)

    global:在局部声明一个名字是来自于全局作用域的,可以用来在局部修改全局的不可变类型

    x=1
    def foo():
        global x
        x=2
    foo()
    print(x)#2

    nonlocal:声明一个名字是来自于当前层外一层作用域的,可以用来在局部修改外层函数的不可变类型

    x=0
    def f1():
      x=111
      def f2():
        nonlocal x#只能修改当前函数的外面一层而已
        x=222
      f2()
      print(x)#222
    
    f1()
    print(x)#0

    四、闭包函数

    1 什么是闭包函数

    闭:指的是闭包函数是定义在一个函数内部的函数
    包:该内部函数包含对外层函数作用域名字的引用

    需要结合函数对象的概念将闭包函数返回到全局作用域去使用,从而打破函数的层级限制

    def outter():
      x=111
      def inner():
        print(x)
      return inner
    
    f=outter() #f=outter内的inner


    2 为何要用闭包函数

    闭包函数提供了一种为函数体传值的解决方案

    3 如何用闭包函数


    3.1为函数体传值的方式一:参数

    def func(x,y):
      print(x+y)
    func(1,2)

    3.2为函数体传值的方式二:闭包

    def outter(x,y):
        def func():
            print(x+y)
        return func
    
    f=outter(1,2)
    f()


    3.3案例

    需求
    def get():
      response=requests.get(url)
      if response.status_code == 200:
        print(response.text)


    解决方案一:参数

    pip3 install requests
    
    import requests
    def get(url):
      response=requests.get(url)
      if response.status_code == 200:
        print(len(response.text))
    
    get('https://www.baidu.com')
    get('https://www.baidu.com')
    get('https://www.baidu.com')
    get('https://www.tmall.com')
    get('https://www.tmall.com')
    
    url1='https://www.baidu.com'
    url2='https://www.tmall.com'
    
    get(url1)
    get(url1)
    get(url1)
    
    get(url2)
    get(url2)
    get(url2)


    解决方案二:闭包

    def outter(url):
        # url='https://www.baidu.com'
        def get():
            response=requests.get(url)
            if response.status_code == 200:
                print(len(response.text))
        return get
    
    baidu=outter('https://www.baidu.com')
    
    
    tmall=outter('https://www.tmall.com')
  • 相关阅读:
    Android Gradle Plugin指南(五)——Build Variants(构建变种版本号)
    文件内容操作篇clearerr fclose fdopen feof fflush fgetc fgets fileno fopen fputc fputs fread freopen fseek ftell fwrite getc getchar gets
    文件操作篇 close creat dup dup2 fcntl flock fsync lseek mkstemp open read sync write
    嵌入式linux应用程序调试方法
    version control system:git/hg/subversion/cvs/clearcase/vss。software configruation management。代码集成CI:Cruisecontrol/hudson/buildbot
    最值得你所关注的10个C语言开源项目
    如何记录linux终端下的操作日志
    CentOS 5.5 虚拟机安装 VirtualBox 客户端增强功能
    sizeof, strlen区别
    C/C++嵌入式开发面试题
  • 原文地址:https://www.cnblogs.com/xvchengqi/p/9398029.html
Copyright © 2011-2022 走看看