一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天
全局变量和局部变量
形参和实参
全局变量和局部变量的定义
来个例子
a = 100 #全局变量
def test():
a = 0 #局部变量
print('a = ',a)
test()
def test1():
print('a = ',a)
test1()
以上两段函数可以看出第一段有局部变量,所以结果为局部变量a=0,第二段因为函数内部没有局部变量,所以结果会直接赋值为全局变量a=100
注意:
- 变量在给值得时候采用就近原则,若函数体内有局部变量就直接采用局部变量,若函数体内无局部变量便会采用全体变量。
- 局部变量只能在函数体内部运用,全局变量则可以都能使用
- 在函数体内部无法改变全局变量,即全局变量不参与函数体内部得运算(只可远观而不可亵玩焉)
- 若想在函数体内部对全局变量有动作,那么你可以在函数内部声明它是全局变量(即声明作用域)[针对的是不可变的类型]
可变类型和不可变类型
不可变:当我们改变变量值的时候,地址发生了改变(可以这样理解:当保持地址不变时,我们不能改变其内容)
| 数据类型 | 意义 |
|---|---|
| int | 整数 |
| float | 浮点数 |
| str | 字符串 |
| bool | 布尔数 |
| 元组 | tuple |
可变:当我们改变内部的内容,但地址没改变(我们可以这样理解:在保证地址不变时,我们可以改变里面内容)
| 数据类型 | 意义 |
|---|---|
| list | 列表 |
| dict | 字典 |
| set | 集合 |
函数的返回值
函数向外部返还的结果
格式:
def 函数名():
函数体
return 结果 #返回值
例子
def get_sum(*args):
total = 0
for i in args:
total += i
return total
t = get_sum(1,2,3)
以上我们称之为一个完整的函数结构,那么return只能返回一个值吗?
我们可以来试试这段代码
def get_max_min(number):
for i in range(0,len(number)-1):
for j in range (0,len(number)-1-i):
if number[j] > number[j+1]:
number[j],number[j+1] = number[j+1],number[j]
return number[0],number[-1]
a,b = get_max_min([1,2,5,6,3,4,8,6,8,9]) #拆包
print(a,b)
注意:以上我们会发现return可以同时返回两个值,以此类推,我们可以返回更多的值,这些值会被封装到一个元组中将元组作为整体返回,提高了函数的复用性。(只有python可以这样定义)
函数的注释
函数内部的注释可以更好的给我们提供一些参数信息
示例
def islogin(name, password):
'''
判断用户名和密码是否正确
:param name: 用户名
:param password: 密码
:return: True or False
'''
if name == 'admin' and password == '123456':
print('登陆成功')
return True
else:
print('登陆失败')
return False
注意:我们在函数内部写上注释后我们在调用函数的时候就可以得到函数的相应用法和提示
我们就会得到如图所示的效果
- 总结
def 函数名(参数1,参数2....):
基本注释:"注释内容"
高级注释:
'''
函数的说明
参数的说明
:param name: 用户名
:param password: 密码
返回值的说明
:return: True or False
'''
函数的引用
就是在传递值得时候直接将地址交付,而不是简单地传递一个值
- 引用一
sys.getrefcount()这个可以看引用次数
例子:
import sys
list1 = [1,2,3,4,5]
list2 = list1
list3 = list2
print(sys.getrefcount(list1))
>>> 4
del list1
print(sys.getrefcount(list2))
>>> 3 #注意这里可以证明传递得是地址
注意:python的垃圾回收机制是判断该变量有没有指针,若无指针则可能会被回收
- 参数的值传递(引用二)
类似于前面的全局变量和局部变量的关系
def sum(n1):
for i in range(0,n1):
print(i)
n1 += 1
n=9
sum(n)
print(n)
>>> 9
注意:这里有两种理解方式
- 因为int型是不可变参数,所以在对其作为全局变量时,在函数体内要进行global全局变量声明
- 因为我们这里有一个常量池,当n=n1=9时只是将n1指向的常量池中的9,而n1 += 1这个操作就是断开n1指向9的指针转而将n1的指针指向10这个常量
这里的两种理解其实归根结底就是可变类型和不可变类型的区别
函数的嵌套(闭包)
函数是一段可执行的代码,编译后就固化了,每一个函数在内存中只有一份实例,得到函数的入口点便可以执行函数,函数还可以嵌套定义,即在一个函数的内部嵌套另一个函数,有了嵌套函数这种结构体,便会产生闭包问题
- 函数嵌套的示例
def outer():
a = 100
def inner():
b = 200
b += a #内部函数可以使用外部函数的变量
nonlocal a #声明外部函数的变量
a += b #内部函数不能修改外部函数的变量
print(a,b)
result = locals() #这里的locals()表示查看函数中的局部变量,以字典的形式返回
print(result)
print(a)
inner()
outer()
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
{'inner': <function outer.<locals>.inner at 0x00000213C688F700>, 'a': 10}
100
300 300
注意:
-
这里的locals()表示查看函数中的局部变量,以字典的形式返回
-
内部函数不能修改外部函数的变量
-
内部函数可以使用外部函数的变量
-
nonlocal a 声明外部函数的变量
-
变量的寻找顺序:内部-->外部-->全局-->系统builtins
- 闭包
- 嵌套函数
- 内部函数引用了外部函数的变量
- 返回值是内部函数
闭包示例
def outer(n):
a = 10
def inner():
b = a + n
print('内置函数:',b)
return inner
result = outer(5)
print(result)
r()