1. 局部变量和全局变量
- 局部变量 是在 函数内部 定义的变量,只能在函数内部使用
- 全局变量 是在 函数外部定义 的变量(没有定义在某一个函数内),所有函数 内部 都可以使用这个变量
提示:在其他的开发语言中,大多 不推荐使用全局变量 —— 可变范围太大,导致程序不好维护!
1.1 局部变量
- 局部变量 是在 函数内部 定义的变量,只能在函数内部使用
- 函数执行结束后,函数内部的局部变量,会被系统回收
- 不同的函数,可以定义相同的名字的局部变量,但是 彼此之间 不会产生影响
局部变量的生命周期
- 所谓 生命周期 就是变量从 被创建 到 被系统回收 的过程
- 局部变量 在 函数执行时 才会被创建
- 函数执行结束后 局部变量 被系统回收
- 局部变量在生命周期 内,可以用来存储 函数内部临时使用到的数据
1.2 全局变量
- 全局变量 是在 函数外部定义 的变量,所有函数内部都可以使用这个变量
注意:函数执行时,需要处理变量时 会:
- 首先 查找 函数内部 是否存在 指定名称 的局部变量,如果有,直接使用
- 如果没有,查找 函数外部 是否存在 指定名称 的全局变量,如果有,直接使用
- 如果还没有,程序报错!
1) 函数不能直接修改 全局变量的引用
- 全局变量 是在 函数外部定义 的变量(没有定义在某一个函数内),所有函数 内部 都可以使用这个变量
- 在函数内部,可以 通过全局变量的引用获取对应的数据
- 但是,不允许直接修改全局变量的引用 —— 使用赋值语句修改全局变量的值
- 如果在函数中需要修改全局变量,需要使用
global
进行声明 - 为了保证所有的函数都能够正确使用到全局变量,应该 将全局变量定义在其他函数的上方
2. 函数与参数
2.1 函数的定义
定义函数的格式如下:
def 函数名():
函数封装的代码
……
def
是英文define
的缩写- 函数名称 应该能够表达 函数封装代码 的功能,方便后续的调用
- 函数名称 的命名应该 符合 标识符的命名规则
函数调用
调用函数很简单的,通过 函数名()
即可完成对函数的调用
函数参数的使用
- 在函数名的后面的小括号内部填写 参数
- 多个参数之间使用
,
分隔
2.2 参数的作用
- 函数,把 具有独立功能的代码块 组织为一个小模块,在需要的时候 调用
- 函数的参数,增加函数的 通用性,针对 相同的数据处理逻辑,能够 适应更多的数据
- 在函数 内部,把参数当做 变量 使用,进行需要的数据处理
- 函数调用时,按照函数定义的参数顺序,把 希望在函数内部处理的数据,通过参数 传递
形参和实参
- 形参:定义 函数时,小括号中的参数,是用来接收参数用的,在函数内部 作为变量使用
- 实参:调用 函数时,小括号中的参数,是用来把数据传递到 函数内部 用的
2.3 函数的返回值
- 在程序开发中,有时候,会希望 一个函数执行结束后,告诉调用者一个结果,以便调用者针对具体的结果做后续的处理
- 返回值 是函数 完成工作后,最后 给调用者的 一个结果
- 在函数中使用
return
关键字可以返回结果 - 调用函数一方,可以 使用变量 来 接收 函数的返回结果
注意:
return
表示返回,后续的代码都不会被执行
以上知识是Python中有关函数的基本知识,有了以上知识之后我们就可以来分析在C语言中一个很经典的例子,那就是在函数中交换两个变量的值,Python中对这一问题的处理跟C有着比较大的不同。
相信学过C的都知道,如果直接把要交换的两个变量传递给函数,在函数内部进行交换,并不能真正实现交换,因为函数参数的传递只是实参先形参的单向传递,例如如下代码
#include "stdio.h"
void swap(int a, int b)
{
int t;
t = a;
a = b;
b = t;
printf("a = %d, b = %d\n", a, b);
}
int main()
{
int a = 1, b = 2;
printf("a = %d, b = %d\n", a, b);
swap(a, b);
printf("a = %d, b = %d\n", a, b);
}
以上代码的执行结果是
a = 1, b = 2
a = 2, b = 1
a = 1, b = 2
这其中的原因就是,C编译器首先在main函数中为a和b两个变量开辟一块内存空间,然后调用swap函数时,在函数内部又新开辟了两个内存空间来存放参数a和b,并且把主函数中a和b的值传递给swap函数内的参数a和b,在swap函数中完成交换后,返回main函数时,会把swap函数内部的两个内存空间释放,所以main函数中的a和b没有被交换。
我们可以在Python中写类似的代码,例如
def swap(a, b):
t = a
a = b
b = t
print("a = %d, b = %d" % (a, b))
g_a = 1
g_b = 2
print("a = %d, b = %d" % (g_a, g_b))
swap(g_a, g_b)
print("a = %d, b = %d" % (g_a, g_b))
这个代码的执行效果和C是完全相同的,但是其中的原因却不一样,在上一篇博客中我们知道了Python中的变量和C中的变量的区别,在这里就表现出来了
在Python中函数参数的传递是通过引用传递的,当给变量g_a和g_b赋值的时候,python解释器首先在内存中开辟了两个空间分别存放数字1和2,然后让g_a引用数字1,让g_b引用数字2,下面我们用“标签”和“小盒子”来分析
当调用函数的时候,传递的是引用,也就是把g_a的引用传递给a,把g_b的引用传递给b,这个时候g_a和a这两个标签都贴在数字1的小盒子上,g_b和b这两个标签都贴在数字2这个小盒子上,然后在函数内部交换的时候,把标签a撕下来贴在数字2的小盒子上,把标签b撕下来贴在数字1的盒子上(因为数字是不可变类型)。函数调用完毕后系统会把函数中使用的标签都撕下来扔掉,这个时候函数外部的标签g_a和g_b都还是贴在原来的盒子上并没有被改变,所以输出跟调用之前一样。
那么我们要在函数内部改变外部变量的内容应该怎么做呢?
在C中,C给我们提供了指针这种方法,我们只需要把指针作为参数传递到函数内部,然后在函数内部对指针进行操作,就可以改变外部变量的值,由于C中的函数只能返回一个值,所以这个方法也是在C中函数返回多个值的方法。
我们可以对上面的C代码做如下修改
#include "stdio.h"
void swap(int *a, int *b)
{
int t;
t = *a;
*a = *b;
*b = t;
printf("a = %d, b = %d\n", *a, *b);
}
int main()
{
int a = 1, b = 2, *a1, *b1;
a1 = &a;
b1 = &b;
printf("a = %d, b = %d\n", a, b);
swap(a1, b1);
printf("a = %d, b = %d\n", a, b);
}
而在Python中修改就比较方便了,因为Python中的函数可以返回多个值,我们只要把传入的参数a和b调换一下返回就行了,代码如下
def swap(a, b):
return b, a
g_a = 1
g_b = 2
print("a = %d, b =%d" % (g_a, g_b))
g_a, g_b = swap(g_a, g_b)
print("a = %d, b =%d" % (g_a, g_b))