[Python基础06]函数的参数&返回值

本节内容开始进入基础进阶部分的学习

1、什么是函数

我们通常在进行一些功能处理的过程中,需要执行一行或者多行代码来完成整个业务流程的处理,如:

# 计算指定半径的圆的面积
# 定义圆周率
pi = 3.1415926;
# 指定用户输入圆的半径,通过int()将输入的数据转换成整数
r = int(input("请输入圆的半径:"));
# 执行计算功能,求取圆的面积
area = pi * (r ** 2);
print("您要求的半径为" + r + "的圆的面积为:"  + str(area));

上面这段程序相信大家都能看懂,就是求取用户输入一个指定半径的圆的面积
如果我们在不确定的某个时刻,又需要求取另一个圆的面积,应该怎么做呢?

思考中…没事,我重新写一下这段代码!
这样,合适吗?!
合适,但是存在问题,什么问题呢…就是代码重复,工作重复,如果每天这样大量重复的工作出现,程序就不再是编程,而是搬砖了。
此时,我们python和其他编程语言一样,可以将这段程序封装成函数,通过一个定义的函数封装好这些代码,在某些需要的时候,通过函数的名称直接调用即可。

1.1、 函数的定义

函数的定义非常简单,python中通过def关键字来定义函数

def 函数名称(参数列表):
    函数中封装的代码块
     [return 返回值]

代码块,就是多行代码作为一个整体,在python中,通过缩进的方式来确定不同的代码块,临近的相同缩进的代码为一个整体代码块。
一个python程序中,所有出现缩进的空格数量必须一致。
函数中的封装的代码块必须是缩进一定部分的多行代码。

按照上面的例子,我们定义一个求取圆的面积的函数

# 定义一个函数,用于计算指定半径的圆的面积
def getCircleArea(radius):
    pi = 3.1415926;
    area = pi * (radius ** 2);
    return area;

如上所示,一个计算圆的面积的函数就被定义好了,函数的名称为getCircleArea。
切记,定义函数不会让函数中的代码执行。

2、 函数的调用

定义好的函数,我们需要通过函数的名称来调用函数,函数中的代码才会执行。
调用函数通过**函数名称()**来调用函数,后面的圆括号中,可以根据定义函数的参数列表给函数传递对应的参数

r = int(input("请输入圆的半径:"));
a = getCircleArea(r);
print("圆的面积是:" + str(a));

这样,我们就可以在需要的时候,直接通过定义好的函数名称getCircleArea(radius)来进行函数功能的重复执行了。

3、 函数中的变量

3.1、 函数中的变量

在函数中,我们可以看到也进行了变量的使用,那函数中的变量和函数外的变量到底有什么区别呢?

3.2、 全局变量的定义

声明在函数外面的变量,可以在文档的任意地方使用这个变量,我们称为全局变量
关于全局变量,使用方式如下

# 定义在函数外部的变量
name = "tom"
# 直接使用全局变量
print(tom)
# if代码块中使用全局变量
print(tom)
# 函数中使用全局变量
def test():
    print(tom)   # tom
3.3、 函数中使用全局变量

上面代码的输出结果,都是tom,表示全局变量一旦声明赋值,在任何地方都可以使用
但是如果我们要在函数中修改变量的值,就会出现如下的问题

name = "tom"
def test():
    name = "jerry"
    print(name)   # jerry
test()
print (name)   # tom
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# 运行上述程序,我们会发现,即时函数执行了,在函数中name输出jerry
# 但是,在函数外部,我们重新打印name的值,发现name的值还是tom
# 
# 此时:函数中的name是局部变量,函数外部的name是全局变量
# 如此诡异的情况,也是python为了避免出现开发人员在操作函数的过程中
# 如果不明确是否使用全局变量的情况下,无意中覆盖全局变量的值
#
# 所以,在函数中使用全局变量,必须显示的声明使用哪个全局变量
# 语法是:global 变量名
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
name = "tom"
def test():
    global name
    name = "jerry"
    print(name)  # jerry
test()
print(name)  # jerry
3.4、 函数中的变量隔离

如果函数中没有通过global引入全局变量,但是在函数中又使用了和全局变量相同的名称
此时就会出现问题

name = "tom"
def test():
    # 这里只是想使用一下全局变量的值
    print(name)   
    # n行代码之后,又声明了局部变量name
    # 此时一旦声明了局部变量,上面打印的代码就会出现错误
    name = "jerry" 

