zoukankan      html  css  js  c++  java
  • 函数的进阶(动态参数,命名空间和作用域,函数的嵌套,gloabal和nonlocal关键字)

    1. 函数参数--动态传参

      昨天已经解过了传参, 如果需要给一个函数传参,而参数又是不确定的. 或者我们给一个函数传很多参数, 我的形参就要写很多, 写起来就很麻烦, 这时我们可以考虑使用动态参数.形参的第三种:动态参数.

    (1) 动态参数分为两种:

      1) 动态接收位置参数

      语法: def 函数名(*args):         在形参前加个'*'符号

    def chi(*food):  # *表示任意,即可以接收任意位置参数
        print('我要吃',food)  # 动态参数接收到的是tuple类型的数据
    chi('大盘鸡','火锅','烤鱼','烤鸭','冰淇淋')#  我要吃 ('大盘鸡', '火锅', '烤鱼', '烤鸭', '冰淇淋')
    
    def food(he,tang,*cai):
        print('我要吃',he,cai,tang)
    food('可乐','紫菜蛋花汤','大盘鸡','烧烤')  #实参'可乐','紫菜蛋花汤'传递给了形参'he','tang',实参'大盘鸡','烧烤'传给了形参'cai'
    # 我要吃 可乐 ('大盘鸡', '烧烤') 紫菜蛋花汤
    
    # 定义求一组数相加的和的函数
    def sun(*a):
        sum = 0
        for c in a:
            sum = sum + c
        return sum  #返回值为sum
    print(sun(1,2,3,4,5,6,7,8,9,10))  #55

      2) 动态接收关键字参数

      语法: def    函数名(**kwargs):     在形参前面加两个'*'符号

    def food(**a):   # **表示任意,即任意接收关键字参数
        print('我想吃',a)  # 接收到的是字典
    print(food(主食='米饭',菜='大盘鸡',喝的='可乐'))  #我想吃 {'主食': '米饭', '菜': '大盘鸡', '喝的': '可乐'}

      形参有位置参数,默认值参数,动态位置参数(*args),动态接收关键字参数(**kwsrgs)这四种. 他们写的先后顺序是:

      位置参数>>动态接收位置参数>>默认值参数>>动态接收关键字参数

    def f(*args,a,b):  #动态接收位置参数写在位置参数前会导致传入的所有实参都传递给'*args',而a,b没有值
        print(args,a,b)
    f(1,2,3,4,5,6)  #会报错因为a,b没有值 TypeError: f() missing 2 required keyword-only arguments: 'a' and 'b'
    
    def f(a,b,*args):  #改变一下位置,把*args写在位置参数后面
        print(args, a, b)
    f(1,2,3,4,5,6)  #(3, 4, 5, 6) 1 2
    def f(a,b,c='hello',*args):  #当默认值参数在*args前面,想要传递给*args值,就必须要传递'c'的值.不想给c值,就无法给*args值
        print(a,b,c,args)
    f(1,2,3,4,5)  #1 2 3 (4, 5)
    f(1,2)  #1 2 hello ()
    
    def f(a,b,*args,c='hello'):  #把默认值参数放后面,在传递完*args的值后,最后可以用关键字参数传给c
        print(a,b,c,args)
    f(1,2,3,4,c='world')  #1 2 world (3, 4)
    给定义函数的两个形参*args和**kwargs, 那么这个函数可以接收所有的参数
    def fuc(*args,**kwargs):
        print(args,kwargs)
    fuc('hello','world','hhhh',一 ='one',二 ='two',三 ='three') 
    #('hello', 'world', 'hhhh') {'一': 'one', '二': 'two', '三': 'three'}
    把列表中的每一个元素作为参数, 传递给函数. 一次都传过去
    def func(*args, **kwargs):  # *表示聚合,所有的位置参数, 聚合成元组 **聚合成字典
        print(args)
        print(kwargs)
    lst = ["one", "two", "three", "four"]
    func(*lst)  # 实参, 打散, 迭代产生的
    #('one', 'two', 'three', 'four')
    # {}
    
    dic = {"name":"alex", "sex":""}
    func(**dic) # 把字典打散. 以key=value形式进行传参
    #()
    # {'name': 'alex', 'sex': '男'}

    (2) 函数的注释 先写'''''',然后在六个单引号中间位置按回车,自动生成注释

    def f(a,b):
        '''
        介绍函数的功能,返回的值
        :param a: 介绍变量a
        :param b: 介绍变量b
        :return:  介绍返回值
        '''
    
        pass

    2. 命名空间和作用域

       在python解释器开始执行之后, 就会在内存中开辟一个空间, 每当遇到一个变量的时候, 就把变量名和值之间的关系记录下来, 但是当遇到函数定义的时候, 解释器只是把函数名读入内存, 表示这个函数存在了,  ⾄至于函数内部的变量和逻辑, 解释器是不关心的. 也就是说一开始的时候函数只是加载进来, 仅此⽽而已, 只有当函数被调用和访问的时候, 解释器才会根据函数内部声明的变量来进行开辟变量的内部空间. 随着函数执行完毕, 这些函数内部变量占用的空间也会随着函数执行完毕而被清空.

    def f(a):
        a = 10
        return a
    print(f(3))  # 10
    print(a)  #a不存在了,NameError: name 'a' is not defined

      存放名字和值的关系的空间叫命名空间. 变量在存储的时候就是存储在这片空间中的.   

      命名空间分类:        

      1. 全局命名空间--> 直接在py文件中, 函数外声明的变量都属于全局命名空间       

      2. 局部命名空间--> 在函数中声明的变量会放在局部命名空间       

      3. 内置命名空间--> 存放python解释器提供的名字, list, tuple, str, int这些都是内置命名空间

      加载顺序:       

      1. 内置命名空间

      2. 全局命名空间      

      3. 局部命名空间(函数被执⾏行行的时候)       

      取值顺序:       

      1. 局部命名空间       

      2. 全局命名空间       

      3. 内置命名空间
       

    a = 10  #全局
    def f():  #全局
        a = 20  #局部
        print(a)  #从局部空间取a的值
    f()  #20
    print(a)  #10
    a = 10
    def f():
        print(a)  #找不到局部a的值时,会去全局命名空间找,如果全局也没有,那么就从内置命名空间找.
    f()  #10
    print(a)  #10

      作用域 :  作用域就是作用范围, 按照生效范围来看分为全局作用域和局部作用域  

      全局作用域 : 包含内置命名空间和全局命名空间. 在整个文件的任何位置都可以使用(遵循 从上到下逐行执行).

      局部作用域 : 在函数内部可以使用.             

      作用域命名空间 :        

      1. 全局作用域 :    全局命名空间 + 内置命名空间       

      2. 局部作用域 :    局部命名空间    我们可以通过globals()函数来查看全局作用域中的内容,  也可以通过locals()来查看局部作用域中的变量和函数信息

    a = 10
    def func():
        a = 20
        print(a)    # 就近原则
        print(globals())  # globals() 获取到全局作用域(内置,全局)中的所有名字
        print(locals())  # locals() 查看当前作用域中的所有名字
    func()
    # 20
    # {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 
    #0x0000011BD70A6160>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 
    #'D:/pycharm/练习/week02/new10.py', '__cached__': None, 'a': 10, 'func': <function func at 0x0000011BD74697B8>}
    # {'a': 20}

    3. 函数的嵌套

    (1)只要遇见了()就是函数的调用, 如果没有()就不是函数的调用.

    (2) 函数的执行顺序

    def func1():
        print("")
        def func2():
            print("")
            def func3():
                print("")
            print("")
        def func4():
            print("哈哈")
            func2()
        print("")
        func2()
    func1()
    #
    #
    #
    #

     

    4. gloabal, nonlocal关键字

     (1) global表示不再使用局部作用域中的内容了. 而改用全局作用域中的变量

    a = 10  #全局变量
    def f():
        global a  #把全局变量的a拿来用了
        a = a + 20  #改变的a是全局变量a
        print(a)
    f() #30
    print(a)  #30
    def f():
        global a  #建立一个全局变量的a
        a = 20  #给全局变量a赋值
        print(a)
    f() #20
    print(a)  #20

    (2)nonlocal 表示在局部作用域中, 调用其他层的局部变量(就近原则调用).

    a = 10
    def f():
        a = 20
        print(a)  320
        def ff():
            nonlocal a  # 找局部作用域中 离他最近的那个变量引入进来,将函数f中的a引入
            a = a + 20  #函数f中的a变成40
            print(a)  #40
        ff()
        print(a)  #40
    f()
    # 20
    # 40
    # 40
    print()  # 10
    无限的我,现在才开始绽放,从东边的第一缕阳光到西边的尽头
  • 相关阅读:
    AtCoder Beginner Contest 167
    AtCoder Beginner Contest 166
    AtCoder Beginner Contest 165
    AtCoder Beginner Contest 164
    AtCoder Beginner Contest 163
    AtCoder Beginner Contest 162
    AtCoder Beginner Contest 161
    AtCoder Beginner Contest 160
    AtCoder Beginner Contest 159
    自定义Mybatis自动生成代码规则
  • 原文地址:https://www.cnblogs.com/huangqihui/p/9306307.html
Copyright © 2011-2022 走看看