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')
  • 相关阅读:
    EBS中的采购单据状态及其控制
    详解EBS接口开发之采购接收&退货处理之关键API--(补充)
    数据挖掘系列
    如果看了这篇文章你还不懂傅里叶变换,那就过来掐死我吧
    机器学习中的数学
    一个机器学习博客 ,包括 Standford公开课machine learning
    机器学习流行算法一览
    java se 另一博客
    java 正则
    java map
  • 原文地址:https://www.cnblogs.com/xvchengqi/p/9398029.html
Copyright © 2011-2022 走看看