函数基础

函数的基本使用

  • 函数的定义

格式如下:
image.png
说明:

  • 函数定义代码块以def关键词开头,后接函数标识符名称和圆括号()
  • 任何传入参数都必须放在圆括号中间
  • 函数内容以冒号:开始,并且缩进
  • return [表达式]结束函数,选择性地返回一个值给调用方,不带表达式的return相当于返回None
  • 函数标识符名称采用下划线表示法,且不能以数字开头
  • 注意:因为函数体相对比较独立,因此在函数定义的上方,应该和其他代码保留两个空行
    • 函数的调用
  • 通过 函数名(参数列表) 即可完成对函数的调用
  • 注意:函数调用必须放在函数定义的下方
    • 函数的文档注释
  • 函数的文档注释位于函数体的最前面,即def的下方
  • 使用连续的三对引号,在连续的三对三对引号之间编写对函数的说明文字
  • 在函数调用位置,使用 Ctrl + 鼠标位置 可以查看函数的说明信息,也可以使用 Ctrl + 点击鼠标 跳转到函数的定义代码处

    参数和返回值传递

    变量的引用

  • 在Python中,变量和数据分开存储,数据保存在内存中的一个位置,变量中保存着数据在内存中的地址,变量中记录数据的地址就叫做引用
  • 在Python中,变量引用自对象,对象有不同类型的区分,而变量是没有类型的,变量可以指向任何类型的对象
  • 使用id()可以查看变量的引用数据所在的内存地址,即变量中存储的地址值
  • 注意:如果变量已经被定义,当给一个变量赋新值的时候,本质上是修改了变量的引用,即变量不再对之前的数据引用,变量改为对新赋值的数据引用
  • 在Python中,变量的名字类似于便签纸贴在数据上

    可变和不可变对象

  • 不可变对象:内存中的数据不会被修改,即不会在被调用函数内修改调用函数内的变量值

    • 数值类型:int、float、bool、complex
    • 字符串:str
    • 元组:tuple
    • 举例:变量赋值 a = 5 后再赋值 a = 10,实际是新生成一个int值对象10,再让a指向它,而5被丢弃,不是改变a的值,相当于新生成了a
  • 可变对象:内存中的数据会被修改,通过接口改变的是数据所在的位置,变量的地址没变

    • 列表:list
    • 字典:dict
    • 集合:set
    • 举例:变量赋值 list = [1, 2, 3, 4]后再赋值 list[2] = 5,此时list的第三个元素的值被修改,而list变量的引用没有改变;但是对 list 变量重新赋值为 list = [4, 3, 2, 1],则list变量的引用改变了,原数据[1, 2, 3, 4]的地址和内容都没有改变
    • 因此,无论传递的参数是可变对象还是不可变对象,在函数内部对参数使用赋值语句,只会修改局部变量的引用,不会影响到外部变量的引用。但是,如果传递的参数是可变对象,在函数内部使用方法修改了数据的内容,则会影响到外部的数据
    • 注意:在函数内部对可变对象使用 += 运算符不会修改变量的引用,即会影响到外部的数据

      函数的参数传递

  • 在Python中,函数的参数传递以及返回值都是靠引用传递的

  • 对于不可变对象,类似于C++中的值传递,在函数体内修改参数的值,函数体外的值不会受到影响
  • 对于可变对象,类似于C++中的引用传递,在函数体内修改参数的值,函数体外的值也会随之改变
    • 注意:在函数内对指向可变对象的变量重新赋值是不会改变可变对象的值,这没有修改可变对象
  • 因此,严格意义上不能说Python的参数传递是值传递还是引用传递,而是应该分传不可变对象和传可变对象两种情况讨论

    函数参数的说明

  • 必需参数:必需参数须以正确的顺序传入参数,调用时的参数数量和顺序必需和定义函数时一致

  • 关键字参数:关键字参数允许函数调用时参数的顺序与定义函数时不一致,因为Python解释器能够用参数名来匹配参数值,但是参数数量仍需一致

举例:
image.png

  • 缺省参数
    • 定义函数时,可以给某个参数指定一个默认值,具有默认值的参数就叫做缺省参数
    • 调用函数时,如果没有传入缺省参数的值,则在函数内部使用定义函数时指定的参数默认值
    • 注意事项
      • 定义函数时必须保证带有默认值的缺省参数在参数列表末尾
      • 如果调用函数时有多个缺省参数,需要指定参数名,这样解释器才能够知道参数的对应关系。如果都不指定也是可以的,指定一个以后,后面的就必须指定
      • 定义函数时,缺省参数需要使用最常见的值作为默认值
      • 如果一个参数的值不能确定,则不应该设置默认值

