Python基础(函数)

本文详细介绍了Python中的函数,包括函数的创建与调用、参数传递(位置实参、关键字实参、内存分析)、返回值、参数定义(默认值、可变数量参数)、变量作用域以及递归函数的概念、组成、调用过程和优缺点。通过实例解析了如何定义和使用递归函数,并展示了斐波那契数列的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python基础(函数)

一、函数的创建和调用

什么是函数

  • 函数就是执行特定任务和以完成特定功能的一段代码

为什么需要函数

  • 复用代码
  • 隐藏实现细节
  • 提高可维护性
  • 提高可读性便于调试

函数的创建

def 函数名([输入参数]):

​ 函数体

​ [return xxx]

def calc(a,b):
    c=a+b
    return c

函数的调用

def calc(a,b):
    c=a+b
    return c

result=calc(10,20)
print(result)

输出:30

执行步骤:

  1. 跳到定义函数的函数体内
  2. 执行函数体
  3. 跳到函数的调用处
  4. 继续执行下一条语句

二、函数的参数传递

位置实参

  • 根据形参对应的位置进行实参传递
print('-----函数的创建-----')
def calc(a,b):  #a,b称为形式参数,形参的位置在函数的定义处
    c=a+b
    return c

result=calc(10,20) #10,20是实际参数的值,称为实参,实参的位置在函数的调用处
print(result)

a占第一个位置,b占第二个位置

则调用处第一个位置的10 传递给a,调用处第二个位置的传递给

关键字实参

  • 根据形参名称进行实参传递
re=calc(b=21,a=11)
print(re)

输出:32

函数参数传递的内存分析

def fun(arg1,arg2):
    print('arg1',arg1)
    print('arg2',arg2)
    arg1=100
    arg2.append(10)
    print('arg1',arg1)
    print('arg2',arg2)

n1 = 11
n2 = [22,33,32]
print('n1',n1)
print('n2',n2)
fun(n1,n2)

print('n1',n1)
print('n2',n2)

输出:

n1 11
n2 [22, 33, 32]
arg1 11
arg2 [22, 33, 32]
arg1 100
arg2 [22, 33, 32, 10]
n1 11
n2 [22, 33, 32, 10]

如果是不可变对象,在函数体的修改不会影响实参的值,arg1的修改为100,不会影响n1的值

如果是可变对象,在函数体的修改会影响到实参的值,arg1的修改,append(10),会影响到n2的值

三、函数的返回值

函数返回多个值时,结果为元祖

def func(num):
    odd = [] #存奇数
    even = [] #存偶数
    for i in num:
        if i%2:
            odd.append(i)
        else:
            even.append(i)
    return odd,even

print(func([10,29,34,23,44,53,55]))

输出:

([29, 23, 53, 55], [10, 34, 44])

将两个列表当元素组成了元祖

函数返回值

  • 如果函数没有返回值(函数执行完毕之后,不需要给调用处提供数据),return可以省略不写

  • 函数的返回值,如果是1个,直接返回类型

  • 函数的返回值,如果是多个,返回的结果为元祖

    def func1():
        print('hello')
    
    res = func1()
    print(res)
    

输出:

hello
None

因为func1 没有返回值,所以为None

def func2():
    return 22

res2=func2()
print(res2)

输出:

22

有一个返回值

四、函数的参数定义

函数定义默认值参数

def func3(a,b=10):  #b称为默认值参数
    print(a,b)

#函数的调用
func3(100) #只传一个参数,b的值为默认值
func3(20,30) #传了两个参数,b的默认值被覆盖

这里给参数b设置了个默认值

输出:

100 10
20 30

其实参数里面有个隐形默认值

print('hello')
print('kitty')

print('hello',end='\t')
print('world')

输出:

hello
kitty
hello	world

其实是有个隐形参数 end= ,默认是换行,但是可以换成 ‘\t’ 表示tab

个数可变的位置参数

  • 定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的位置参数

  • 使用*定义个数可变的位置形参

  • 结果为一个元祖

    def fun5(*args):
        print(args)
    
    fun5(10)
    fun5(10,20,30)
    

输出:

(10,)
(10, 20, 30)

个数可变的关键字形参

  • 定义函数时,无法事先确定传递的关键字实参的个数时,使用可变的关键字形参

  • 使用**定义个数可变的关键字形参

  • 结果为一个字典

    def fun6(**args):
        print(args)
    
    fun6(a=10)
    fun6(a=10,b=20,c=36)
    

