Python入门第十天-函数进阶

本文详细介绍了Python中的函数参数,包括位置参数、关键字参数及其混用,参数默认值,参数类型说明,以及不定长参数的使用。接着探讨了函数返回值的定义、获取方式。此外,还讨论了全局变量、局部变量,以及如何使用`global`和`nonlocal`关键字。最后,简单介绍了匿名函数(lambda)和递归函数的概念及使用步骤。

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

day10-函数进阶

一、函数的参数

1、位置参数和关键字参数

实参按照传递方式的不同分为位置参数和关键字参数

(1)位置参数
  • 调用函数时让形参和实参一一对应(第一个实参给第一个形参赋值,第二个实参给第二个形参赋值)
  • 格式:数据1,数据2,数据3,…
(2)关键字参数
  • 让实参和形参通过关键字(形参名)对应
  • 格式:形参名1 = 数据1(实参),形参名2 = 数据2,…
(3)关键字参数和位置参数混用
  • 混用时位置参数必须在关键字参数前面
def func1(x, y, z):
    print(f'x:{x}, y:{y}, z:{z}')

# 关键字参数
func1(10, 20, 30)    # x:10, y:20, z:30
func1(10, 30, 20)    # x:10, y:30, z:20
# 关键字参数(位置不影响调用结果)顺序是没有关系的
func1(x=100, y=200, z=300)    # x:100, y:200, z:300

# 混用
func1(10, z=30, y=20)    # x:10, y:20, z:30
# func1(x=20, 40, z=40)    # 报错:SyntaxError: positional argument follows keyword argument
# 原因:位置参数必须在关键字参数前面

2.参数默认值

定义函数的时候可以以“形参名 = 数据”的形式给参数赋默认值,调用函数的时候有默认值的参数可以不赋值

  • 可以给每个形参都赋个默认值
  • 当参数有了默认值之后,可以给他附一个新的值也可以不给他赋值
  • 如果有的有默认值,有的没有默认值,有默认值的形参必须放在最后,放在没有默认值的参数后面
  • 如果想跳过前面的参数,直接给后面的参数赋值,就可以使用默认值参数和关键字参数
def func2(x, y, z):
    print(f'x:{x}, y:{y}, z:{z}')
# 参数默认值
def func3(x, y, z=100):   # 可以给z赋值,也可以不给他赋值
    print(f'x:{x}, y:{y}, z:{z}')

func3(10, 20, 3)   # x:10, y:20, z:3
func3(10, 20)      # x:10, y:20, z:100
#
# def func4(x, y= 30, z):
#     print(f'x:{x}, y:{y}, z:{z}')
# 报错:SyntaxError: non-default argument follows default argument

def func4(x=10, y=100, z=30):
    print(f'x:{x}, y:{y}, z:{z}')
# 如果只想让y的值有变化,a和z的值依旧是10和30
func4(y=200)   # x:10, y:200, z:30

3.参数类型说明

  • 定义函数时可以对参数类型进行说明
  • 赋默认值,默认值是什么类型,参数类型说明就是什么类型
  • 形参名:数据类型
# 赋默认值
def func5(x=''):
    pass
# 形参名:数据类型
def func6(x: list):
    x.append()

4.不定长参数 - 主要用于参数个数不确定时

  • 在形参前加*或者加**,就可以让这个参数变成不定长参数,不定长参数的形参可以同时接受多个实参
(1)带*的不定长参数
  • 带*的参数会变成一个元组,元组中的元素就是对应的实参
  • 注意:a.一个函数可以同时存在带*和不带的参数,如果不带的在带星号的后面,不带的参数必须使用关键字参数;b.在调用不定长参数时,即使用带星号的参数时只能用位置参数传参
  • 带**的不定长参数后面必须使用关键字参数
(2)带**的不定长参数
  • 带**的不定长参数会变成一个字典,调用的时候用关键字参数传参,每个关键字及时字典的key,关键字后面的数据就是字典的value
  • 不带双星号的定长参数必须放在带**不定长参数的前面,否则会报错
  • 带*的不定长参数和带**的不定长参数可以同时出现,带一个星号的不定长参数必须在前面
  • 两个同时出现可以使函数调用时更加灵活
