目录
一、局部变量与全局变量
1.1、局部变量
局部变量:
- 定义:局部变量,就是在函数内部定义的变量。
- 特点:不同函数中的局部变量可以是相同的名字,它们之间不会相互影响。(C语言的语法相似)
- 作用:临时保存数据需要在函数中定义变量来进行存储
示例:
def test1():
a = 1
print("修改前:%d" % (a))
a = 2
print("修改后:%d" % (a))
def test2():
a = 3
print("修改前:%d" % (a))
test1()
test2()
"""
运行结果为:
修改前:a = 1
修改后:a = 2
修改前:a = 3
"""
1.2、全局变量
全局变量:
- 定义:在函数外面定义的变量是全局变量,每一个函数都可以使用。
- 特点:相同变量名称的时候,函数在调用的时候先使用局部变量。
C语言中全局变量必须定义在函数定义之前声明,在编译的时候告诉编译器,这个变量已经定义过了,而python的全局变量,对于变量定义的前后位置不做要求。python函数必须要在函数使用前定义(同C语言的规则相同),因为在编译时,要做正确性检查。
示例:
a = 10
def test1():
a = 20 # 局部变量
print("修改前a = %d" % a)
a = 30
print("修改后a = %d" % a)
def test2():
print("a = %d" % a) # 使用了全局变量
test1()
test2()
"""
运行结果为:
修改前a = 20
修改后a = 30
a = 10
"""
1.3、修改全局变量
全局变量在脚本中均可使用,但是在函数内无法进行修改。(除列表和字典数据类型的
+=
操作外)
在python中,定义一个变量和给变量赋值是相同的语法(这是与C语言的一个不同)。所以在函数内想要对全局变量进行赋值时,发现它就定义了一个局部变量。为了使得在函数内对全局变量进行修改,这时候就需要使用一个关键字global,通过global关键字对变量的声明,告诉解释器这个变量是全局变量。
a = 10 # 定义变量 or 变量赋值?
示例:
a = 10
def test1():
global a # 声明变量 a 是全局变量
print("a = %d" % a)
a = 20
print("a = %d" % a)
def test2():
print("a = %d" % a)
test1()
test2()
"""
运行结果为:
a = 10
a = 20
a = 20
"""
注意:int或者str型全局变量在函数内修改时,需要global修饰;如果是list或者dict,则在函数可以直接修改(仅限于单个元素修改)。
示例:
list1 = [1, 2] # 全部变量
list2 = [11, 22] # 全部变量
def test1():
list1[0] = 2 # 全部变量
return list1
def test2():
list2 = [33, 22] # 局部变量
return list2
print(test1())
print(list1)
print(test2())
print(list2)
"""
运行结果为:
[2, 2]
[2, 2]
[33, 22]
[11, 22]
"""
nonlocal与global的作用是相似的,不同点在于,global针对于全局变量在函数可被修改,nonlocal针对于函数内的变量在其嵌套的函数中可被修改。
示例:
def test1():
a = 1
def demo():
nonlocal a
print("a = %d" % a)
a = 20
print("a = %d" % a)
demo()
print(a)
test1()
"""
运行结果为:
a = 1
a = 20
20
"""
二、返回多个返回值
return 的作用是,函数执行到return时,立即跳出函数,函数后面的程序不执行
示例:
def num(a, b):
c = a + b
d = a - b
return c
print("---") # 为了测试第二个return是否被执行了
return d
c = num(20, 10)
d = num(20, 10)
print(c)
print(d)
"""
运行结果为:
30
30
"""
python中可以返回多个值:
# 格式
def 函数名(参数名1, 参数名2, .....):
函数执行代码
函数执行代码
.........
return 返回值1, 返回值2, ......
# 调用
依次存返回值变量1, 变量2, ... = 函数名(参数值1, ........)
示例:
def test1(a, b):
c = a + b
d = a - b
return c, d
num1, num2 = test1(20, 10)
print(num1, num2)
"""
运行结果为:
30 10
"""
三、缺省/不定长参数与引用传参
3.1、缺省参数
缺省参数:调用函数时,缺省参数的值如果没有传入,则被认为是默认值。
格式:def 函数名(参数名1,参数2=默认值,…参数n=默认值):
调用时:函数名(值1)
注意:带有默认值的参数一定要位于参数列表的最后面。
示例:
def user_info(name, age = 16):
print("name = %s" % name)
print("age = %d" % age)
user_info("小李")
user_info("小李", 20)
"""
运行结果为:
name = 小李
age = 16
name = 小李
age = 20
"""
3.2、不定长参数
格式:def 函数名(参数名1, *args, **kwarg):
调用时:函数名(值1)
注意:
- 加
*
表示args可以存放所有未命名的变量参数,args为元组。- 加
**
表示kwarg可以存放命名参数,即形如key=value的参数, kwargs为字典。
示例:
def num(a, b, *args, **kwargs):
print(a)
print(b)
print(args)
print(kwargs)
num(1, 2, 3, 4, 5, m = "1", n = 2)
"""
运行结果为:
1
2
(3, 4, 5)
{'m': '1', 'n': 2}
"""
3.3、引用传参
3.3.1、可变类型与不可变类型的数据类型
可变类型,值可以改变:
- 列表 (list)
- 字典 (dict)
不可变类型,值不可以改变:
- 数值类型 (int、long、bool、float)
- 字符串 (str)
- 元组 (tuple)
3.3.2、a += a 与 a = a + a 的区别
示例一:可变类型
a = [1,2,3]
print(id(a)) #打印内存地址
a += a
print(a)
print(id(a))
"""
运行结果为:
39060800
[1, 2, 3, 1, 2, 3]
39060800
"""
a = [1,2,3]
print(id(a)) #打印内存地址
a = a + a
print(a)
print(id(a))
"""
运行结果为:
38929728
[1, 2, 3, 1, 2, 3]
38941248
"""
可变类型:
+= :内存地址相同。
= : 内存地址不相同。
示例二:不可变类型
a = 10
print(a)
print(id(a))
a += a
print(a)
print(id(a))
"""
10
8791384971200
20
8791384971520
"""
a = 10
print(a)
print(id(a))
a =a + a
print(a)
print(id(a))
"""
10
8791348991936
20
8791348992256
"""
不可变类型:
+= :内存地址不相同。
= : 内存地址不相同。
小结:
- 如果a是一个可变类型,那么a += a 是在a指向的内存中直接修改,a = a+a 是指向了一个新的内存。
- 如果a是一个不可变类型,那么a += a 和a = a+a 的效果一样即:a指向了一个新的内存。
3.3.3、引用传参
python中函数参数是引用传递(注意不是值传递)。
- 对于可变类型来说,函数体中的运算有可能会更改传入的参数变量。
- 对于不可变类型,因变量不能修改,所以运算不会影响到变量自身。
示例一:可变类型
# a += a
def num(a):
print("函数内:")
print(id(a)) # 内存地址
a += a
print("a = %s" % a)
print(id(a))
print("函数外:")
a = [1, 2]
num(a)
print("a = %s" % a)
print(id(a))
"""
运行结果为:
函数内:
31196480
a = [1, 2, 1, 2]
31196480
函数外:
a = [1, 2, 1, 2]
31196480
"""
# a = a + a
def num(a):
print("函数内:")
print(id(a)) # 内存地址
a = a + a
print("a = %s" % a)
print(id(a))
print("函数外:")
a = [1, 2]
num(a)
print("a = %s" % a)
print(id(a))
"""
运行结果为:
函数内:
38995264
a = [1, 2, 1, 2]
39006784
函数外:
a = [1, 2]
38995264
"""
可变类型:
+= :实参与形参内存地址相同。
= : 实参与形参内存地址不相同。
示例二:不可变类型
# a += a
def num(a):
print("函数内:")
print(id(a)) # 内存地址
a += a
print("a = %d" % a)
print(id(a))
print("函数外:")
a = 10
num(a)
print("a = %d" % a)
print(id(a))
"""
运行结果为:
函数内:
8791384971200
a = 20
8791384971520
函数外:
a = 10
8791384971200
"""
# a = a + a
def num(a):
print("函数内:")
print(id(a)) # 内存地址
a = a + a
print("a = %d" % a)
print(id(a))
print("函数外:")
a = 10
num(a)
print("a = %d" % a)
print(id(a))
"""
运行结果为:
函数内:
8791384971200
a = 20
8791384971520
函数外:
a = 10
8791384971200
"""
不可变类型:
+= :内存地址不相同。
= : 内存地址不相同。
引用传参小结:
- 如果a是一个可变类型,那么a += a 是传引用,a = a+a 是传值。
- 如果a是一个不可变类型,那么a += a 和a = a+a 的效果一样即:传值。
四、递归函数与匿名函数
4.1、递归函数
递归函数:如果一个函数在内部不调用其它的函数,而是自己本身的话,这个函数就是递归函数。
示例:
def cal_num(n):
if n >= 1:
result = n * cal_num(n-1)
else:
result = 1
return result
ret = cal_num(3)
print(ret)
"""
运行结果为:
6
"""
4.2、匿名函数
匿名函数:用lambda关键词能创建小型匿名函数。这种函数得名于省略了用def声明函数的标准步骤。
特点:节省行数,用完就可以扔掉,简便。
注意:lambda函数的语法只包含一个语句。
格式:
lambda [arg1, [arg2,.....argn]]:expression
示例:
c = lambda a, b: a + b
print(c(1, 2))
"""
运行结果为:
3
"""
五、参考资料
[1]:Python笔记之nonlocal语句
[2]:Python当中的a += a 与 a = a + a 的区别,可变类型与不可变类型的数据类型,引用传参
[3]:python中a+=a与a=a+a的区别
[4]:python函数传参是传值还是传引用?
[5]:Python中的引用传参