• python学习日记(函数进阶)


    命名空间

    内置命名空间

      存放了python解释器为我们提供的名字:print,input...等等,他们都是我们熟悉的,拿过来就可以用的方法。

      内置的名字在启动解释器(程序运行前)的时候被加载在内存里。

    全局命名空间

      放置了我们设置的所有变量名和函数名。

      是在程序从上到下被执行的过程中依次加载进内存里。

    局部命名空间

      函数内部定义的名字。

      调用函数的时候。才会产生这个名称空间,函数执行结束的时候,这个名称空间就消失(被释放)了。

    使用规则

    在局部:可以使用全局、内置命名空间中的名字

    在全局:可以使用内置命名空间中的名字,但不能使用局部中的名字

    在内置:不能使用全局和局部的名字

      名字局部找不到,往上一级找,再找不到再上一级,内置空间都没有的话,就会引发异常

      自己当前级别有的话,就不去找上一级要了

    一、

    b = '全局'
    def func():
        a = '局部'
        print(b)#内部可以使用全局 b 以及内置 print
    func()
    print(a)#全局不能使用内部

    二、

    当全局定义的名字和内置的名字相同时,会使用全局定义的名字。

    def input(x):
        print('全局函数')
    input('请输入:')

    # def input(x):
    #     print('全局函数')
    input('请输入:')

    附加一:函数名的本质:内存地址

    def input(x):
        print('全局函数')
    def func():
        # input = '局部变量'
        print(input)
    func()
    print(func)
    # 函数名 :指向内存地址(同变量),函数名() :函数的调用

    附加二:多个函数拥有多个独立的局部名字空间,不互相共享

    def hh():
        a = 'hh'
    def kk():
        print(a)#无法使用另一个函数定义的变量
    kk()

    作用域

    概述

    作用域就是做用范围,按照生效范围可以分为局部作用域和全局作用域。

    全局作用域:包含内置名称空间,全局名称空间,在整个文件的任意位置都能被引用,全局有效

    局部作用域:局部名称空间,只能在局部范围内生效

    global

    a = 1
    def kk():
        # global a
        a += 1
        print(a)
    kk()
    #对于不可变数据类型,局部可以查看全局作用域中的变量,但不能直接修改
    #若想修改,需要在程序一开始之前添加 global 声明

    a = 1
    def kk():
        global a
        a += 1
        print(a)
    kk()
    print(a)#全局的也被修改

    补充:出于对代码的安全性考虑,我们应该尽量少的或者不使用global

    a = 1
    def kk():
        a = 2
        return a#利用返回值来代替global
    a = kk()#调用的时候,才会执行函数,不调用就不会影响全局变量 a 
    print(a)

    globals 和 locals

    a = 1
    b = 2
    def hh():
        x = 'happy'
        y = 'day'
        print(globals())#globals() 函数会以字典类型返回当前位置的全部全局变量。
        print(locals()) #locals()  函数会以字典类型返回当前位置的全部局部变量。
    hh()
    print(globals())
    print(locals())

     函数的嵌套

    引子

    比较三个数的大小

    def max(a,b):
        return a if a > b else b
    def bmax(x,y,z):
        c = max(x,y)#函数的嵌套
        return max(c,z)
    print(bmax(1,2,3))

    函数内部调用其他函数,即为函数的嵌套。最常见的为定义一个函数,函数体里面含有print()函数。

    例子

    1、

    def outer():#外部函数
        def inner():#内部函数
            print('inner')
        inner()
    outer()

    2、

    def outer():#外部函数
        a = 1
        def inner():#内部函数
            print(a)#内部函数可以使用外部函数的变量
            print('inner')
        inner()
    outer()

    3、

    def outer():#外部函数
        a = 1
        def inner():#内部函数
            b = 2
            print(a)#内部函数可以使用外部函数的变量
            print('inner')
            def inner2():
                print(a,b)#内部函数可以使用外部函数的变量
                print('inner2')
            inner2()
        inner()
    outer()

    4、global只能修改全局变量

    a =  1#全局变量
    def outer():
        a = 1#局部变量
        def inner():
            b = 2
            print(a)
            def inner2():
                global a#只修改了全局,不能修改局部
                a +=1
            inner2()
        inner()
        print('局部:',a) #局部变量没有被修改
    outer()
    print('全局:',a)#全局变量被修改

    5、nonlocal,修改当前变量最近的一个函数里面的此变量,没有的话继续往上一层找,但不能修改全局变量

      5.1

    a =  1#全局变量
    def outer():
        a = 1#局部变量
        def inner():
            b = 2
            print(a)
            def inner2():
                nonlocal a#只能修改局部,不能修改全局
                a +=1
            inner2()
        inner()
        print('局部:',a) #局部变量被修改
    outer()
    print('全局:',a)#全局变量没有被修改

      5.2

    a =  1#全局变量
    def outer():
        a = 1#不是最近的,不考虑
        def inner():
            a = 1#最近的变量 a,进行修改
            b = 2
            print(a)
            def inner2():
                nonlocal a#只能修改局部,不能修改全局
                a +=1
            inner2()
            print('局部最近',a)#局部变量被修改
        inner()
        print('局部较远:',a) #没有被修改
    outer()
    print('全局:',a)#全局变量没有被修改

    函数名的本质

    一、函数名可以被赋值

    def hh():
        print('yes')
    # hh()
    kk = hh#函数名可以赋值
    kk()
    li = [hh,kk]#函数名可以作为容器类型的元素
    print(li)#函数名就是地址
    for i in li:
        i()

    二、函数名可以作为参数和返回值

    作为返回值和参数

    def hh():
        print('hhhhh')
    def kk(k):
        k() #加上括号就是调用函数
        return k#函数名可以作为返回值
    # hh()
    q = kk(hh) #返回值,返回的是 k ,k 为 hh ,即内存地址
    print(q)
    q()#同下,内存地址加括号,调用函数
    kk(hh)  #hh就是内存地址,函数名可以作为函数参数

    可以当作函数的参数和返回值,即就当普通变量用

    第一类对象(first-class object)指
    1.可在运行期创建
    2.可用作函数参数或返回值
    3.可存入变量的实体
    第一类对象概念

    函数闭包

    定义

    嵌套函数,内部函数调用外部函数的变量。

    调用全局变量不属于闭包。

    可以使用 __closure__ 来判断是否是闭包

    def hh():
        a = 1
        def kk():
            print(a)
        print(kk.__closure__)
    hh()
    print(hh.__closure__)

    闭包函数最常用的用法

    保存函数的状态信息,使函数的局部变量信息依然可以保存下来。

    def hh():
        a = 1
        def kk():
            print(a)
        return kk #返回 kk :函数地址
    x = hh()#调用之后接收返回值,即接收的为地址 kk
    x()#地址加括号,调用

    使得函数hh虽然被调用,但是其局部信息依然被保存,x() 能成功输出为验证。

    举个栗子

    1、

    from urllib.request import urlopen
    sc = urlopen('https://www.baidu.com').read()
    print(sc)

    2、闭包实现

    def get():
        url = 'https://www.baidu.com'
        def get_url():
            sc = urlopen(url).read()
            print(sc)
        return get_url#返回函数名
    arg = get()
    arg()#加括号调用,调用一次,执行一次,保存了局部变量信息

    pass

    作者:Gruffalo
    ---------------------------------------------
    天行健,君子以自强不息
    地势坤,君子以厚德载物
    内容仅为自己做日常记录,备忘笔记等
    真小白,努力学习ing...一起加油吧!(ง •̀_•́)ง
  • 相关阅读:
    strlen和sizeof的区别
    gdb调试多进程和多线程命令
    (转)Mybatis insert后返回主键给实体对象(Mysql数据库)
    mybatis中使用where in查询时的注意事项
    MySQL IFNULL()函数用法MySQL
    (转)Mysql 多表查询详解
    HTTP的请求方法OPTIONS
    (转)跨域的另一种解决方案——CORS(Cross-Origin Resource Sharing)跨域资源共享
    (转)HTML5开发中Access-Control-Allow-Origin跨域问题
    java maven项目找不到jconsole-1.8.0.jar和tools-1.8.0.jar包
  • 原文地址:https://www.cnblogs.com/smallfoot/p/10023226.html
Copyright © 2020-2023  润新知