test()
执行结果:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in test
UnboundLocalError: local variable 'name' referenced before assignment

上面的错误,主要是变量提升引起的错误,首先描述一下错误出现的条件
1.如果函数中没有声明和全局变量名称一致的局部变量,函数中直接使用全局变量的值,不会出现错误
2.如果函数中,一旦在任意位置定义了和全局变量名称一致的局部变量,函数中在局部变量声明定义之前使用这个名称的变量,就会出现上述错误

这是因为,在函数中,一旦声明变量并且赋值一个局部变量,函数中又没有通过global引入同名的全局变量,此时在函数中只会存在局部变量~不允许使用全局变量
此时如果在同名的局部变量声明赋值之前使用这个变量,就会出现错误。

3.5、 局部变量

声明在函数内部的变量,只能在函数内部使用,函数执行结束这个变量就会被回收,我们称为局部变量。局部变量只是在函数中可以使用,出了函数这个变量就不认识了

def test():
    name = "tom" # 这是一个test函数中的局部变量

test()
print(name) 
# 执行结果
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'name' is not defined # 出现错误,name没有定义

通常情况下,函数内部声明赋值的变量和函数的参数都会当成局部变量进行处理

全局变量和局部变量:
几乎所有的编程语言中都有全局变量和局部变量的区分,同时我们在开发过程中,也需要尽量避免频繁使用全局变量
**原因之一:**全局变量一经使用就常驻内存,如果全局变量中数据过于庞大就会导致内存溢出程序崩溃的情况
**原因之二:**是全局变量在使用的过程中容易造成变量的全局污染,因为在项目开发过程中通常是多个人协同开发多个Python文件然后整合到一起,此时就有可能会因为全局变量重名造成变量的值覆盖的情况出现。

4、 函数的参数

4.1、 函数的形式参数和实际参数

函数的参数主要会涉及到两个概念:形式参数、实际参数

  • 形式参数:其实就是定义函数时,函数括号中的变量,形式参数的意义是当前函数如果要被调用执行,就必须让函数接收括号中定好的参数才能正常执行,就是形式上需要这些数据才能执行函数,所以称为形式参数
  • 实际参数:实际参数是我们在通过函数名称调用函数时,在括号中传递的真实数据;实际传递给函数用于执行的数据,称为实际参数
    形式参数和实际参数的具体关系如下图所示:

形式参数和实际参数的关系

4.2、函数的参数定义规则

函数通过def进行定义,用于执行一个功能,一个函数,可以需要参数,也可以不需要参数。
类似我们现实生活,执行一个功能就是做一件事情,做这件事情需要的资源就是参数,去做一件事情,有些需要资源,有些是不需要资源的。

所以!
规则1:如果我们的程序中出现了一部分功能代码重复执行,就需要封装一个函数来减少代码的重复量
规则2:根据代码执行是否需要其他额外的数据,需要额外的几个数据就定义几个参数,不需要额外的数据就不定义参数
规则3:实际参数可以传递任意对象(python中一切皆对象)

4.3、 函数参数默认值

某些时候,我们可以给函数的参数定义默认值,这样函数在调用过程中,如果某些参数没有传递,就直接使用默认值来执行函数代码了,函数默认参数确定比较简单,直接在形式参数上赋值就可以

# 重新定义函数,给参数设置默认值5
def getCircleArea(pi=3.1415, radius=5) :
    a = pi * (radius ** 2);
    return a;

# 调用函数计算圆面积,不传递参数,使用默认值
a1 = getCircleArea();
# 调用函数,传递参数进行计算
a2 = getCircleArea(3.14, 3);
# 调用函数,给第二个参数传递数据进行计算
a3 = getCircleArea(radius=8);

4.4、 函数的可变参数

在某些情况下, 函数的参数个数不是确定的,这样在常规定义函数时就木有办法进行形式参数的定义了。
python提供了一种可变参数,可以完美的解决这个问题
可变参数,是在形式参数前面加一个 * 符号作为标识

# 定义一个函数,用于打印多个数据
def printMsg(*msgs) :
    for x in msgs:
        print(x);

printMsg("tom");
printMsg("tom", "jerry");
printMsg("tom", "jerry", "shuke");
# 以上三个函数调用,都是可以正常执行的

注意,在某些特殊情况下,函数的可变参数放在了固定参数的前面;此时函数的调用就需要通过变量名称指定数据了(这个也成为命名关键字参数,后面的内容中有单独介绍)