输出:

{'a': 10}
{'a': 10, 'b': 20, 'c': 36}

在函数中,可变的关键字参数只能有一个,可变的位置参数,也只能有一个

def fun2(*args,*a):
    pass

以上写法错误,因为可变的位置参数,只能有一个

def fun2(**args,**a):
    pass

也报错,因为个数可变的位置参数,也是只能有一个

既有个数可变的位置参数,又有个数可变的关键字形参:

def fun2(*args,**a):
    pass

两种形参同时有,必须将个数可变的关键字形参放在个数可变的位置形参的后面

def fun2(*args,**a):
    print(args,a)


fun2(10,11,12,a=12,b=13,c=14,d=15)

输出:

{'a': 10, 'b': 20, 'c': 36}
(10, 11, 12) {'a': 12, 'b': 13, 'c': 14, 'd': 15}

五、函数的参数总结

序号参数的类型函数的定义函数的调用备注
1位置参数1
将序列中的每个元素都转换为位置参数1使用*
2关键字实参1
将字典中的每个键值对都转换为关键字实参1使用**
3默认值形参1
4关键字形参1使用*
5个数可变的位置形参1使用*
6个数可变的关键字形参1使用**

将参数以列表的形式传入

def fun6(a,b,c):
    print('a=',a)
    print('b=',b)
    print('c=',c)

lst=[11,22,33]
fun6(*lst)

**想让lst中的元素对应函数的形参,一要个数对应,二要在列表名前加个 ***

参数传递的特殊情况

def func4(a,b,c,d):
    print('a=',a)
    print('b=',b)
    print('c=',c)
    print('d=',d)

位置传参:

func4(10,22,33,55)

输出:

a= 10
b= 22
c= 33
d= 55

关键字传参:

func4(a=12,b=11,c=15,d=66)

输出:

a= 12
b= 11
c= 15
d= 66

混合方式:

func4(12,15,c=18,d=19)

输出:

a= 12
b= 15
c= 18
d= 19

传参方式限制

def func8(a,b,*,c,d):
    print('a=',a)
    print('b=',b)
    print('c=',c)
    print('d=',d)

中间放颗 * ,之前的位置传参,之后的关键字传参,否则报错

print(12,17,18,d=20)

结果报错:

TypeError: func8() takes 2 positional arguments but 3 positional arguments (and 1 keyword-only argument) were given

func8(12,17,c=18,d=20)

输出:

a= 12
b= 17
c= 18
d= 20

形参的顺序问题

def fun9(a,b,*,c,d,**args):
    pass

def func10(*args,**args2):
    pass

def func11(a,b=10,*args,**args2):
    pass

上面方式都是可以的

六、变量的作用域

def fun(a,b):
    c=a+b #c,就称为局部变量,因为c是在函数体内进行定义的变量,a,b为函数的形参,作用范围就是函数内部,相当于局部变量
    print(c)

当在函数体外进行操作变量c时:

print(c)

会报红:Unresolved reference ‘c’

name ='杨老师'  #name的作用范围为函数内部和外部都可以使用 ---全局变量
print(name)
def func2():
    print(name)

func2()
杨老师
杨老师
  • 在局部定义全局变量
  • global
def fun3():
    global age  #函数内部定义的变量,局部变量,局部变量使用global声明,这个变量实际上就变成了全局变量
    age =20
    print(age)

fun3()
print(age)
20
20

七、递归函数

什么是递归函数

  • 如果在一个函数的函数体内调用了该函数本身,这个函数就称为递归函数

递归函数的组成部分

  • 递归调用与递归终止条件

递归的调用过程

  • 每递归调用一次函数,都会在栈内存分配一个栈帧
  • 没执行完一次函数,都会释放相应的空间

递归的优缺点

  • 缺点:占用内存多,效率低下
  • 优点:思路和代码简单

示例:

print('-----递归函数-----')
def fac(n):
    if n == 1:
        return 1
    else:
        return n*fac(n-1)

print(fac(6))

输出:

-----递归函数-----
720

斐波那契额数列

#斐波那契额数列
def fib(n):
    if n == 1:
        return 1
    elif n ==2:
        return 1
    else:
        return fib(n-1) + fib(n-2)

print(fib(7))

#输出这个数列前几位上的数字
for i in range(1,8):
    print(fib(i))

输出:

13
1
1
2
3
5
8
13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值