Day 07 python学习笔记

函数


函数的传参

关键字参数

函数调用时,指定参数的名称,即为关键字参数

  • 允许传入0个或者多个含参数名的参数
  • 关键字参数必须放在普通参数的后面
例:
def abc(x,a,b):
    print(x)
    print(a)
    print(b)

abc(100,b=4,a=2)  #其中a,b作为关键字参数可以随意调换位置,
                  #但x作为位置参数必须在关键字参数前面


结果:
100
2
4

命名关键字参数

限定后边的参数必须是以关键字形式传参

例:
def abc(a,b,*,c,d):  #*后边的参数必须为关键字形参
    print(a)
    print(b)
    print(c)
    print(d)

abc(1,2,c = 3,d = 4)



结果:
1
2
3
4

可变参数

可变参数:传入的形参个数是可变的。

1、*参数:常见的*args,args变量指向一个tuple对象

自动接收所有的未匹配的位置参数,到一个tuple对象里

例:
def abc(a,*b):
    print(a)
    print(b)

abc(11)
abc(11,12,13,14,344)


结果:
11
()    #可变参数无传参时默认空元组
11
(12, 13, 14, 344)
 
  

练习:

如:求一组数字的平方和,参数个数不确定
1、用列表或者元组-------但是调用时,需要先组成列表或者元组
2、可变参数

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum += n * n
    print(sum)

calc(1,2,3,4)



结果:
30

如果要传进的是元组或者列表:
在元组或者列表前面添加(*num):即把num这个list的所有元素作为可变参数传进去

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    print(sum)

num = [1,2,3,4]
calc(*num)


结果:
30

2、**参数:所有未匹配的未知参数存储到一个字典里边去

**kwargs

例:
def abc(a,**b):
    print(a)
    print(b)

abc(10)
abc(10,name="zs")  #必须以关键字参数的形式传入,才能以键值对的形式传出

结果:
10
{}  #无传参,默认空字典
10
{'name': 'zs'}

python参数的解包

参数类型是字符串、列表、元组、集合、字典的时候,可以解包

传递实参时,可以在序列类型的参数前边添加*

*自动将序列中的元素依次作为参数传递

例:
def abc(a, b, c):
    print(a)
    print(b)
    print(c)


abc(*"123")
abc(*[4,5,6])

结果:
1
2
3
4
5
6

注意:字典有点特殊

若要取出字典里的值时(**),必须保证字典的键与函数的传入形参相同,否则会报错

但若只是取出字典里的键时(*),不需要使字典的键与函数的传入形参相同

字典例:
def abc(a, b, c):
    print(a)
    print(b)
    print(c)

d = {
    "a" : "zs",
    "b" : 18,
    "c" : "python"
}

abc(*d)  #一个解包是取出字典里的键
abc(**d) #两个解包是取出字典里的值

参数解包与可变参数一起用

例:
def abc(a,*args):
    print(a)
    print(args)

abc(100,(1,2,3))   #传入元组
abc(100,*(1,2,3))

结果:
100
((1, 2, 3),)
100
(1, 2, 3)

函数递归

我们先来讲一下函数调用函数

函数调用函数

例:
def fun_01():
    print("11111111111")

def fun_02():
    print("22222222222222")
    fun_01()

fun_02()

结果:
22222222222222   #先调用2再调用1
11111111111

递归的定义

如果一个函数内部调用了自己本身,那么这个函数就是递归函数

递归在使用时,注意防止栈溢出。栈的大小是有限的,如果递归调用次数太多,会导致栈溢出

例:

简单的死递归

def fn():
    print("我是递归函数")
    fn()


fn()   #死递归


结果:
  File "D:\python\Day07\10.10\代码\10-函数递归.py", line 48
    a = fibonacci(1000)jiu
                       ^^^
SyntaxError: invalid syntax

因为递归函数必须要有一个出口

如果没有一般计算机递归1000次会报错

当然,我们也可以简单的检查一下我们的递归限制

方法:
import sys
a = sys.getrecursionlimit()
print(a)


结果:
1000

或在终端上:

练习1:

求阶乘

举例:9!

9!=8!*9

9!=7!*8*9

。。。

9!=1*2*3*4*5*6*7*8*9

所以:

n!=(n-1)!*n

递归出口:1

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


a = fact(3)
print(a)

结果:
6

但fact(1000):会报错

因为超过了计算机的递归限制,造成栈溢出

尾递归:为了解决递归调用栈溢出的方法。
调用函数时,调用自身本身,并且,return语句不能包含表达式。编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

def fact(n):
    return fact_iter(n, 1)

def fact_iter(num, product):
    if num == 1:
        return product
    return fact_iter(num - 1, num * product)

遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。

练习2:

编写一个递归函数 fibonacci(n),用于计算斐波那契数列的第 n 个数字

斐波那契数列的定义是:前两个数是 0 和 1,后续的每个数都是前两个数之和

例:1 1 2 3 5 8 13 21

def fibonacci(n):
    if n == 1 or n == 2:  #或n <= 2
        return 1
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)


a = fibonacci(6)
print(a)

结果:
8

你可能感兴趣的:(python,python,学习,笔记,开发语言,算法,后端,网络安全)