函数的基本使用

1、定义

  • 函数存在的现实意义:
    在一个完整的项目中,某些功能可能会被反复使用,如果将反复出现的代码封装成函数,以后如果要继续使用该功能则直接使用函数即可,另外,如果要修改需求,只需要修改函数
  • 设计函数的优点:
    a.简化代码结构,提高应用的模块性
    b.提高了代码的复用性
    c.提高了代码维护性
  • 语法
'''
def  函数名(变量1,变量2....):
	函数体
	return   返回值
'''
  • 说明:
    a.def是一个关键字,是definition的缩写,专门定义函数

    b.函数名:遵循合法标识符的规则和规范即可,尽量做到见名知意

    c.(变量1,变量2…):被称为形式参数,是一个参数列表,都只是没有赋值的变量

    d.函数体:封装某些特殊的功能

    e.return是一个关键字,表示返回,只能用在函数中,表示结束函数,可以单独使用,也可以携带数据,当携带数据,则表示该函数的返回值

    f.返回值:常量,变量,表达式

    g.函数的定义分为两部分:函数的声明和函数的实现

    h.变量1,变量2… 和 return 返回值 可以根据具体的需求选择性的省略

'''
def  函数名(变量1,变量2....):
	函数体
	return   返回值
'''
# 3.1.无参无返回值
def func1():
    print("ok~~~1111")

# 3.2.有参无返回值
def func2(a):
    print('ok~~~2222')

# 3.3.无参有返回值
def func3():
    print('ok~~~~3333')
    return 10

# 3.4.有参有返回值
def func4(a,b):
    print('ok~~~~~~4444')
    return 'abc'

print('end')

"""
注意:
    1.定义函数相当于定义变量,简单来说,将函数加载到了内存中,可以通过debug来看执行过程。
    2.一个函数一旦被定义,需要手动调用它,否则无法执行
"""

2、调用

  • 1.函数调用的本质:就是使用函数的过程/执行函数内部代码的过程
  • 2.调用函数的过程中,一定要注意传参的问题
  • 3.形式参数:简称形参,出现在函数的声明部分,实际上就是一个变量,等待实参赋值
  • 4.实际参数:简称实参,出现在函数的调用部分,实际上就是一个数据【常量,变量,表达式】,目的是为了给形参赋值
  • 5.传参:在调用函数的过程中,实参给形参赋值的过程
#1正常调用
def check1():
    print('ok~~~1111',end=' ')
    check2()
def check2():
    check3()
    print('ok~~~2222',end=' ')
def check3():
    print('ok~~~3333',end=' ')


print(check1()) # ok~~~1111 ok~~~3333 ok~~~2222 None

#2死锁(恶意调用)
# def a():
#     print('aaaaa')
#     a()
# a() #RecursionError: maximum recursion depth exceeded while calling a Python object

"""
注意:
    1.函数之间可以相互调用
    2.代码在执行的过程中,一旦遇到某个函数的调用,则优先执行该函数,当该函数执行完毕好,回到调用函数的地方,继续执行后面的代码
    3.一定要避免函数之间的恶意调用
"""

3、参数

  • 形式参数:简称形参,定义在函数的声明部分,本质是一个没有值的变量,用于接收实参的值
  • 实际参数:简称实参,出现在函数的调用过程中,本质是一个有值的变量或者常量,用于给形参赋值
  • 传参:实参给形参赋值的过程
  • 参数分类:
    • 必需参数
    • 默认参数
    • 关键字参数
    • 不定长参数【可变参数】
#5、参数
#5.1、必须参数:如果形参是必需参数,调用函数的时候,实参和形参的数量和顺序必须保持一致,也需要注意类型的问题。
def func1(a,b):
    print(a + b)
func1(1,2)  #3

#5.2、默认参数:默认参数的出现,可以简化函数的调用
def add(num1,num2=5):
    print(num1 + num2)
add(10)
add(9)  #14

def add(num1=0,num2=0):
    print(f"{num1} + {num2} = {num1 + num2}")
add()   #0 + 0 = 0
add(34) #34 + 0 = 34
add(23,9)   #23 + 9 = 32

# 注意3:如果形参有多个,可以必需参数和默认参数混合使用,但是在形参中,默认参数靠后书写
# def test4(a,b = 0,c):   # SyntaxError: non-default argument follows default argument
#     print(a,b,c)
# test4(6,3)

#5.3、关键字参数:
# 注意1:关键字参数体现在函数的调用部分,通过关键字参数传参,可以调换参数的顺序
# 注意2:调用函数的时候,如果使用关键字参数,则关键字一定要和形参名称保持一致
def func32(name,age=0):
    print(f"姓名:{name},年龄:{age}")
func32('aaa')   #姓名:aaa,年龄:0
func32('aaa',34)    #姓名:aaa,年龄:34
func32(name='aaa')  #姓名:aaa,年龄:0
func32(name='aaa',age=6)    #姓名:aaa,年龄:6
func32(age=8,name='aaa')    #姓名:aaa,年龄:8