举例:
image.png

  • 不定长参数(多值参数)
    • 基本语法

image.png

  • 说明:加了星号*的不定长参数会以元组的形式导入,存放所有未命名的变量参数。如果在函数调用时没有指定参数,它就是一个空元组

举例
image.png

  • 另外一种就是参数带两个星号**,此时实际参数会以字典的形式导入
    • 注意:和普通参数不一样的是,在函数内对传入的字典以调用方法的形式进行修改,函数外不会生效

举例
image.png

  • 两者可以一起使用,运用场景是:将一个元组变量直接传递给 args,将一个字典变量直接传递给 kwargs,此时需要使用拆包
    • 拆包的方式是,在元组变量前增加一个 ,在字典变量前增加两个
    • 传递给一个函数的元组和字典也可以继续传递给别的函数,仍然是使用拆包
    • 说明:一般在给多值参数命名时,习惯使用 args 存放元组参数,**kwargs 存放字典参数 ```python def demo1(args, **kwargs): print(args) print(kwargs)

def demo(num1, num2, args, **kwargs): print(num1) print(num2) demo1(args[1:], **kwargs)

if name == ‘main‘: tuple1 = (1, 2, 3, 4, 5) dict1 = {‘name’: ‘小明’, ‘age’: 18, ‘gender’: True} demo(123, ‘abc’, tuple1, *dict1)

“”” 输出: 123 abc (2, 3, 4, 5) {‘name’: ‘小明’, ‘age’: 18, ‘gender’: True} “””

  1. <a name="sPEfA"></a>
  2. ### 使用模块中的函数
  3. <a name="ZwaoI"></a>
  4. #### 基本说明
  5. - 模块就好比是工具包,要想使用这个工具包中的工具,就需要import 这个模块
  6. - 每一个以扩展名py结尾的Python源代码文件都是一个模块
  7. - 导入模块后,在模块外可以直接使用模块中定义的全局变量、函数,以模块名.变量 / 模块名.函数的方式
  8. - 注意:以数字开头的模块是无法在Pycharm中导入的
  9. <a name="dSDjU"></a>
  10. #### 关于if __name__ == '__main__':
  11. - 每个python模块(文件)都包含内置的变量__name__,当该模块被直接执行的时候,它的__name__等于'__main__';而当该模块被import到其他模块中,则它的__name__等于该模块的文件名(不包含后缀.py)
  12. - 因此,当该模块被直接执行的时候,if __name__ == '__main__': 语句中的代码将被执行;而当该模块被import到其他模块中,if __name__ == '__main__': 语句中的代码不会被执行
  13. - 因此,在被导入模块中,将测试代码写在 if __name__ == '__main__': 语句的内部,防止在导入模块中被执行
  14. <a name="kO9Mr"></a>
  15. ### 全局变量和局部变量
  16. <a name="g0wNf"></a>
  17. #### 局部变量
  18. - 局部变量是在函数内部定义的变量,只能在函数内部使用
  19. - 函数执行结束后,函数内部的局部变量会被系统回收
  20. - 不同的函数,可以定义相同名字的局部变量,彼此之间不会产生影响
  21. <a name="Vftk8"></a>
  22. #### 全局变量
  23. - 全局变量是在函数外部定义的变量,所有函数内部都可以使用这个变量
  24. - 在函数内部修改全局变量的值和参数传递的规律是一样的,对于不可变对象是修改不了的,对于可变对象可以通过调用接口进行修改
  25. - 为了保证所有的函数都能够正确使用到全局变量,应该将全局变量定义在所有函数的上方
  26. - 函数执行时,需要处理变量时会:
  27. 1. 首先在函数内部查找是否存在指定名称的局部变量,如果有,直接使用
  28. 1. 如果没有,在函数外部查找是否存在指定名称的全局变量,如果有,直接使用
  29. 1. 如果还没有,程序报错
  30. - 为了避免局部变量和全局变量造成混淆,在定义全局变量时,可以考虑在全局变量名前增加 g_ 或者 gl_ 的前缀
  31. <a name="rN7yS"></a>
  32. #### global的使用
  33. - 如果在函数内部需要修改全局变量,可以使用global进行声明,此时在函数内部对任何全局变量进行的一切修改,在函数外部都将生效
  34. ```python
  35. num = 10
  36. list = [1, 2, 3]
  37. def demo():
  38. global num
  39. global list
  40. num = 5
  41. list = [2, 3, 4]
  42. demo()
  43. print(num)
  44. print(list)
  45. """
  46. 输出:
  47. 5
  48. [2, 3, 4]
  49. """