zoukankan      html  css  js  c++  java
  • 函数进阶-名称空间

    一、形参角度

    万能参数*args和**wkargs

    一个*可以接受所有的实参。

    *args,约定俗称:args

    函数定义时,*代表聚合。他将所有的位置参数聚合成一个元组,赋值给了args

    def eat(*args):
        print(args, type(args))
        print('我请你吃,%s,%s,%s' % args)
        
    eat('小吃', '泡面', '熊掌')
    # 输出:
    ('小吃', '泡面', '熊掌') <class 'tuple'>
    我请你吃,小吃,泡面,熊掌

    函数的定义时:两个**将所有的关键字参数聚合到一个字典中,将这个字典赋值给了kwargs

    def func(**kwargs):
        print(kwargs)
    ​
    func(name='小杨',age='22')
    # 输出:
    {'name': '小杨', 'age': '22'}

    形参角度的参数的顺序:*args的位置?

    args得到实参的前提,sex必须被覆盖了,如果放在所有形参之前,就会导致args获取全部的参数,形参获取不到参数。所以要放在形参的默认关键字参数之间。

    def func(a, b, sex='', *args):    如:def func(a, b, *args,sex=''):
        print(a, b)
        print('sex:', sex)
        print(args)
    ​
    func(1, 2, 3, 4, 5, 6, 7)
    # 输出:
    1 2
    sex: 3
    (4, 5, 6, 7)

    形参角度的参数的顺序:**kwargs的位置要放在形参的默认关键字之后,不然kwargs就会获取所有的关键字参数,导致默认关键字参数就没有意义了,就直接报错。

    def func(a, b, *args, sex='', **kwargs):
        print(a, b)
        print('sex:', sex)
        print(args)
        print(kwargs)
    ​
    func(1, 2, 3, 4, 5, 6, 7,name='小杨',age=22)
    ​
    # 输出:
    1 2
    sex: 男
    (3, 4, 5, 6, 7)
    {'name': '小杨', 'age': 22}

    *的魔性用法

    * **在函数的调用时,*代表打撒。(只要是可迭代对象)

    def func(*args):
        print(args)  # 需要这样时(1,2,3,22,33)
    ​
    func([1, 2, 3], [22, 33])   # 正常情况下
    func(*[1, 2, 3], *[22, 33])  # 相当于  func(1,2,3,22,33)
    # 输出:
    ([1, 2, 3], [22, 33])
    (1, 2, 3, 22, 33)

    **代表打撒字典,(仅限于字典)

    def func(*args, **kwargs):
        print(args)
        print(kwargs)
    ​
    func({'name': '小杨'}, {'age': 22})
    print('-----------------')
    func(**{'name': '小杨'}, **{'age': 22})  # 相当于  func(name = '小杨‘, age = 22)
    # 输出
    ({'name': '小杨'}, {'age': 22})
    {}
    -----------------
    ()
    {'name': '小杨', 'age': 22}

    仅限关键字参数(了解)

    形参角度的第四个参数:仅限关键字参数。只能写在*args和**kwargs之间的关键字参数。不是位置参数,必须以关键字参数传值。

    形参的最终顺序

    形参角度最终的顺序:位置参数,*args,默认参数,仅限关键字参数(默认参数和仅限关键字参数位置可以互换的),**kwargs。

    def func(a, b, *args, sex='', hobby, **kwargs):  # hobby是仅限关键字参数
        print(a, b)                                   # 而且必须传值
        print(args)
        print('sex:', sex)
        print('hobby', hobby)
        print(kwargs)
    ​
    func(1, 2, 3, 4, 5, 6, 7,name='小杨',age=22, hobby='篮球')
    # 输出
    1 2
    (3, 4, 5, 6, 7)
    sex: 男
    hobby 篮球
    {'name': '小杨', 'age': 22}

    在函数定义的时候代表聚合,在函数的执行的时候代表打撒

    二、名称空间:也叫命名空间

    全局名称空间(当前py文件)

    随着代码的执行,解释器会在内存开辟一个空间叫做全局名称空间,里面存储着代码执行过程中的变量与值的对应关系,如果是遇到函数就记录函数名和函数体内存地址的对应关系,会随着整个代码的结束而清除空间。

    总结:全局名称空间记录着整个文件里面的变量与值,以及函数名与函数体的对应关系。

    临时名称空间:也叫局部名称空间

    和全局名称空间类似,在代码运行过程中遇到要运行的函数时,解释器会在内存中在开辟一个临时名称空间,用于存储函数运行时所调用的函数体内部的变量与值的对应关系,会随着函数的结束而消失。

    如果在代码运行还没结束时,又遇到了第二个或第三个或更多需要调用的函数时,会每运行一个函数就开辟一个新的临时名称空间,随着函数的结束而消失。

    总结:临时名称空间里面记录着,函数运行时函数体里面的变量与值的对应关系,而且随着函数的结束而消失

    内置名称空间:(builtins.py文件)

    Python源码提供的一些内置空间,print input.......

    像print input......等等其他就在内置名称空间里面

    加载顺序,取值顺序

    加载顺序:内置名称空间---->全局名称空间---->局部名称空间(函数执行时)

    取值顺序(就近原则,LEGB原则):(从局部找时)局部名称空间----->全局名称空间----->内置名称空间

    根据实际情况来找,从局部找时从局部开始,从全局找时从全局开始,全局没有在找内置。

    取值顺序是单向不可逆的。例如:

    input = '小杨'  # 运行到这里时全局已经记录了  (当这里被注释了,全局没有了这条记录)
    def func():
        input = '红红'  # 此函数被调用时,这里属于局部,且已经被记录了
        print(input)
    ​
    print(input)   # 这是从全局开始找的
    func()          # 调用函数,这是从局部开始找
    # 输出:
    小杨
    红红
    ​
    ---------------------------------------------------------# input = '小杨'   当这里被注释了,全局没有了这条记录
    def func():
        input = '红红'  # 此函数被调用时,这里属于局部,且已经被记录了
        print(input)
    ​
    print(input)   # 这是从全局开始找的,全局没有,就从内置里面找。
    func()          # 调用函数,这是从局部开始找
    # 输出:
    <built-in function input>
    红红

    作用域。两个作用域

    全局作用域

    内置名称空间 + 全局名称空间,(不能取局部作用域的变量)

    局部作用域

    局部名称空间,可以取全局作用域的变量(引用,不可修改)

    也可以取它上一级的局部名称空间变量(同样不可修改,只能引用),列如:

    def func():
        count = 1          # 在局部命名空间1里创建count变量
        def func2():
            count = 100    # 这叫在局部命名空间2里创建了一个新的变量
            print(count)
        func2()
    func()   
    # 输出:
    100
    
    ---------------------------------------------
    
    def func():
        count = 1          # 在局部命名空间1里创建count变量
        def func2():
            count += 1    # 这叫修改,全局命名空间1的 count 自加1
            print(count)
        func2()
    func()   
    # 输出:会报错
    UnboundLocalError: local variable 'count' referenced before assignment

    为什么局部作用域不能改变全局作用域的变量

    当Python解释器读取到局部作用域时,发现了你对一个变量进行了修改的操作,解析器会认为你在局部已经定义过了这个局部变量了,他就从局部找这个局部变量,没有就报错了。(个人有争议)

    count = 1
    def func():
        count = 100    # 这叫在局部作用域里面创建了一个新的不是修改
        print(count)
        
    func()
    # 输出:
    100
    
    --------------------------------------------------------------
    
    count = 1
    def func():
        count += 1    # 这叫修改,全局作用域的 count 自加1
        print(count)
        
    func()   # 会报错
    # 输出:
    UnboundLocalError: local variable 'count' referenced before assignment

    三、函数的嵌套(高阶函数)

    看懂这三道题也就差不多了:执行顺序。

    def func1():
        print('in func1')
        print(3)
    
    
    def func2():
        print('in func2')
        print(4)
    
    func1()
    print(1)
    func2()
    print(2)
    def func1():
        print('in func1')
        print(3)
    
    
    def func2():
        print('in func2')
        func1()
        print(4)
    
    print(1)
    func2()
    print(2)
    def fun2():
        print(2) 
        
        def fun3():
            print(6)
        print(4)
        fun3()
        print(8)
    
    print(3)
    fun2()
    print(4)

    四、内置函数 globals locals

    globals

    返回的是字典:字典里面的键值对:全局作用域的所有内容。

    content = '全局作用域'
    def func():
        name = '小杨'
        age = 22print(globals())
    # 输出:
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0161BEC8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:\Users\YS\Desktop\Python全栈\day10\python.py', '__cached__': None, 'content': '全局作用域', 'func': <function func at 0x016A5460>}

    locals

    返回的是字典:字典里面的键值对:当前作用域的所有内容

    content = '全局作用域'
    def func():
        name = '小杨'
        age = 22
        def func2():
            a = 666
        print(locals())    # 当前作用域func()
    ​
    func()
    ​
    # 输出:
    {'name': '小杨', 'age': 22, 'func2': <function func.<locals>.func2 at 0x01CB5418>}
    学习之旅
  • 相关阅读:
    2013暑假集训B组训练赛第二场
    2013暑假集训B组训练赛第二场
    2013暑假集训B组训练赛第二场
    2013暑假集训B组训练赛第二场
    SPOJ ANARC05H 计数DP
    HDU 2586 LCA-Tarjan
    POJ 1330 LCA最近公共祖先 离线tarjan算法
    Codeforces 176B 经典DP
    UVA 10564 计数DP
    HDU 4901 多校4 经典计数DP
  • 原文地址:https://www.cnblogs.com/XiaoYang-sir/p/14652183.html
Copyright © 2011-2022 走看看