def func7(*x):
    print(x)
func7()    # ()
func7(10)   # (10,)

def func8(x, *y):
    print(f'x:{x}, y:{y}')

func8(10)              # x:10, y:()   空的元组
func8(10, 20, 30, 40)  # x:10, y:(20, 30, 40)

def func9(*x, y):
    print(f'x:{x}, y:{y}')
func9(1, 2, 3, y=10)

def func10(**y):
    print(y)

# func10(10, 20)  # 报错
func10(a=10, c=20, d=23)  # {'a': 10, 'c': 20, 'd': 23}
func10()                 # {}

def func11(x, **y):
    print(f'x:{x}, y:{y}')
func11(10, a=20, c=45, d=23)   # x:10, y:{'a': 20, 'c': 45, 'd': 23}
func11(x=10, a=20, c=45, d=23)  # x:10, y:{'a': 20, 'c': 45, 'd': 23}
def func12(*x, **y):
    print(f'x:{x}, y:{y}')

func12(1, 2, 3)          # x:(1, 2, 3), y:{}
func12(a=10, b=23)       # x:(), y:{'a': 10, 'b': 23}
func12(1, 2, a=2, b=4)   # x:(1, 2), y:{'a': 2, 'b': 4}
# 练习:定义一个函数,可以求多个数的和

def sum1(*num):
    sum2 = 0
    for x in num:
        sum2 += x
    print(sum2)
sum1(10, 20, 30)

def sum2(*num):
    print(sum(num))

sum2(10, 20, 30)
sum2(30, 4, 56, 78)   # 168

二、函数返回值

1、什么是返回值

  • 返回值就是从函数内部传递到函数外部的数据
  • 如果实现函数的功能,产生了一个新的数据一般都需要将这个数据通过返回值返回

2、怎么确定函数返回值

  • 在函数体中通过return关键字来返回返回值:return 数据
  • 注意:同一个函数中只有一个return有效(因为执行函数体时,只要遇到return,函数直接结束)
  • 直接写return相当于return None
  • 如果要在一个函数中返回多个数据,用能够保持多个数据的容器,常用元组:return 数据1,数据2,数据3,数据4,…

3、怎么在函数外部获取函数返回值

  • 获取函数调用表达式的值就是获取函数返回值
  • 返回值对应的数据能做的,函数调用表达式都能做
  • 如果函数执行过程中遇到return,return的值是多少,返回值就是多少
  • 如果执行过程中没有遇到return,返回None
def sum1(num1, num2):
    s = num2 + num1
    return s, s/2  # return(s, s/2)

def func1():
    return [1, 2, 3]
print(func1())       # [1, 2, 3]
print(func1()[0])   # 1
if func1():
    print('您好')    # 您好

for x in func1():
    print('x:', x)
# x: 1
# x: 2
# x: 3
for x in func1():
    print(f'x: {x}')

def func2():
    print('abc')

func2()   # abc
print(func2())   # None

# 练习: 删除指定列表中所有指定元素
# [1, 23, 4, 5, 1, 34, 2, 1]  - 删除元素1
# 产生了一个新的列表,
def deal_number(list1:list, num):
    new_list = []
    for x in list1:
        if x != num:
            new_list.append(x)
    return new_list

new_list = deal_number([1, 23, 4, 5, 1, 34, 2, 1], 1)
print(new_list)
for x in new_list:
    print(f'x: {x}')

三、全局变量和局部变量

根据变量的作用域不同,将变量分为全局变量和局部变量两种

1、全局变量

  • 定义在函数和类外面的变量都是全局变量(只要不在函数和类里面,不管在哪里都是全局变量)
  • 全局变量的作用域:从定义开始到程序结束的任何地方都可以用
# a是全局变量
a = 10    # 全局变量
# b 和 c 是全局变量
for b in range(4):
    c = 10
    pass

2、局部变量

  • 定义在函数里面的变量是局部变量
  • 作用域:从定义开始到函数结束
  • 局部变量产生的原因:调用函数的时候,系统会自动为被调用的函数在栈区间开辟一块独立的内存空间,专门用来保存在这个函数中定义的变量,当函数调用结束的时候这块内存空间会自动销毁
