python-函数与作用域

1、函数

(1)基本知识

  • 函数是对功能的封装

  • 语法

    def function_name([parameters]):
        function_body
    
  • 返回值

    • 如果没有return,或者return后面不跟数据,返回None
    • return后的语句不执行,即终止函数
    • return可以返回多个值,即return value1, value2, ...
      • 多个返回值返回的是一个元组
  • 参数:形参、实参和传参

    • 形参:函数声明时的未知的变量
      • 位置参数
      • 默认值参数:如def fuc(argu1, argu2 = None)
        • 当argu2没有实参时,默认argu2=None
        • 注意:当默认值参数可变时(列表、指定、集合),默认值变量不会随函数结束而消亡
      • 动态参数:即不定参数
    • 实参:函数调用的时候给的具体的值
      • 位置参数:按照形参顺序传递实参
      • 关键字参数:按照形参名字传递实参,与位置无关
      • 混合参数:位置参数和关键字参数一起使用,先位置参数,后关键字参数(必须先位置参数)
    • 传参:过程
  • 例子

    In [30]: def fuc(para1, para2, para3=None):
        ...:     print(para1)
        ...:     print(para2)
        ...:     print(para3)
        ...:     
    
    In [31]: fuc(1, 2)
    1
    2
    None
    
    In [32]: fuc(1, 2, 3)
    1
    2
    3
    
    In [33]: fuc(para3=1, para2=2, para1=3)
    3
    2
    1
    
    • def fuc(para1, para2, para3=None)
      • para1、para2、para3就是形参
      • 其中para1和para2为位置参数,是有严格的顺序的
      • para3为默认值参数,即不给para3传值时它有默认值
    • fuc(1, 2, 3)
      • 1、2、3就是实参,是具体传递的值
      • 这里三个实参都是位置参数,即按顺序给形参赋值
    • fuc(para3=1, para2=2, para1=3)
      • 这里的1、2、3就是关键字参数,与位置无关,直接按形参的名字赋值

(2)参数传递

  • 动态传参

    • def function(*argument_name) *表示动态传参(位置参数),函数接收的数据类型是元组

      • 注意:使用这种动态传参时要注意位置参数,合理顺序是先位置参数,再动态参数,最后默认值参数
        (因为默认值要生效就不能往形参传值)
      • def fuc1(name, *food)
      • def fuc2(*food, name) fuc1和fuc2函数体相同
      • fuc1(a, b, c, d)fuc2(a, b, c, d)效果不同,因为对于fuc2,food把a、b、c、d都接收了
      In [34]: def f1(a, *args):
          ...:     print(a)
          ...:     print(args)
          ...:     
      
      In [35]: def f2(*args, a):
          ...:     print(a)
          ...:     print(args)
          ...:     
      
      In [36]: f1(1, 2, 3)
      1
      (2, 3)
      
      In [37]: f2(1, 2, 3)
      ---------------------------------------------------------------------------
      TypeError                                 Traceback (most recent call last)
      <ipython-input-37-f8cc322696a9> in <module>()
      ----> 1 f2(1, 2, 3)
      
      TypeError: f2() missing 1 required keyword-only argument: 'a'
      
      • 可以看到使用f2时报错了,因为形参args将所有实参都吸收了
      • 由此我们知道*args参数一定要放到位置参数后面
    • def function(**argument_name) **表示动态传参(关键字参数),函数接收的数据类型是字典

      In [38]: def fuc(a1=None, **kwargs):
          ...:     print(a1)
          ...:     print(kwargs)
          ...:     
      
      In [39]: fuc(name='aaa', age=20)
      None
      {'name': 'aaa', 'age': 20}
      
      In [40]: fuc(100, name='aaa', age=20)
      100
      {'name': 'aaa', 'age': 20}
      
      In [41]: fuc(name='aaa', age=20, 100)
        File "<ipython-input-41-86542b6e5b0a>", line 1
          fuc(name='aaa', age=20, 100)
                                 ^
      SyntaxError: positional argument follows keyword argument
      
      • 可以看到若实参使用关键字参数,且形参中没有定义,则这些实参会被放到一个字典里
      • 从上例中我们也可以得知**kwargs应该放在位置参数后面

