python之初识函数(函数的使用、可变长度参数*args和**kwargs、return的作用),了解函数的本质(9)

前言

本篇文章的目的是带领大家从零开始认识函数,作为函数学习的第一课,本章内容是非常重要的!!!在学习函数之前,我们要明白以下几点:

  • 什么是函数?
    在Python中,函数是一段组织好的、可重复使用的、用来实现单一或相关联功能的代码块。你已经定义了一个函数,就可以在你的程序中多次调用这个函数。它相当于一个功能,我们可以通过定义的函数名,重复使用这个功能,而这个功能的作用则由你自己来定义

  • 为什么要使用函数
    当我们在开发程序时,可能会重复用到一些相同的代码,这些代码通常用来实现特定的功能,若我们需要在程序的多个地方使用这些代码,一般会将他们复制然后粘贴,但这样编写的代码会显得冗余,还会浪费不必要的时间,所以python中内置了函数这个功能,通过将特定的几段代码定义为一个函数,后续使用这些代码只需要调用函数名即可

  • 函数的作用是什么?
    1、将一段代码定义为一个函数,这样只需调用函数即可使用代码,减少代码冗余,避免重复代码
    2、定义好函数后,在程序出现问题时,只需检查函数中的代码即可,便于维护
    3、函数定义后可随时修改其中的代码,这样我们就能自定义的增加或减少函数的功能,易于扩展

1、函数

1.1 函数的本质

函数在本质上其实和变量是一样的,如下:

  1. 变量保存数据,函数保存的是功能
  2. 函数和变量的基本原则都是:先定义,在使用
  3. 函数名和变量名都指向的是一个内存空间,用于保存定义的功能或数据
  4. 函数名和变量名的命名规则相同

对变量的本质不是很熟悉的朋友,可以读这篇文章:http://t.csdnimg.cn/ugmAi

1.2 定义函数

语法格式:
def 函数名():
	代码1
	代码2
	... ...

如:

def ah():
    print(666) # 缩进用来区分不同层级的代码
# 程序运行后不会有任何结果

注意:
定义好函数后,运行程序并不会不会执行其中代码,需要通过调用函数名才会执行这些代码

1.3 调用函数

语法格式:函数名()

def ah():
    print(666)

ah() # 调用定义的函数

输出结果:

666

1.4 深入解析函数

  • 定义函数时,发生了什么事情?
  1. 在内存中开辟了一个空间
  2. 将定义的代码块放入到这个空间中
  3. 将内存地址绑定给这个函数名
  • 调用函数的本质
    格式:函数名(),其实就是 内存地址();因为函数名绑定给了内存地址,加上括号才是表示调用这个函数,也就是执行这个内存地址中保存的代码

案例1:

def ah():
    print(666)

print(ah) # 直接打印函数名,输出该函数名绑定的内存地址相关信息

输出结果:

<function ah at 0x000001B3621D81F0>

案例2:

def ah():
    print(666)

b = ah # 将函数名绑定给变量b后,他们内存地址就相同了,通过变量b也可以直接调用函数
b() # 输出结果:666
  • 函数的叠加调用
    定义一个函数时,可以在里面放任何代码,同样也可以调用其他函数;如:
def a():
    print(666)

def b():
    a() # 在函数b中调用函数a,当调用函数b时,两个函数中的代码都会执行
b() # 输出结果:666
  • 函数的基本原则
  1. 先定义,再使用;指的是代码执行的顺序,并不是书写顺序
  2. 定义函数后,并不会执行其中的代码,在被函数名调用后,才会执行其中的代码;所以我们在定义函数时,可以先使用还未定义的变量,这样在调用时也不会报错

案例:

def a():
    b() # 先使用还未定义的函数b,不会报错

def b():
    print(666)
a() # 调用函数a,输出结果:666

说明:
从上面可以看到,我们在定义函数a时在其中使用了函数b,但函数b此时还未定义,结果却没有报错;这里我们就要理解,函数先定义,在使用的真正含义,因为函数在定义时并不会执行其中的代码,所以实际上只是将这个函数的代码放入了内存空间;而只有在我们调用它时,函数中的代码才会执行;所以实际上当我们在调用函数a时,函数 a和b已经被定义了;而我们执行的则是内存空间中的代码

  • 内置函数

函数就是使用关键字 def,通过特定语法将一堆代码块组合成可以让我们任意使用的功能;而像这种功能我们在python中是经常使用的,如:print(),input(),strip() 等等,他们都属于内置函数

  1. 为什么我们在使用内置函数时,不用定义呢?
    因为python已经提前帮我们定义好了,这些函数都放在python的内置模块中;我们可以直接使用
  2. 若我们定义的函数名与内置函数名相同,内置函数会被覆盖掉;如:
def input():
    print(666)

input() # 输出结果:666

说明:
可以看到,原本input()函数是用于接收数据的,但将它重新定义调用后,变成了我们自定义的功能,原来的功能已经被覆盖掉了,所以在平常定义函数时,要注意不能与python中的内置函数重名,以免影响使用

