变量起作用的范围称为变量的作用域,不同作用域内同名变量之间互不影响,变量分为:
操作示例:
a=3 #全局变量
def test1():
b=1 #局部变量
print(b)
>>>print(a)
3
>>>print(b)
NameError: name 'b' is not defined
a=3 #全局变量
def test1():
b=1 #局部变量
a=300 # 在函数体中,优先使用与全局变量a同名的局部变量
print(a)
>>>test1()
300
>>>print(a)
3
a=3 #全局变量
def test1():
global a # 若想使用全局变量a的值,则需global声明
a=300
print(a)
>>>print(a)
300
>>>test1()
300
底层逻辑:
个人理解,在Python执行def命名时,在堆空间中创建了一个函数对象(包含所有相关的函数信息),随后将该对象的地址赋予栈空间中的函数名变量test1,即,test1指向堆空间中对应的函数对象,当用()调用函数时,Python会在栈空间中创建栈帧(Stack Frame),仅在栈帧内部放置局部变量,并执行函数体相关语句,在调用完毕后,栈帧被丢弃,等下一次调用时再次建立新的栈帧,以此往复
函数参数传递的本质是从实参到形参的赋值操作,Python中一切皆对象,所有的赋值操作都是“引用的赋值”,所以,参数传递的过程是“引用传递”的过程,而不是“值传递”的过程
传递参数是可变对象(列表、字典、集合、自定义对象等),实际传递的还是对象的引用。在函数体中不创建新的对象拷贝,而是直接修改所传递的对象
操作示例:
'''
传递可变对象的引用
'''
b=[10,20]
def f2(m):
print("m:",id(m)) # b和m指向同一个对象
m.append(30) # 由于m是可变对象,不创建对象拷贝,直接修改这个对象(即列表)
f2(b)
print("b:",id(b)) # id(b)与id(m)的结果一致
传递参数是不可变对象(例如字符串,元组,布尔值,数字等),实际传递的还是对象的引用,在传递时,由于不可变对象无法修改,系统会创建一个新的对象
操作示例:
'''
传递不可变对象的引用
'''
a=100
def f1(n):
print("n:",id(n)) # 传递的是a所指向的对象的地址
n=n+200 # 由于100是不可变对象,因此会创建新的对象
print("n:",id(n)) # n指向新的对象,对象值为300
f1(n)
print("a:",id(a))
'''
结果为:
1663816464
46608592
1663816464
'''
函数调用时,实参默认按位置顺序传递,需要个数和形参匹配,按照位置传递的参数,称为位置参数
操作示例:
'''
位置参数
'''
def f(a,b,c):
print(a,b,c)
>>>f(2,3,4) # 位置匹配
>>>f(2,3) # 报错,位置不匹配
我们可以为某些参数设置默认值,这些参数在传递时就是可选的,称为默认值参数,默认值参数必须位于其它参数后面
操作示例:
'''
默认值参数
'''
def f(a,b,c=10): # c就是默认值参数
print(a,b,c)
>>>f(8,9)
8 9 10
>>>f(8,9,19)
8 9 19
我们也可以按照形参的名称传递参数,称为命名参数,也称关键字参数
操作示例:
'''
命名参数(关键字参数)
'''
def f1(a,b,c):
print(a,b,c)
>>>f1(7,7,8) # 按位置传递,位置参数
7 7 8
>>>f1(c=9,b=1,a=3) # 按形参的名称传递,命名参数
3 1 9
可变参数称为可变数量的参数,分两种情况:
操作示例:
'''
可变参数
'''
def f(a,b,*c):
print(a,b,c)
>>>f(8,9,29,2)
8 9 (29, 2)
'''
可变参数
'''
def f(a,b,**c):
print(a,b,c)
>>>f(8,9,i=100,j=200)
8 9 {
'i': 100, 'j': 200}
在带星号的可变参数后面增加新的参数,必须是强制命名参数
操作示例:
'''
强制命名参数
'''
def f(*a,b,c):
print(a,b,c)
>>>f(2,3,4) # 报错,因为a是可变参数,会把实参全部收集为元组,导致b,c没有赋值
>>>f(2,b=3,c=4)
(2,) 3 4
基本语法:
lambda arg1,arg2,arg3…: <表达式>
arg是函数的参数,<表达式>相当于函数体,运算结果就是函数的返回值
操作示例:
'''
lambda表达式
'''
f=lambda a,b,c:a+b+c
>>>f(2,3,4)
9
这一块内容在此只做简单阐释,具体内容将在数据结构与算法篇呈现。
递归函数指的是:自己调用自己的函数,在函数体内部直接或间接地自己调用自己。递归需要包含两个部分:
递归函数会创建大量函数对象,大量消耗内存和运算能力,处理大量数据时应谨慎使用
操作示例:
'''
递归计算阶乘
'''
def factorial(n):
if n==1:
return 1
else:
return n*factorial(n-1)
>>>factorial(5)
120