• 函数(二)


    可变长参数

    可变长参数:指的是在调用函数时,传入的参数个数可以不固定

    调用函数时,传值的方式无非两种,一种是位置实参,另一种是关键字实参,因此形参也必须得有两种解决方法,以此来分别接受溢出的位置实参(*)与关键字实参(**)

    牢记

    一、可变长形参之*

    形参中的*会将溢出的位置实参全部接收,然后存储为元组的形式,然后把元组赋值给*后的参数。需要注意的是:*后的参数名约定俗成为args。

    def func(name, pwd, *args): # *后可以跟其他参数,例如abc,但尽量不要使用,应该使用args,args是约定俗成的
        print('name:', name, 'pwd:', pwd) 
        print(args) # args会接收多余的位置实参,以元组形式存储
        return 1
    
    res = func('xiaowu', 123456, 18, 170, 140)
    print(res)
    
    # name: xiaowu pwd: 123456
    # (18, 170, 140)
    # 1
    

    二、可变长形参之**

    形参中的**会将溢出的关键字实参全部接收,然后存储字典的形式,然后把字典赋值给**后的参数。需要注意的是:**后的参数名约定俗成为kwargs

    def func(name, pwd, **kwargs): # **后可以跟其他参数,但尽量不要使用,应该使用kwargs,kwargs是约定俗成的
        print('name:', name, 'pwd:', pwd)
        print(kwargs) # kwargs会接收多余的关键字实参,以字典形式存储
        return 1
    
    res = func('xiaowu', 123456, age = 18, height = 170, weight = 140)
    print(res)
    
    # name: xiwowu pwd: 123456
    # {'age': 18, 'height': 170, 'weight': 140}
    # 1
    

    了解

    一、可变长实参之*

    实参中的*,*会把*后的以元组形式存储的参数值,打散成位置实参,然后传给形参

    def func(name, pwd, x, y, z): # 我们用具体的参数去接收可变长实参,会返回具体的值
        print('name:', name, 'pwd:', pwd)
        print(x, y, z)
        return 1
    
    tup = (18, 170, 140)
    res = func('xiaowu', 123456, *tup)
    print(res)
    
    # name: xiaowu pwd: 123456
    # 18 170 140
    # 1
    
    def func(name, pwd, *args): 
        print('name:', name, 'pwd:', pwd)
        print(args)
        return 1
    
    tup = (18, 170, 140)
    res = func('xiaowu', 123456, *tup)
    print(res)
    
    # name: xiaowu pwd: 123456
    # (18, 170, 140)
    # 1
    

    二、可变长实参之**

    实参中的**,**会把**后的以字典形式存储的参数值,打散成关键字实参,然后传给形参

    def func(name, pwd, **kwargs): # 我们用可变长形参去接收可变长实参,会以字典的形式返回
        print('name:', name, 'pwd:', pwd)
        print(kwargs)
        return 1
    
    dic = {'age': 18, 'height': 170}
    res = func('xiaowu', 123456, **dic)
    print(res)
    
    # name: xiaowu pwd: 123456
    # {'age': 18, 'height': 170}
    # 1
    
    def func(name, pwd, age, height): # 我们用具体的参数去接收可变长实参,会返回具体的值
        print('name:', name, 'pwd:', pwd)
        print('age:', age, 'height:', htight)
        return 1
    
    dic = {'age': 18, 'height': 170}
    res = func('xiaowu', 123456, **dic)
    print(res)
    
    # name: xiaowu pwd: 123456
    # age: 18 height: 170
    # 1
    

    可变长参数*和**的连用

    我们可以在一个函数中同时使用*和**

    def func(name, pwd, *args, **kwargs):
        print('name:', name, 'pwd:', pwd)
        print(args)
        print(kwargs)
        return 1
    
    res = func('xiaowu', 123456, 1, 2, age=18, height=170)
    print(res)
    
    # name: xiaowu pwd: 123456
    # (1, 2)
    # {'age': 18, 'height': 170}
    # 1
    

    函数对象

    函数是第一类对象,即函数可以被当做数据处理。

    函数名等同于变量名,即变量名有的方法,函数名同样也有,被引用、当做容器元素、当做函数参数、当做函数返回值。

    函数对象的四大功能

    1. 引用

      def func():
          print('from func')
      
      f = func
      print(f)
      
      # <function func at 0x000001B9B5742CA8>
      
    2. 当做参数传给一个函数

      def func():
          print('from func')
      
      def foo(m):
          m()
      
      foo(func)
      
      # from func
      
    3. 可以当做函数的返回值

      def func():
          print('from func')
      
      def foo(x):
          return x
      
      res = foo(func)
      print(res)
      res()
      
      # <function func at 0x0000018D5A072EE8>
      # from func
      
    4. 可以当做容器类型的元素

      def func():
          print('from func')
      
      function_list = [func]
      function_list[0]()
      
      # <function func at 0x0000027B7C6C2CA8>
      # from func
      

    函数嵌套

    函数的嵌套,就是在函数内部再定义函数。但是函数内部定义的函数,无法在函数外部使用函数内部定义的函数。

    def f1():
        def f2():
        	print('from f2')
        f2()
    
    f2()
    
    # NameError: name 'f2' is not defined
    
    def f1():
        def f2():
        	print('from f2')
        f2()
    
    f1()
    
    # from f2
    

    名称空间和作用域

    一、名称空间

    名称空间:我们之前说过创建变量,就会在内存中开辟一个空间存储变量。我们一直没有说变量名的存储,其实在内存中有一块内存存储变量名和变量之间绑定关系的空间,这个空间就叫名称空间。名称空间又分为内置名称空间、全局名称空间、局部名称空间。

    1. 内置名称空间

    内置名称空间:是python解释器独有的,存放着python解释器自带的名字,如int、len

    内置名称空间会在python解释器启动的时候自动开辟存放python解释器自带的名字,在python解释器关闭后销毁

    2. 全局名称空间

    全局名称空间:除了内置名称空间和局部名称空间,其他的都存放在全局名称空间,如下面代码中的x、func、l

    全局名称空间会在文件执行的时候生效,在文件执行结束后失效

    x = 1
    
    def func():
        pass
    
    l = [1, 2]
    

    3. 局部名称空间

    局部名称空间:用于存放函数调用期间函数体产生的名字,如下面代码中的f2

    局部名称空间会在文件执行时,调用函数期间的时候生效,在函数执行结束后失效

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

    4. 执行顺序

    三种名称空间的执行顺序是:内置 --> 全局 --> 局部

    5. 查找顺序

    名称空间是用来存放变量名和变量值之间的绑定关系的,所以查找变量名一定是在三个名称空间找到的。

    查找顺序为:从自己的当前位置开始 --> 局部 --> 全局 --> 内置,且不可逆寻找。

    二、作用域

    作用域就是作用的区域,产生作用的范围。作用域分为全局作用域和局部作用域。

    1. 全局作用域

    全局作用域:全局有效,全部存活,包含内置名称空间和全局名称空间,全局作用域中的变量只能在全局中使用。

    x = 1
    
    def f1():
        x = 3
    
    print(x)
    
    # 1
    

    2. 局部作用域

    局部作用域:局部有效,临时存储,只包含局部名称空间,局部作用域中的变量只能在局部中使用。

    def f1():
        def f2():
            def f3():
                print(x)
            x = 2
            f3()
        f2()
    
    f1()
    
    # 2
    

    3. 注意点

    作用域关系在函数定义阶段就已经固定死了,与函数的调用没有关系。

    4. 补充

    4.1 global关键字

    global关键字可以修改全局作用域中的变量。

    x = 1
    
    def f1():
        global x
        x = 3
    
    f1()
    print(x)
    
    # 3
    

    4.2 nonlocal关键字

    nonlocal关键字可以修改局部作用域中的变量。

    def f1():
        x = 1
        def f2():
            nonlocal x
            x = 3
        f2()
        print(x)
    
    f1()
    
    # 3
    

    4.3 注意

    1. 在局部想要修改全局的可变类型,不需要任何声明,可以直接修改。

    2. 在局部想要修改全局的不可变类型,需要借助global声明,声明为全局的变量,即可直接修改。

    即作用域关系仅适用不可变数据类型,不适用可变数据类型

  • 相关阅读:
    高效的多维空间点索引算法 — Geohash 和 Google S2
    Geohash距离估算
    位图(BitMap)索引
    深入浅出空间索引:为什么需要空间索引
    harbor rest api 转graphql api
    ringojs java jar 集成使用
    ringojs 使用rp 包管理web 应用依赖
    ringojs 的包管理
    ringojs 基于jvm 的javascript 平台试用
    graphql cli 开发graphql api flow
  • 原文地址:https://www.cnblogs.com/yunluo/p/11334386.html
Copyright © 2020-2023  润新知