一、Python函数的使用

1. 函数的定义与使用

1.1. 函数:表达一定功能的特定可重用的一段代码的表示。(函数定义时所指定的参数只是一种占位符,如果不经调用不会执行。)
表示方法:

def <函数名> (<参数(0个或多个)>)
     <函数体> # 函数内部包含的语句代码
     return <返回值>

1.2 案例:n!

def factor(n):
    s=1 # 四个半角字符作为空格,s作为初始值
    for i in range(1, n+1):
        s*=i
    return s # 返回s值

2. 函数的调用及参数传递

2.1 调用:调用是运行函数代码的方式

2.2 参数:函数可以有参数,可以没有参数。
2.3 可选参数:函数定义时可以为某些参数指定默认值,构成可选参数。必须放在非可选参数之后,即必须放在要有的参数之后。

def <函数名> (<非可选参数,可选参数>):
    <函数体>
    return <返回值>

举例:可选参数用于n!//m,放在必选参数之后

def factor(n,m=1):    #给出默认值m=1,调用时可以使用第二个参数,也可以不使用
    s=1
    for i in range(1,n+1):
        s *= i
        return s//m
>>>factor(10)  #m没有给出,此时m默认为1
3628800 
>>>factor(10,5)  #m给出,此时m为给出值5
725760

2.4 可变参数传递:不确定参数总数量。函数max和min就是使用了可变参数传递。

def <函数名> (<参数>,*b):     #*b用于表达不确定的参数,即可变参数,也可以用*a或者*c等
    <函数体>
    return <返回值>

举例:用不确定参数实现n!再乘乘数

def factor(n,*b):   #可变参数加入
    s=1 # 四个半角字符作为空格,s作为初始值
    for i in range(1, n+1):
        s*=i
    for item in b:#n!再与b相乘
        s *= item
    return s       # 返回s值
>>>factor(10,3)
10886400
>>>factor(10,3,5,8)
435456000

2.5 参数传递的两种方式:函数调用时,参数可以按照位置名称方式传递。

def factor(n,m=1):    #给出默认值m=1,调用时可以使用第二个参数,也可以不使用
    s=1
    for i in range(1,n+1):
        s *= i
        return s//m
>>>factor(10,5)  #位置传递
725760
>>>factor(m=5,n=10)  #名称传递
725760

2.6 函数的返回值:函数可以返回0个或多个值,return不是函数必须要有的保留字,可以不需要。

def factor(n,m=1):   
    s=1
    for i in range(1,n+1):
        s *= i
        return s//m,n,m  #return保留字给出多个值,返回多个值
>>>factor(10,5)  #位置传递
(725760,10,5)   #用逗号隔开,返回多个值,这是一种元组类型
>>>a,b,c = factor(10,5)  #分别赋值给a,b,c
>>>print(a,b,c)
725760,10,5

3. 函数的局部变量和全局变量。

3.1 全局变量:整个程序中使用的变量叫全局变量
3.2 局部变量:程序中函数体中使用的变量叫局部变量,局部是函数内部使用的变量。

n,s = 10, 100    # n,s是全局变量
def factor(n):
    s=1             # factor函数中的n,s是局部变量
    for i in range(1, n+1):
        s*=i
    return s 
print(factor(n),s)    # n,s是全局变量

3.3 局部变量和全局变量使用规则:

1. 局部变量与全局变量可能重名但不同,局部变量是函数内部的占位符。
2. 函数运算结束后,局部变量被释放。
3. 可以使用global保留字在函数内部使用全局变量。

n,s = 10, 100    # n,s是全局变量
def factor(n):
    s=1             # factor函数中的s是局部变量,与全局变量s不同
    for i in range(1, n+1):
        s*=i
    return s        #此处局部变量s是3628800
print(factor(n),s)    # 此处全局变量s是100
运行结果:
3628800 100

保留字:global用来在函数内部中声明这个变量是全局变量而不是局部变量。

n,s = 10, 100    # n,s是全局变量
def factor(n):
    global s             # factor函数中使用global保留字声明s是全局变量
    for i in range(1, n+1):
        s*=i
    return s        #此处s已经是全局变量
print(factor(n),s)    # 此处全局变量s已经被函数运算进行了修改
运行结果:
3628800 3628800

4. 局部变量是组合数据类型,且未在函数内部创建,此时它是等同于全局变量。
组合数据类型:组合数据类型在python中是由指针来体现的,未真实创建组合数据类型,使用的变量是使用指针,而指针指的是外部的全局变量。修改指针对应的内容,就修改了全局变量。

