当系统开始执行函数时,系统对形参执行初始化,是把实参的值赋给函数的形参,在函数中操作的并不是实际的实参变量
a = 10
b = 16
def swap(a , b) : # 该函数实现交换a、b变量的值
a, b = b, a
print("在函数里经过交换后,a的值是",a,"b的值是",b)
swap(a , b)
print("执行函数之后,变量a的值是",a,"变量b的值是",b)
在函数里经过交换后,a的值是 16 b的值是 10
执行函数之后,变量a的值是 10 变量b的值是 16
程序中实际定义的变量 a 和 b,并不是 swap()函数里的 a 和 b
1. 程序开始定义了 a、b 两个变量
2. 当在主程序中调用swap()函数时,系统分别为主程序和swap()函数分配两块栈区,用于保存它们的变量
3. 将主程序中的a、b变量作为参数值传入swap()函数,实际是在swap() 函数栈区中重新产生了两个变量a、b,并将主程序栈区中a、b 变量的值分别赋值给 swap()函数栈区中的a、b参数
4. 系统存在两个a变量、两个b变量,存在于不同的栈区
5. 在swap()函数中交换a、b两个变量的值,实际上是对swap()函数栈区的a、b 变量进行交换,交换结束后,输出swap() 函数中a、b变量的值
6. 主程序栈区中 a、b 的值并未有任何改变,改变的只是swap()函数栈区中 a、b 的值
参数的数据类型是可变对象(列表、字典),则函数的参数采用引用传递
引用传递方式的底层实现,采用的还是值传递
a_dict = {
'a': 10, 'b': 16}
def swap(a_dict):
a_dict['a'],a_dict ['b'] =a_dict ['b'], a_dict['a'] #实现字典的a、b两个元素的值交换
print("swap函数里,a的值是",a_dict['a'], "b的值是", a_dict['b'])
swap(a_dict)
print("交换结束后,a的值是",a_dict['a'], "b的值是", a_dict['b'])
swap函数里,a的值是 16 b的值是 10
交换结束后,a的值是 16 b的值是 10
在执行swap()函数后 a、b 的值被交换,主程序中字典的a、b的值也被交换了
- 创建了一个字典对象,并定义了一个a_dict引用变量(指针)指向字典对象,此时内存中:对象本身和指向该对象的引用变量
- 主程序调用swap()函数,把a_dict变量作为参数传入swap()函数,采用值传递
- 主程序中的a_dict是一个引用变量(指针),保存了字典对象的地址值,值传递后让swap()函数的a_dict参数也保存这个地址值,引用到同一个字典对象图
- swap()函数中a_dict只是一个引用变量,实际操作的还是字典对象,主程序和swap() 函数引用的是同一个字典对象。所以在swap()函数中交换字典对象的 a、b的值后,主程序中所引用字典对象的a、b的值也被交换
在 Python 函数中对参数直接使用“=”符号赋值并不能改变参数
通过把数据包装成列表、字典等可变对象,然后把可变对象作为参数传入函数,在函数中通过列表、字典的方法修改它们,从而改变这些数据
作用域(Scope),变量的有效范围,就是变量可以在哪个范围内使用
变量的作用域由变量的定义位置决定,在不同位置定义的变量,作用域不一样
局部变量(Local Variable)
在函数内部定义的变量,作用域仅限于函数内部
def test():
name = "youchanwill"
print("函数内部",name)
test()
print("函数外部",name)
函数内部 youchanwill
NameError: name 'name' is not defined #在函数外部访问其内部定义的变量,解释器会报NameError错误
当函数被执行时,会为其分配临时的存储空间,所有在函数内部定义的变量,都会存储在这块空间中
在函数执行完后,临时存储空间会被释放,其内部定义的变量会被销毁并回收
def test(name):
print("函数内部",name)
test("youchanwill")
print("函数外部",name)
函数内部 youchanwill
NameError: name 'name' is not defined
函数的参数也属于局部变量,只能在函数内部使用
*Python解释器逐行运行程序代码
全局变量(Global Variable)
在所有函数的外部定义变量
在函数体外定义的变量,一定是全局变量
在函数内部定义全局变量,使用global关键字对变量进行修饰后,该变量就会变为全局变量
def test():
global name
name = "youchanwill"
print("函数内部",name)
test()
print("函数外部",name)
函数内部 youchanwill
函数外部 youchanwill
使用global关键字修饰变量名时,不能直接给变量赋初值,否则会引发语法错误
获取某个作用域内(全局范围或局部范围)所有的变量
globals()
返回一个包含全局范围内所有变量的字典,该字典中的每个key-value对,key为变量名,value为该变量的值
def test():
name = "youchanwill"
print("函数内部",name)
print(globals())
{
.... 'test': <function test at 0x02A15810>....}
globals() 函数返回的字典中,会默认包含有很多变量,都是Python主程序内置的
通过该字典,还可以访问指定变量,如果需要,还可以修改值
name = 'you'
print(globals()['name'])
globals()['name'] = "youchanwill"
print(name)
you
youchanwill
locals()
到一个包含当前作用域内所有变量的字典,在函数内部调用locals()函数,会获得包含所有局部变量的字典,在全局范围内调用功能和globals()函数相同
name1 = 'you'
def test():
name = "youchanwill"
print(locals())
test()
print(locals())
{
'name': 'youchanwill'}
{
... 'name1': 'you', 'test': <function test at 0x02995810>...}
使用locals()函数获取所有全局变量时,和globals()函数一样,其返回的字典中会默认包含有很多变量
使用locals() 函数获得所有局部变量组成的字典时,可以像globals()函数那样通过指定键访问对应的变量值,但无法对变量值做修改
vars()
返回一个指定object对象范围内所有变量组成的字典,如果不传入object参数则和locals()的作用完全相同
name1 = 'you'
class test:
name = "youchanwill"
print(vars(test))
print(vars())
{
...'name': 'youchanwill'...}
{
... 'name1': 'you'...}
类(class): 用来描述具有相同的属性和方法的对象的集合,后续会学习到
在函数内部定义函数,此类函数称为局部函数
def outdef (): #全局函数
def indef(): #局部函数
print("youchanwill")
indef() #调用局部函数
outdef() #调用全局函数
youchanwill
默认情况下局部函数只能在其所在函数的作用域内使用
通过将局部函数作为所在函数的返回值,可以扩大局部函数的使用范围
def outdef (): #全局函数
def indef(): #局部函数
print("youchanwill")
return indef #局部函数作为返回值
new_indef = outdef() #调用全局函数中的局部函数
new_indef()
youchanwill
所在函数没有返回局部函数,局部函数的可用范围仅限于所在函数内部
所在函数将局部函数作为返回值,则局部函数的作用域就会扩大,可以在所在函数的作用域中使用
def outdef (): #全局函数
name = "所在函数中定义的 name 变量"
def indef(): #局部函数
print(name)
name = "局部函数中定义的name变量"
indef()
outdef() #调用全局函数
UnboundLocalError: local variable 'name' referenced before assignment
局部函数中定义的变量遮蔽了所在函数中定义的变量
indef()函数中name变量的定义位于print()输出语句之后,导致 print(name) 语句在执行时找不到定义的name变量
使用nonlocal关键字解决上述问题
def outdef (): #全局函数
name = "所在函数中定义的 name 变量"
def indef(): #局部函数
nonlocal name #使用nonlocal关键字
print(name)
name = "局部函数中定义的name变量"
indef()
outdef() #调用全局函数
所在函数中定义的 name 变量
直接将函数赋值给其它变量,在程序中可以用其他变量来调用该函数,更加灵活
def a_def ():
print("执行a_def函数")
b_def = a_def #将函数赋值给其他变量
b_def() #间接调用a_def() 函数
执行a_def函数
支持将函数以参数的形式传入其他函数中
def add (a,b):
return a+b
def multi(a,b):
return a*b
def a_def(a,b,add_multi):
return add_multi(a,b)
print(a_def(10,16,add))#求 2 个数的和
print(a_def(10,16,multi)) #求 2 个数的乘积
26
160
通过使用函数作为参数,可以在调用函数时动态传入函数,实现动态改变函数中的部分实现代码,在不同场景中赋予函数不同的作用
支持函数的返回值也为函数,通过返回值为函数的形式,可以扩大局部函数的作用域
def outdef (): #全局函数
def indef(): #局部函数
print("youchanwill")
return indef #局部函数作为返回值
new_indef = outdef() #调用全局函数中的局部函数
new_indef()
youchanwill
lambda表达式(匿名函数)常用来表示内部仅包含 1 行表达式的函数
如果一个函数的函数体仅有1行表达式,就可以用 lambda 表达式来代替
name = lambda [list] : 表达式
定义lambda 表达式,必须使用lambda 关键字
[list] 为可选参数,等同于定义函数是指定的参数列表
value 为该表达式的名称
该语法格式转换成普通函数的形式:
def name(list):
return 表达式
name(list)
def multi(a,b):
return a*b
print(multi(10,16))
multi = lambda x,y:x*y
print(multi(10,16))
lambda 表达式,就是简单函数的简写版本
对于单行函数,使用 lambda 表达式可以省去定义函数的过程,让代码更加简洁
对于不需要多次复用的函数,使用 lambda 表达式可以在用完之后立即释放,提高程序执行的性能