# 关键字参数在系统函数中体现较多
print(34,45,5,5,sep='*')   #  34*45*5*5  同时体现了默认参数和关键字参数
print(int('110',base=2))    #   6

# 注意1:关键字参数体现在实参中
def check1(name,age,score):
    print(f"姓名:{name},年龄:{age},成绩:{score}")
# 注意2:使用关键字参数传参可以不用匹配顺序,但是,关键字需要和形参的变量名保持一致
check1(age=18,name="jack",score=100)  # 姓名:jack,年龄:18,成绩:100

# 注意3:在实参中,关键字参数只能书写在参数的后面(这个可以对比默认参数中,在形参中默认参数也是靠后写的注意事项)
def check2(name,age,score):
    print(f"姓名:{name},年龄:{age},成绩:{score}")
# check2(name="tom",10,66)  # SyntaxError: positional argument follows keyword argument
# check2(10,66,name="tom")  # TypeError: check2() got multiple重复 values for argument 'name'

#5.4、不定长参数/可变参数
# a. *x:x将会被当做元组处理,实参可以是任意数量的数据
def func41(*num):    # 打包
    print(num,type(num))
    print("*num:",*num)  # 拆包(元组前面加*,元组当中元素会被一个个拆开出来)
func41()    
print('#'*30)
func41('abc')  
print('#'*30)
func41('abc',45,65,7,8,89,9,True)  
'''
() <class 'tuple'>
*num:
##############################
('abc',) <class 'tuple'>
*num: abc
##############################
('abc', 45, 65, 7, 8, 89, 9, True) <class 'tuple'>
*num: abc 45 65 7 8 89 9 True
'''

# b.**x:x将会被当做字典处理,实参必须以key=value的方式传参,key必须是一个标识符
def func42(**num):   # 打包
    print(num,type(num))
func42()
func42(x=45,y=6,z=67)  # {'x': 45, 'y': 6, 'z': 67}
func42(abc='hello')

dict1 = {'a':10,"b":20}
print('check')
#print(f'{**dict1}') #SyntaxError: f-string: invalid syntax (没有这种写法)
func42(**dict1)   # {'a': 10, 'b': 20} <class 'dict'>【**dict1是拆包(把字典中的元素拆成键值对),然后再被形参打包】

# 说明:在实际应用中,*和**可以同时使用,作为不定长参数(★★★★★)
def func(*args,**kwargs):
    print(args,kwargs)
func()
func(10,20)
func(10,20,name='zhangsan',age=10)

# 注意1:必需参数可以和不定长参数混合使用
def text2(num1,*num2):
    print(num1,num2)
text2(10,45,56,67,6,8,7,8)	# 10 (45, 56, 67, 6, 8, 7, 8)

# 注意2:如果不定长参数出现在形参列表的前面,则可以结合关键字参数完成传参
def text3(*num1,num2):
    print(num1,num2)
# text3(10,45,56,67,6,8,7,8)  # TypeError: text3() missing 1 required keyword-only argument: 'num2'
text3(10,45,56,67,6,8,7,num2 = 8)	# (10, 45, 56, 67, 6, 8, 7) 8

# 注意3:*xxx在形参列表中只能被使用一次
# def text4(*num1,*num2):
#     print(num1,num2)
# text4(45,57,6,77,8)

# 注意4:给**xxx的形参传参,则必须以key=value的方式传参

# 注意5:**xxx在同一个函数的形参中只能出现一次
# def f2(**num1,**num2):
#     print(num1)
# f2(x=10,y=20,z=30)

# 注意6:*xxx和**xxx可以同时使用,但是,分别只能使用一次
def f3(*num1,**num2):
    print(num1,num2)
f3(45,45,65,7,67)   # (45, 45, 65, 7, 67) {}
f3(45,45,65,7,67,a=4,b=467,fag="abc")   # (45, 45, 65, 7, 67) {'a': 4, 'b': 467, 'fag': 'abc'}
f3(a=4,b=467,fag="abc") # () {'a': 4, 'b': 467, 'fag': 'abc'}

3.1、形参传递说明(★★★★★★):

  • 值传递:传参的时候,传递的是不可变的数据类型,如:int/float/str/tuple/bool,当形参发生修改,对实参没有影响
  • 引用传递:传参的时候,传递的是可变的数据类型,如:list/dict/set等,当形参中的元素发生修改,则实参会随着修改
  • 具体是引用传递还是值传递,主要看传到形参当中的是可变还是不可变数据
# 1.值传递
def func1(num):
    print(f"修改之前,num的地址:{id(num)}") #参数给45时,打印:修改之前,num的地址:1227227492016
    num = 100
    print(f"修改之后,num的地址:{id(num)}~~~~") #参数给45时,打印:修改之后,num的地址:1227227682256~~~~