举例:组合数据类型未在函数内部创建,等同于全局变量。

ls = ["F","f"]    # 通过使用[]真实创建了一个全局变量列表ls,列表必须使用"[]"才能被真实创建
def func(a) :
    ls.append(a)            # 在ls列表中增加一个元素,此处ls是列表类型,未真实创建,则等同于全局变量
    return        
func("C")    # 此处全局变量ls已经被进行了修改,即调用函数在ls中增加一个字符C
print(ls) 
运行结果:
['F','f','C'] #列表没有在函数内部真实创建

举例:组合数据类型在函数内部真实创建,就是函数的局部变量,在函数运行后被释放

ls = ["F","f"]    # 通过使用[]真实创建了一个全局变量列表ls,列表必须使用"[]"才能被真实创建
def func(a) :
    ls = []      # 使用[]真实创建了一个列表ls,ls此时是局部变量
    ls.append(a)            # 在ls列表中增加一个元素,此处ls是列表类型,未真实创建,则等同于全局变量
    return        
func("C")    # 局部变量ls已经被进行了修改,即调用函数在ls中增加一个字符C
print(ls) 
运行结果:
['F','f']  #列表在函数内部真实创建

5. 对于基本数据类型,无论是否重名,局部变量与全局变量不同。可以通过global在函数内部声明全局变量。

4. 函数的使用——lambda函数

4.1 lambda函数功能:lambda函数返回函数名作为结果,是一种匿名函数,没有函数名,使用lambda保留字定义,其返回值就是函数的名字。lambda定义简单的、能够在一行内表示的函数。

<函数名> = lambda<参数>:<表达式> #返回的结果可以赋值为函数的名字,是一种简单的函数紧凑表达形式。
等价于:
def <函数名> (<非可选参数,可选参数>):
    <函数体>
    return <返回值>
>>>f = lambda x,y : x+y #函数有两个参数x和y,进行的运算是x+y,名字通过lambda赋值给与了变量f。
>>>f(10,15)
25
>>>f = lambda : "lambda函数" #定义了一个函数,只要调用就会产生结果。
>>>print(f())
lambda函数

4.2 lambda函数应用:不是定义函数的主要形式,一般主要用于一些特定函数或方法的参数,建议使用def定义函数。

5. 代码复用和函数递归

5.1 代码复用: 同一份代码在需要时可以被重复使用(把代码当成资源进行抽象——代码资源化、代码抽象化。)函数对象来实现。
注意:函数——将代码命名,在代码层面建立了初步抽象。对象——属性和方法,在函数之上再次组织和抽象。<a>.<b><a>.<b>()5.2 模块化设计:紧耦合——两个部分交流很多,无法独立存在。松耦合——两个部分交流很少,可以独立存在。函数内部紧耦合,模块之间松耦合,使得代码可以复用


5.3 函数递归:(n!属于递归的一种)类似数学的数学归纳法

递归的两个关键:
n!={1,n=0;n(n-1)!, otherwise}——这两个可以构成递归链条。
链条:计算过程中存在递归链条。
基例:存在一个或多个不需要递归的基例,比如上述的n=0,n!=1,属于递归的最末端。
链条和基例构成递归的基础。

5.4 函数递归的实现: 递归实现n!,递归本身是一个函数,需要利用函数分支语句来实现,使用分支语句对函数进行判断。

def fact(n):
     if n==0 :
        return 1
      else:
      return n*fact(n-1)

5.5 递归的调用过程: 计算机分配内存逐次计算。
5.6 递归举例——字符串反转: 将字符串反转后输出。

>>>S[::-1]————字符串切片功能,对于字符串s从开始到最后采用-1的步长输出,从后往前,实现字符串反转。
def rvs(s):
    if  s==" ":
        return s
     else:
        return rvs(s[1:])+s[0] 调用字符串反转

5.7 递归举例——斐波那契数列

>>>F(n)=F(n-1)+F(n+1)
def f(n):
    if  n==1 or n==2:
        return 1
     else:
        return f(n-1)+f(n-2)

5.8 递归举例——汉诺塔问题——搬运圆盘

count=0
def hanoi(n, src, dst, mid):
  global count
  if n==1 :
    print("{}:{}->{}".format(1, src, dst))
    count += 1
  else :
     hanoi(n-1, src, mid, dst)
     print("{}:{}->{}".format(n, src, dst))
     count += 1
     hanoi(n-1, mid, dst, src)