Python学习笔记(七):函数

Python学习笔记(七):函数

关于函数

  • Python学习笔记(七):函数
  • 一. 函数
    • 函数的定义
    • 函数的调用
    • 说明文档
  • 二. 函数的返回值与递归
    • 函数返回多个值
    • 函数递归
    • 经典递归算法
  • 三. 参数
    • 关键字参数
    • 默认参数
    • 可变参数

一. 函数

函数的定义

将常用的代码以固定的格式封装成一个独立的模块,这个模块就叫做函数(Function)

函数的本质是一段有特定功能、可以重复使用的代码

在后续编写程序过程中,如果需要同样的功能,直接通过提前起好的名字就可以调用这段代码

Python 函数支持接收多个(≥0)参数,还支持返回多个(≥0)值

def 函数名(参数列表):
    //实现特定功能的多行代码
    [return [返回值]]def 关键字实现,用[]的为可选择部分

函数名:符合 Python 语法的标识符
形参列表:设置该函数可以接收多少个参数,多个参数之间用逗号,分隔
[return [返回值] ]:整体作为函数的可选参参数,用于设置该函数的返回值

在创建函数时,即使函数不需要参数,也必须保留一对空的() 
如果定义一个没有任何功能的空函数,可以使用 pass 语句作为占位符,空函数本身没有实际意义
def str_max():
    pass
#创建一个空函数

def str_max(str1,str2):
    str = str1 if str1 > str2 else str2
    return str
#定义一个比较字符串大小的函数

def str_max(str1,str2):
    return str1 if str1 > str2 else str2
    
return语句可以直接返回一个表达式的值,这里就省略了创建 str 变量

函数的调用

[返回值] = 函数名([形参值])

函数名:要调用的函数的名称
形参值:创建函数有多少个形参,那么调用时就需要传入多少个值,顺序必须和创建函数时一致,即便该函数没有参数,函数名后的小括号也不能省略

如果该函数有返回值,可通过一个变量来接收该值
def str_max(str1,str2):
    return str1 if str1 > str2 else str2 #str_max函数
    
str3 = str_max("YOUCHANWILL","youchanwill"); #调用str_max函数
print(str3)
youchanwill

调用str_max()函数,当初定义该函数设置了2个参数,因此调用该参数必须传入 2个参数

函数内部使用了return语句,可以使用str3变量来接收该函数的返回值

说明文档

函数的说明文档(一段字符串)通常位于函数内部、所有代码的最前面

def str_max(str1,str2):
	'''
    比较字符串
    '''
    return str1 if str1 > str2 else str2 

调用Python的内置函数help()或__doc__ 属性查看某个函数的使用说明文档

help(str_max)
print(str_max.__doc__)

Help on function str_max in module __main__:

str_max(str1, str2)
    比较字符串

    比较字符串

二. 函数的返回值与递归

函数返回多个值

Python的函数返回多个值其实就是返回一个tuple

在语法上,返回一个tuple可以省略括号,多个变量可以同时接收一个tuple,按位置赋给对应的值

函数递归

一个函数在内部调用自身本身,这个函数就是递归函数

递归函数特性:

 - 必须有一个明确的结束条件
 - 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
 - 相邻两次重复之间的联系,通常前一次的输出作为后一次的输入
 - 递归效率不高,递归层次过多会导致栈溢出

函数调用通过栈(stack)实现,每进入一个函数调用,栈就会加一层栈帧,递归调用的次数过多,会导致栈溢出
def sum_number(n): 
    if n>0: 
       return n +sum_number(n-1) 
    else: 
       return 0 
sum = sum_number(100) 
print(sum)
5050

理论上,所有的递归函数都可以写成循环的方式,但递归函数定义简单,逻辑清晰

def sum_number(n): 
    if n>0: 
       return n +sum_number(n-1) 
    else: 
       return 0 
sum = sum_number(1000)  #将参数改为1000
print(sum)
RuntimeError: maximum recursion depth exceeded in comparison

递归调用的次数过多,会导致栈溢出

经典递归算法

Python学习笔记(七):函数_第1张图片

汉诺塔问题:
n = int(input("开始A塔上圆盘的个数:"))
def move( n , A , B ,C ):   
	if n == 1 :       
		print( "%s is moved to %s" %(A ,C) ) #只有一个圆盘时,直接从A柱移动到C柱
	else :
		move( n-1 , A , C , B ) #将剩下的A柱上的n-1个圆盘借助C柱移动到B柱
		move( 1 , A , B , C ) #将A柱上最后一个圆盘直接移动到C柱上
		move( 1 , B , A , C ) #将B柱上的n-1个圆盘借助A柱移动到C柱