1.5 定义函数的完整语法

语法格式:
def 函数名(参数1,参数2,...)
	代码1
	代码2
	return 返回值

从上面可以看到,完整的语法格式中,多出了两个元素,参数和return,这两个元素不写,函数依然能够定义,它们的作用主要是为了丰富函数的功能,使函数使用起来更加方便,接下来我会逐步分析这两个元素的作用

1.5.1 参数

  • 函数中有两种参数:
  1. 形参,定义函数时使用的参数,如:def 函数名(形参1,形参2,…)
  2. 实参,调用函数时使用的参数,如:函数名(实参1,实参2,…)

在python中实参代表一个具体的数据,相当于变量值,而形参相当于变量名,当我们调用函数时,这个数据就会被绑定给形参,从而被函数中的代码使用,如下:

def a(r1): # r1 为形参用于接收实参的数据
    print(r1)

a('阿豪') # '阿豪' 代表实参;输出结果:阿豪
b = '张三'
a(b) # b为实参,输出结果: 张三

说明:
从上面可以看到,实参可以是变量,也可以是一个具体的数据,当我们调用函数时,实参的值被绑定给了形参,并且在函数a中可以通过形参使用这个值

  • 当函数拥有多个参数时,形参和实参的数量要相同,不然会报错,在调用函数时,实参会从左往右依次绑定给形参;如:
def a(r1,r2,r3): 
    print(r1) # 输出结果:222
    print(r2) # 输出结果:333
    print(r3) # 输出结果:666

a(222,333,666) 
1.5.1.1 参数的分类(位置、默认、关键字、可变长度)

参数根据使用的方法和作用可以分为以下四类:

  1. 位置参数:形参和实参从左往右一一对应,依次绑定,我们通常使用的都是位置参数
def a(r1,r2,r3): # 从左往右依次绑定实参的值
   print(r1) # 输出结果:222
   print(r2) # 输出结果:333
   print(r3) # 输出结果:666

a(222,333,666)
  1. 默认参数:定义函数括号内 形参=默认值,给形参提前绑定默认值,若调用函数时,形参没有对应的实参赋值,那么形参就会使用默认值,若有对应的实参赋值,那么就以实参的值为主
def a(r1=000): # 给形参绑定默认值
    print(r1)

a(222) # 有对应实参绑定给形参,输出结果:222
a() # 没有对应的实参绑定给形参,使用默认值,输出结果:000
  1. 关键字参数:调用函数括号内 形参名=实参值,在函数调用时,可以将实参值绑定给指定的形参,这样实参和形参的位置就不用一一对应,就可以得到想要的值
def a(r1,r3,r2): # 可以随意变更顺序
    print(r1) # 输出结果:666
    print(r2) # 输出结果:0
    print(r3) # 输出结果:11

a(r2=00,r3=11,r1=666) # 通过形参名指定绑定的实参值

注意:
上面的几种参数,形参和实参的数量必须保持一致,他们之间互相对应,不然会报错

  1. 可变长度参数:在调用函数括号内使用,前面几种参数,一个形参只能接受一个实参,当我们需要 将多个实参绑定给一个形参时,就需要用到可变长度参数了;一般分为两种,如下:
  • 用法1:*形参 ,为了方便我们称这个参数为args,如:*args
    作用:接受多个默认参数,组成一个元组
def a(*args): # 接收所有的实参,组成一个元组
    print(args) # 输出结果:(111, 555, 666)

a(111,555,666)
  • 用法2 :**形参,为了方便我们称这个参数为kwargs,如:**kwargs
    作用:接受多个关键字参数,组成一个字典
def test(**kwargs): # 接受所有关键字参数,组成字典
    print(kwargs) # 输出结果:{'a': 111, 'b': 555, 'c': 666}

test(a=111,b=555,c=666)

注意:
args 和 kwargs 只是一个名字,为了区分,重点是名字前面的 * 号;名称可以随意更改,如:*r1 ,**r2

  • 用法3:(*args,**kwargs )
    将两种用法结合一起使用,表示可以接受 任意多个,任意形式的实参
def test(*args,**kwargs):
    print(args)
    print(kwargs)
    
test(13,666,a='阿豪',b='我爱你') # 默认参数和关键字参数分别被 *args和**kwargs接收,组成元组和字典
test() # 没有任何参数,*args和**kwargs默认会返回 空元组和空字典

输出结果:

(13, 666)
{'a': '阿豪', 'b': '我爱你'}
()
{}
  • 拓展点 :用处不大
    1、在调用函数括号内,使用:*列表*元组 ,表示将元组或列表中的元素依次绑定给形参
def test(a,b): 
    print(a,b)

test(*[55,66]) # 将列表中的元素依次绑定给形参,要一一对应
test(*(11,22)) # 将元组中的元素依次绑定给形参,要一一对应

输出结果:

55 66
11 22

2、在调用函数括号内,使用:**字典,表示将字典中的值绑定给指定的形参,键的名字就是形参的名字,且键必须为字符串类型

def test(b,a):
    print(a,b)