# 可变参数msgs放在固定参数name的前面了
def printMsg(*msgs, name) :
   print (name);
   print(msgs);
   for x in msgs:
       print("-->" + x);
# 普通调用,出现错误
# 函数中的参数都被可变参数接收了,name就木有可以接收的数据了
printMsg("tom", "jerry");
# 必须如下方式调用才可以;指定name参数传递数据
printMsg("tom", "jerry", name="shuke");

可变参数是将传入函数的多个参数,自动封装成了一个tuple字典,也就是一组数据来使用。
上面的可变参数*msgs在函数中打印的结果如下:

print (msgs);
执行结果:("tom", "jerry")'

4.5、特殊的用法:关键字参数

将传递给函数的参数,解析成dict字典的形式,也就是key:value键值对的形式,这就是关键字参数的意义,更加方便可变参数的操作
关键字参数,使用两个 ** 符号来声明关键字参数

def printMsg(**msgs) :
    print(msgs);

printMsg(name="jerry", age=18);
函数中打印结果:{name:"jerry", age:18}

注意,关键字参数,还可以指定只能传递什么样的名称为参数名称,就是命名关键字参数。命名关键字参数通过*符号作为分隔符号,符号后面的参数就是命名关键字参数

# 定义具有命名关键字的参数
def printMsg(name, age, *, province, city):
    print(name, age, province, city);
# 调用时需要传递具体的参数
printMsg("tom", 18, province="HN", city="ZZ");

另外一种情况,就是在可变参数的后面,添加的参数都是命名关键字参数,这里的命名关键字参数就不需要*符号分隔了

# 下面的函数,province和city两个参数是放在可变参数*args后面的
# 就是制定的命名关键字参数,在前面可变参数部分有提到
def printMsg(name, age, *args, province, city):
    函数中的执行代码
# 此时函数的调用如下
printMsg("tom", 19, "tom is a cat", province="HZ", city="ZZ");

扩展:函数中的参数,根据传递的参数的顺序、参数类型的不同,会有各种不同的组合方式,如传递[字符串、字符串]、[字符串、字符串…]、[字符串、数值…]、[数值、函数…]等等各种各样的情况,但是我们有了可变参数 *args和命名关键字参数**kw之流的出现,让函数参数的接收变得比较简单。
我们可以通过(*args, **kw)的形式来接收任何形式的参数

5、函数的返回值

5.1、 函数的返回值的意义

函数是执行一段代码完成一定的功能处理过程

函数中代码块执行的结果,如果我们后面的代码中需要用到,就需要函数返回我们执行的结果,就是需要返回值;

如果我们的函数就是执行代码,执行的结果我们后面的代码不适用,就不需要定义返回值

类似生活中某A君让某B君做一件事,就是调用了某B君的函数,如果这件事是取快递,某B君做完取快递这件事情,最后要将执行的结果[快递]返回给某A君,就是函数需要返回值;
如果这件事是下班锁门,某B君做完这件事情就可以了,事情的结果不需要给某A君进行汇报,就是函数不需要返回值

5.2、操作函数的返回值

函数的返回值通过return关键字来确定
返回值的语法结构如下:

def 函数名称(参数列表):
    函数代码块
    return 返回值

注意:返回值可以是任意对象(python中一切皆对象)

返回值,需要在调用函数的时候进行接收,否则返回值也是没有意义的。

'''
这里调用了前面定义的函数getCircleArea
但是没有接受返回值
函数执行的返回值就丢弃了
'''
getCircleArea(5); 
'''
这里调用了前面定义的函数getCircleArea()
并且接收了函数执行之后的返回值
在后面的代码中就可以直接使用这个返回值了
'''
a = getCircleArea(10);

注意:python中的函数,不论是否写了return关键字,都会有返回值的存在,return是开发人员确定的返回值,如果没有return关键字python函数会返回一个None对象。

5.3、 函数可以返回多个数据

python的函数比较特殊,在函数执行完成后,通过return关键字可以同时返回多个数据,调用函数的地方根据返回值的顺序来接收对应的返回值。

# 定义一个函数,进行某个矩形的缩放
def getScaleArea(width, height, scale) {
    w = width * scale;
    h = height * scale;
    return w, h;
}

# 调用函数
x, y = getScaleArea(10, 20, 2);
print (x, y);
执行结果:20, 40



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

周小董

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

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

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

打赏作者

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

抵扣说明:

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

余额充值