# m和x是局部变量
def func3():
    x = 'abc'
    print(f'函数内部x: {x}')

func3()     # 函数内部x: abc

def func4(m=10):
    x = abc
    print(f'函数内部m:{m}')

3、global 和 nonlocal

  • global 和 nonlocal是函数体中的关键字,只能在函数体中使用
(1)global
  • 作用:在函数中定义或者修改全局变量

  • 用法: global 变量名

  • ​ 变量名 = 值

  • 使用global在函数中定义全局变量

def func6():
    global f
    f = 100
func6()
print(f'外部f:{f}')     # 外部f:100
  • 修改全局变量的值
  • 如果直接在函数内部给全局变量赋值,不会修改值,而是产生一个新的局部变量,要想在函数中修改全局变量的值,可以global 变量,在对变量进行赋值
name = '李家半仙儿'
def func7():
    name = '熊大'                # 此处不是在修改全局变量,而是在定义一个新的局部变量
    print(f'函数内部name:{name}')    # 函数内部name:熊大

func7()
print(f'函数外部name:{name}')     # 函数外部name:李家半仙儿

name = '李家半仙儿'
def func8():
    global name
    name = '熊大'
    print(f'函数内部name:{name}')    # 函数内部name:熊大

func8()
print(f'函数外部name:{name}')    # 函数外部name:熊大
(2)nonlocal
  • 作用:在局部的局部中修改一个局部变量的值
  • 用法: nonlocal 变量名
  • ​ 变量名 = 值

四、匿名函数

1、什么是匿名函数(lambda)

  • 匿名函数的本质还是函数,但是匿名函数只能通过一条语句来实现函数的功能
  • 匿名函数是没有函数名的

2、语法

  • lambda 形参列表: 返回值
  • 函数名 = lambda 形参列表: 返回值
# 求两个数的和
lambda num1, num2: num1+num2
sum1 = lambda num1, num2: num1+num2

# 练习:写一个匿名函数,返回指定的年是否是闰年
lambda year: '闰年' if year % 400 == 0 or (year % 4 == 0 and year % 10 != 0) else '平年'

year = lambda year: print('闰年') if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0) else print('平年')
year(2020)

year = lambda year: year % 400 == 0 or (year % 4 == 0 and year % 100 != 0)
print(year(2020))

year = lambda year: '闰年' if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0) else '平年'
print(year(2020))

五、递归(了解)

1、什么是递归函数

  • 在函数中调用函数本身的函数就是递归函数
  • 作用:循环能做的,递归都可以做(指导思想:循环能做的就不要用递归,因为用递归太消耗cpu 了)
  • 递归控制次数:控制递归函数在指定次数后结束

2、使用递归解决问题的步骤

  • 第一步:想定义普通函数一样定义函数
  • 第二步:找临界值(找函数结束的条件) - 一般肯函数至少取多少,即最小值
  • 第三步:找关系(找f(n)和f(n-1) - 找上次循环和本次循环之间的关系)
  • 第四步:假设函数的功能已经实现,通过关系用f(n-1)实现f(n)的功能
def func1(count):
    print('=======')
    if count == 1:
        return
    func1(count-1)
print(func1(4))
# count = 5
# def func1():
#     global count
#     count -= 1
#     print('=======')
#     if count == 1:
#         return
#     func1()
#

# 用递归:1+2+3+4+......+100
# f(n) = 1+2+3+4+......+n
# f(n-1) = 1+2+3+4+......+(n-1)
# 关系:f(n)=f(n-1)+n
def sum1(n):
    # 1.找临界值
    if n == 1:
        return 1
    # 2.找关系
    # sum1(n) = sum(n-1)+n
    return sum1(n-1)+n
print(sum1(100))

'''
n=4
*
**
***
****
n=5
*
**
***
****
*****
'''
def print_star(n):
    for x in range(1, n+1):
        print('*'*x)
print_star(4)

def print_star(n):
    # 1.找临界值
    if n == 1:
        print('*')
        return
    # 2.关系:先实现f(n-1)然后再打印n个*
    print_star(n-1)
    print("*"*n)
print_star(4)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值