test(**{'a':66,'b':'哈哈'}) # 字典中的键就是对应的形参,并将值绑定给这个形参 

输出结果:

66 哈哈
1.5.1.2 参数的书写顺序
  1. 定义函数括号内,从左往右依次是:
    位置参数,默认参数,*args,**kwargs
  2. 调用函数括号内,从左往右依次是:
    位置参数,关键字参数

1.5.2 关键字:return

return 只会出现在函数内,它的作用有很多,如下:

  1. 在函数中,只要执行到 return,立即退出这个函数
    案例1:
def test():
    print(666)
    return # 直接退出程序,不执行后面的代码
    print('哈哈') # 不会输出
test() # 输出结果:666

案例2:

def test():
    while 1:
        while 1:
        	while 1:
            print(666)
            return # 直接退出函数,不会陷入死循环
test() # 输出结果:666

说明
从上面 案例2可以看出,return 在函数中的优先级是最高的,只要执行就会退出函数,尽管在多个死循环内,同样可以直接退出函数;而像break只能退出单个循环,无法同时退出多个循环,当然两者的使用场景是不同的,return是用于退出函数,break用于退出循环;大家不要混淆了

  1. 语法格式:return 返回值
  • 调用函数后,执行函数中的代码,并将返回值会传给函数对象,通过print可以将其打印出来,若没有写返回值,默认为 None;且返回值可以为任意数据类型

案例1:

def test():
    print(666)
    return '啦啦啦' # 有返回值,打印输出返回值

a = test()
print(a)

输出结果:

666
啦啦啦

案例2:

def test():
    print(666)
    return # 没有返回值,输出 None,不写 return 结果同样是 None

a = test()
print(a)

输出结果:

666
None
  • return后面可以跟多个返回值,用逗号隔开;格式:return 返回值1,返回值2,..
    当有多个返回值时,也必须有多个变量对应的进行绑定,才能打印出来,若不用变量接收,直接打印,得到的是一个元组
def test():
    return 66,'哈哈',[1,2,3],{'姓名':'阿豪','年龄':18}

print(test()) # 直接打印,得到元组
a,b,c,d = test() # 绑定变量,与返回值一一对应
print(a,b,c,d)

输出结果:

(66, '哈哈', [1, 2, 3], {'姓名': '阿豪', '年龄': 18})
66 哈哈 [1, 2, 3] {'姓名': '阿豪', '年龄': 18}

总结:
每个函数都有返回值,不写则默认是 None,否则就以写的值为主;且返回值需要打印出来才能看到

1.5.2 函数中的注释

我们在开发程序中为了可以更好的调试代码以及后续对代码进行扩展和修改;通常会使用注释来注明该段代码的作用,这样可以使开发人员快速了解该段代码,进而快速做出判断。从前面我们学到一个函数代表一个功能,而这个功能的作用是什么呢?这时我们就需要使用注释来对函数中的代码进行描述。

  • 函数中注释的规范写法
    通常我们,会在函数开头使用三引号 ''' '''',来进行注释;在pycharm中定义好函数后,在其中使用 三引号回车后,会变成如下格式:
    '''
    这里写的是对函数功能的描述
    :param a: 对参数a的描述
    :param b: 对参数b的描述
    :return: 对返回值的描述
    '''

案例:

def sum(a,b):
    '''
    该函数用于计算传入的两个参数的和
    :param a: 用于接收第一个实参的传值
    :param b: 用于接收第二个实参的传值
    :return: 返回参数a与参数b的和
    '''
    return a+b

print(sum(1,2)) # 输出结果:3
  • 了解点1:打印函数的注释
    语法格式:
    方法1、help(函数名)
    方法2、print(函数名.__doc__)
    用于查看函数的功能,也就是将函数的注释部分打印出来;该方法同样可以用于内置函数

案例:

def sum(a,b):
    '''
    该函数用于计算传入的两个参数的和
    :param a: 用于接收第一个实参的传值
    :param b: 用于接收第二个实参的传值
    :return: 返回参数a与参数b的和
    '''
    return a+b

help(sum) # 方法1
print(sum.__doc__) # 方法2

方法1 输出结果:

Help on function sum in module __main__:

sum(a, b)
    该函数用于计算传入的两个参数的和
    :param a: 用于接收第一个实参的传值
    :param b: 用于接收第二个实参的传值
    :return: 返回参数a与参数b的和

方法2 输出结果:

  该函数用于计算传入的两个参数的和
    :param a: 用于接收第一个实参的传值
    :param b: 用于接收第二个实参的传值
    :return: 返回参数a与参数b的和
  • 了解点2:给函数的形参添加注释并打印
    语法格式:函数名.__annotations__,打印注释

案例:

def sum(a:'必须为整数类型',b:'必须为整数')->'这是返回值':
    print(a+b)

print(sum.__annotations__) # 打印上面写的注释

输出结果:

{'a': '必须为整数类型', 'b': '必须为整数', 'return': '这是返回值'}
  • 31
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盲敲代码的阿豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值