函数

本节导读:

  • 函数的定义与特性
  • 函数的创建
  • 函数的参数
  • 函数的返回值
  •  函数的作用域(局部变量和全局变量)
  • 匿名函数
  • 函数的高级用法

函数的定义与特性

定义:

   函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可

特性:

  1. 减少重复代码
  2. 使程序变的可扩展
  3. 使程序变得易维护

二 函数的创建与调用:

# 创建函数
def sayhi():
    print("Hello, I'm nobody!")
# 调用函数
sayhi() #在函数名后面加括号,就是调用这个函数

三 函数的参数

  • 形参和实参

    形参:是函数定义时候定义的参数

    实参:函数调用的时候传进来的参数

  • 默认参数
    以下代码,country位置不填写,则默认为“CN”,country位置填写,则传入该值,默认参数后移动到最后
    def stu_register(name,age,course,country="CN"):
  • 关键参数

    正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可(指定了参数名的参数就叫关键参数),但记住一个要求就是,关键参数必须放在位置参数(以位置顺序确定对应关系的参数)之后

    def stu_register(name, age, course='PY' ,country='CN'):

    调用可以这样

    stu_register("王山炮",course='PY', age=22,country='JP' )

    但绝不可以这

    stu_register("王山炮",course='PY',22,country='JP' )

    当然这样也不行

    stu_register("王山炮",22,age=25,country='JP' )

    这样相当于给age赋值2次,会报错!

  • 非固定参数
    函数在定义时不确定用户想传入多少个参数时,就可以使用非固定参数

    *arg

    send_alert(msg,*arg)# 会将多个值打包成一个元组,也可以传一个元组或列表,但是要记得在传的元组或列表前加*,否则或默认次列表,为外层元组中的一个元素
    send_alert(msg,*args,age)
    send_alert('alex','rain','eic',22) #会报错,alex后的全被*args截胡了,age得不到值
    send_alert('alex','rain','eic',age = 22) #这样才正确

    **kwarg

    def stu_register(name,age,*args,**kwargs): # *kwargs 会把传入的键值对形式,自动打包成字典,也可以传字典,但是得在前面加**
       print(name,age,args,kwargs) stu_register("Alex",22) #输出 #Alex 22 () {}#后面这个{}就是kwargs,只是因为没传值,所以为空  
    stu_register("Jack",32,"CN","Python",sex="Male",province="ShanDong") #输出 # Jack 32 ('CN', 'Python') {'province': 'ShanDong', 'sex': 'Male'}

四 返回值:

  函数外部的代码要想获取函数的执行结果,就可以在函数里用return语句把结果返回

注意

  • 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,so 也可以理解为 return 语句代表着函数的结束
  • 如果未在函数中指定return,那这个函数的返回值为None

五 作用域(局部全局变量):

 作用域(scope),程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。名字的可用代码范围具体又引申为局部变量和全局变量

局部变量|全局变量

    • 在函数中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
    • 函数内部无法修改全局变量,但可以调用全局变量
    • 强行在局部修改全局变量
      global name 
      name = .....

    • 可以在局部修改全局列表,或字典内部元素的值
    • 全局变量作用域是整个程序,局部变量作用域是定义该变量的函数。
    • 当全局变量与局部变量同名时,在定义局部变量的函数内,局部变量起作用;在其它地方全局变量起作用。

六 匿名函数

匿名函数也叫lambda表达式,匿名函数的核心:一些简单的需要用函数去解决的问题,匿名函数的函数体只有一行

特点是

  • 参数可以有多个,用逗号隔开
  • 返回值和正常的函数一样可以是任意的数据类型
  • 可以使用三元运算,一般与其他函数搭配使用
  • 节省代码量,看着高级

 与map方法搭配

l=[1,2,3,4]
# def func(x):
#     return x*x
# print(list(map(func,l)))

print(list(map(lambda x:x*x,l)))

与filter方法的搭配

1 l=[15,24,31,14]
# def func(x):
#         return x>20
# print(list(filter(func,l)))

print(list(filter(lambda x:x>20,l)))

七  函数的高级用法

1 嵌套使用
多层函数嵌套使用,代码定义完成之后作用域已经生成,无法更改(在外面调用内层函数时,可以调用外层函数的值)

2高阶函数(将函数作为参数或者返回值)
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
只需满足以下任意一个条件,即是高阶函数:

  • return 返回另外一个函数
  • 接受一个或多个函数作为输

3 递归

   在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

递归特性:

  1. 必须有一个明确的结束条件
  2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
  3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

递归的作用:

可以用于解决很多算法问题,把复杂的问题分成一个个小问题,一一解决
比如斐波那契数列,汉诺塔,多级评论树

尾递归
调用下一层时,和上一层完全无关系,只保留一层的栈数据,执行效率较高
return cal(n+1) 尾递归
return n*cal(n+1) n 还在等待下一层的结果,所有不是尾递归

递归注意:

    • 默认最多递归1000层(防止占用大量内存)
    • 可以修改最大递归层次
      import os 
      sys.setreccursionlimit(1500)
原文地址:https://www.cnblogs.com/leiyiming/p/8999979.html