temp = 45
func1(temp)
print(f"temp的值:{temp}") #temp的值:45


print("*" * 50)


# 2.引用传递
def func1(num):
    print(f"修改之前,num的地址:{id(num)}") #参数给[2,3,4]时,打印:修改之前,num的地址:1227237790912
    num[1] = 100
    print(f"修改之后,num的地址:{id(num)}~~~~") #参数给[2,3,4]时,打印:修改之后,num的地址:1227237790912~~~~

temp = [2,3,4]
func1(temp)
print(f"temp的值:{temp}") #temp的值:[2, 100, 4]

4、返回值

  • 注意1:return是一个关键字,可以单独作为一条语句,只能使用在函数中,表示结束函数
  • 注意2:同级的情况,在return的后面添加的任何语句,永远没有执行的机会
  • 注意3:return跳出的是函数,break跳出的是当前循环
  • 注意4:return还可以返回一个或多个返回值,多个返回值的话则该返回值类型为元组
def show1(a):
    print('1111')
    if a > 10:
        return
    print('over')
show1(20)   #1111
show1(9)    #第一行打印:1111	第二行打印:over

def show23():
    return 'abc',10,45
print(show23(),type(show23()))  # ('abc', 10, 45) <class 'tuple'>
print(show23)   #<function show23 at 0x00000276AF9E2A60>	(直接打印函数名的结果,就会打印函数在内存中的位置)

5、封装函数

  • 如果要封装一个函数,需要注意两个方面:
    • 是否需要设置形参:如果需求中有未知项参与运算,则设置为形参
    • 是否需要设置返回值:如果需求运算完是否有结果,如果有结果,则设置返回值
def isprime(num):
    if num < 2:
        return False
    else:
        result = True
        for n in range(2, num):
            if num % n == 0:
                result = False
                break
        return result
r = isprime(11)
print(r)    #True

6、匿名函数(简化函数定义格式★★★★★)

  • 概念:不再使用def这种标准形式定义函数,而是使用lambda表达式来创建函数,该函数没有函数名,被称为匿名函数,匿名函数也被称为lambda表达式。
  • 语法:lambda 形参列表:返回值
  • 特点:
    • a.lambda只是一个表达式,用一行代码实现一个简单的逻辑,可以达到对函数的简化【优点】

    • b.lambda主体是一个表达式,而不是一个代码块,只能封装有限的逻辑【缺点】

    • c.lambda拥有自己的命名空间,不能访问自有列表之外或者全局命名空间里的参数

#匿名函数
#格式: lambda 形参1,形参2,···,形参n : 函数体 【函数体当中可以是返回值】

# 定义
def func1():
    print('111')
print(func1)   # <function func1 at 0x106778f70>

#注意匿名函数如果没有形参就在lambda后加上个空格,有多个形参的话,用空格把形参和lambda隔开,形参之间用逗号隔开。
f2 = lambda :print('111!~~~~')
print(f2)   # <function <lambda> at 0x106814790>    (这里说明匿名函数赋值给那个变量,这个变量就代表了这个匿名函数)

#调用
# 调用
# 方式一:变量  = lambda xx:xxx,通过该变量就可以调用函数
r2 = f2()   #111!~~~~   这里r2代表的是f2所代表的匿名函数的运行结果,因为f2后面有个括号
print(r2)   #None

# 方式二:不常用
(lambda :print('111!~~~~'))()   #111!~~~~

#关于匿名函数的返回值
# 注意:匿名函数的返回值不需要return
add2 = lambda num1,num2:num1 + num2
r2 = add2(23,9)
print(r2)   #32

r = lambda x1,x2 : x1 > x2
print(r(1,2))   # False
print(r(4,2))   # True

6.1、匿名函数在sort()系统功能中的应用

  • 说明:
    • 普通规则:
      列表.sort():将列表中的元素进行升序
      列表.sort(reverse=True):将列表中的元素进行降序
      工作原理:默认情况下,sort()进行排序的时候,是将列表中的元素两两进行大小比较
    • 详细规则:
      列表.sort(reverse,key=func)
      key:表示自定义排序规则,具体则规则由func函数定义
      工作原理:将列表中元素依次取出,传参给func函数,该函数的返回值就是排序的规则,所以要求该函数的返回值必须支持大小比较
#sort之使用匿名函数作为规则key
d = [{'姓名':'凯子','成绩':90},{'姓名':'鸽子','成绩':50},{'姓名':'饺子','成绩':70}]
# d.sort()    #TypeError: '<' not supported between instances of 'dict' and 'dict'
# d.sort(reverse=True) #TypeError: '<' not supported between instances of 'dict' and 'dict'
d.sort(key=lambda k:k['成绩'])
print(d)    #[{'姓名': '鸽子', '成绩': 50}, {'姓名': '饺子', '成绩': 70}, {'姓名': '凯子', '成绩': 90}]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值