(3)参数合理顺序

  • 参数合理顺序应该是:位置参数,*args,默认值参数,**kwargs(key word)

  • 例子如下

    In [42]: def fuc(a1, a2, *args, a3=None, a4=None, **kwargs):
        ...:     print(a1)
        ...:     print(a2)
        ...:     print(args)
        ...:     print(a3)
        ...:     print(a4)
        ...:     print(kwargs)
        ...:     
    
    In [43]: fuc(100, 200, 300, 400)  # 100->a1, 200->a2, 300和400->args
    100
    200
    (300, 400)
    None
    None
    {}
    
    In [44]: fuc(100, 200, a3=300, a4=400, a5=500, a6=600)
    # 100->a1, 200->a2, 300->a3, 400->a4, a5=500和a6=600->kwargs
    100
    200
    ()
    300
    400
    {'a5': 500, 'a6': 600}
    

(4)函数注释

  • 函数的整体注释可以这样写

    In [45]: def fuc():
        ...:     '''
        ...:     函数名称:fuc
        ...:     函数功能:···
        ...:     入口参数:···
        ...:     出口参数:···
        ...:     '''
        ...:     pass
        ...: 
        ...: 
    
    In [46]: print(fuc.__doc__)
    
        函数名称:fuc
        函数功能:···
        入口参数:···
        出口参数:···
        
    
    

(5)聚合(形参)

  • 接收所有参数:def fuc(*args, **kwargs)
  • *args,**kwargs相当于一个聚合的作用

(6)打散(实参)

  • 打散是用的*args的特性,例子如下

    In [52]: def fuc(*para):
        ...:     print(para)
        ...:     
    
    In [53]: l = [1, 2, 3]
    
    In [54]: fuc(l)
    ([1, 2, 3],)
    
    In [55]: fuc(l[0], l[1])
    (1, 2)
    
    In [56]: fuc(l[0], l[1], l[2])
    (1, 2, 3) 
    
  • 可以打散的类型有list、tuple、string、set、dictory

2、作用域

  • 名称空间:

    • 1、内置名称空间 2、全局名称空间 3、局部名称空间
    • 1->2->3(python解释器运行顺序)
  • 作用域命名空间

    • 全局作用域:内置名称空间、全局名称空间
    • 局部作用域:局部名称空间
    • globals() 查看全局作用域的内容
    • locals() 查看当前的作用域的内容
  • 函数的嵌套:

    • 函数的定义可以嵌套
    • 访问函数时要注意作用域
  • globalnonlocal

    • global value_name 可以把全局中的变量引入到函数内部或者在函数内部中创建一个全局变量
    • nonlocal value_name 从当前作用域往外层(全局作用域)方向寻找value_name,
      • 注意,不找全局作用域的变量,且只找离当前作用域最近的一层
  • 例子1

    In [11]: l = [1, 2, 4]
    
    In [12]: def f1():
        ...:     print(l)
        ...:     
    
    In [13]: f1()
    [1, 2, 4]
    
    In [14]: num = 100
    
    In [15]: def f2():
        ...:     print(num)
        ...:     
    
    In [16]: f2()
    100
    
    In [17]: def f3():
        ...:     a = 'hhhh'
        ...:     
    
    In [18]: print(a)
    ---------------------------------------------------------------------------
    NameError                                 Traceback (most recent call last)
    <ipython-input-18-bca0e2660b9f> in <module>()
    ----> 1 print(a)
    
    NameError: name 'a' is not defined
    
    • 局部作用域内可以访问全局作用域里的变量
    • 但是全局作用域内不可以访问局部作用域里的变量
  • 例子2

    In [28]: num = 100
    
    In [29]: def fuc():
        ...:     num = 200
        ...:     print(num)
        ...:     
    
    In [30]: fuc()
    200
    
    In [31]: print(num)
    100
    
    In [32]: def fuc2():
        ...:     global num
        ...:     num = 300
        ...:     
    
    In [33]: fuc2()
    
    In [34]: print(num)
    300
    
    • 在局部作用域内是无法修改全局作用域里的变量的
    • 若要修改,必须在局部作用域内将变量声明为全局变量
    • 函数被执行后,变量才被修改(若不执行函数,则只是创建了函数,函数里的语句并未执行)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值