move( n ,'A' , 'B' , 'C')
斐波拉契数列:
从第三项起,每一项都等于前两项的和,F(N)=F(N - 1)+F(N - 2)(N >= 2)
且F(0) = 0,F(1) = 1

def Fibonacci(n) :   # n为斐波拉契数列项数的值
  if n == 1 or n == 2 :
    return 1
  else :
    m = Fibonacci(n - 1) + Fibonacci(n - 2) #每一项都等于前两项的和
    return m
n = int(input('请输入一个整数'))
Fibonacci1 = [0] #数列首项为0
tmp = 1
while(tmp <= n):  
  Fibonacci1.append(Fibonacci(tmp)) #将tmp代入函数得到的新项加入列表中
  tmp += 1  
print(Fibonacci1)

三. 参数

关键字参数

使用函数时所用的参数都是位置参数,传入函数的实际参数必须与形式参数的数量和位置对应

关键字参数是使用形式参数的名字来确定输入的参数值,指定函数实参时,不需要与形参的位置完全一致,只要将参数名写正确
def dis_str(str1,str2):
    print("str1:",str1)
    print("str2:",str2)

dis_str("youchanwill","YOUCHANWILL") #位置参数

dis_str("youchanwill",str2="YOUCHANWILL") #关键字参数
dis_str(str2="YOUCHANWILL",str1="youchanwill") #关键字参数,任意调换参数的位置

调用有参函数时,既可以使用位置参数,也可以使用关键字参数
使用关键字参数调用时,可以任意调换参数传参的位置,但混合传参时关键字参数必须位于所有的位置参数之后

SyntaxError: positional argument follows keyword argument

默认参数

Python允许为参数设置默认值,在定义函数时,直接给形式参数指定一个默认值

def 函数名(...,形参名,形参名=默认值):
    代码块
    
使用此格式定义函数时,默认值的形式参数必须在所有没默认值参数之后
def dis_str(str1,str2 = "youchanwill"):
    print("str1:",str1)
    print("str2:",str2)
dis_str("YOUCHANWILL")
dis_str("YOUCHANWILL","YOUCHANWILL")
str1: YOUCHANWILL
str2: youchanwill

str1: YOUCHANWILL
str2: YOUCHANWILL

即便有默认值,也会优先使用传递给它的新值,同时可结合关键字参数
查看函数的默认值参数

使用__defaults__查看函数的默认值参数,其返回值是一个元组(tupleprint(dis_str.__defaults__)
('youchanwill',)

可变参数

在函数定义时:
当设定一个如 *you 的星号参数时,从此处开始直到结束的所有位置参数都将被收集并汇集成一个称为 you 的元组(tuple)
当设定一个如 **you 的双星号参数时,从此处开始直至结束的所有关键字参数都将被收集并汇集成一个称为 you 的字典(dict)

在函数调用时:
*参数 解包tuple对象的每个元素,作为位置参数传入到函数中
**参数 解包dict对象的每个元素,作为关键字参数传入到函数中
def dis_str(str1, str2):
    print(str1)
    print(str2)
dis_str('you')
TypeError: dis_str() missing 1 required positional argument: 'str2'

包含两个位置参数的函数print_str在只传入了1个参数后会报错
def dis_str(str1, *str2):
    print(str1)
    print(str2)
dis_str('you')
you
()

没有传入参数*str2 是一个tuple对象的字符串表示形式,()表示含有0个元素的tuple对象
def dis_str(str1, *str2):
    print(str1)
    print(str2)
dis_str('you','chan','will')
you
('chan', 'will')

函数调用时传入的参数,从左到右的顺序在函数中使用,最左侧的参数先由位置参数str1使用,剩下的所有未匹配的参数会被自动收集到1个新的tuple对象中,就是设定的*str2星号参数

*参数只收集未匹配的位置参数
number_tuple = ('1','2','3','4','5')
def dis_str(str1, *str2):
    print(str1)
    print(str2)
dis_str(*number_tuple)
1
('2', '3', '4', '5')
可变参数,必须定义在位置参数以及默认值参数的后面,因为可变参数会收集所有未匹配的参数

调用包含*参数的函数时,传入一个tuple对象时,将tuple对象的元素使用解包语法:*tuple传入

调用包含**参数的函数时,传入一个字典对象时,使用字典解包语法:**dict传入

*参数一般使用变量名为args
 
**参数一般使用变量名为kwargs

你可能感兴趣的:(Note,Python,python)