四、global和nonlocal、函数名应用、格式化输出
-
形参角度,默认参数的坑
如果你的默认参数指向的是可变的数据类型,那么你无论调用多少次这个默认参数,都是同一个
# 默认参数的陷阱:
def func(name,sex='男'):
print(name)
print(sex)
func('alex')
#结果:
alex
男
# 陷阱只针对于默认参数是可变的数据类型:
def func(name,alist=[]):
alist.append(name)
return alist
ret1 = func('alex')
print(ret1,id(ret1))
ret2 = func('太白')
print(ret2,id(ret2))
#结果:共用一个列表
['alex'] 2289216485128
['alex', '太白'] 2289216485128
# 如果你的默认参数指向的是可变的数据类型,那么你无论调用多少次这个默认参数,都是同一个。
def func(name,alist=[]):
alist.append(name)
return alist
print(func(10,)) # [10,]
print(func(20,[])) # [20,]
print(func(100,)) # [10,100]
# print(func(20,[]))是name传值为10,alist传值为[],等同于新建立一个列表,不与print(func(10,))建立的列表用一个;print(func(100,)) 没有建立新列表,与print(func(10,))建立的列表用一个
# 相当于以下代码:
# l1 = []
# l1.append(10)
# print(l1)
# l2 = []
# l2.append(20)
# print(l2)
# l1.append(100)
# print(l1)
# 与上个代码对比:
def func(a, list= []):
list.append(a)
return list
ret1 = func(10,) # ret1 = [10,]
ret2 = func(20,[]) # ret2 = [20,]
ret3 = func(100,) # ret3 = [10,100]此时因为ret1用同一个列表,所以ret1也改变
print(ret1) # [10,100] (与上个代码对比,此处ret1没先打印,因而被ret3改变,然后打印)
print(ret2) # [20,]
print(ret3) # [10,100]
-
局部作用域的坑
在函数中,如果你定义了一个变量,但是在定义这个变量之前对其引用了,那么解释器认为:语法问题,你应该在使用之前先定义
count = 1
def func():
print(count)
count = 3
func()
# 代码在print(count)处飘红,local variable 'count' referenced before assignment,就是赋值前引用的本地变量“count”
二、
-
-
global:
-
在局部作用域声明一个全局变量
name = 'alex'
def func():
name = '太白'
print(name)
func()
print(name)
# 结果:
太白
alex
# 还是以上代码加入global,
name = 'alex'
def func():
global name
name = '太白'
print(name)
func()
print(name)
# 结果:
太白
太白
name = 'alex'
def func():
global name
name = '太白金星'
print(name) #alex
print(globals()) #获取全局变量
func()
print(name) #太白金星
print(globals() #获取全局变量 -
修改一个全局变量
count = 1
def func():
#print(count) ,报错,在全局声明之前使用名称“count”
global count
count += 1
print(count) # 1
func()
print(count) # 2
#将全局变量的count = 1,在函数中改成了2
-
-
nonlocal:
-
不能够操作全局变量
count = 1
def func():
nonlocal count
count += 1
func()
# 会报错,nonlocal是不能用来操作全局变量的 -
局部作用域:内层函数对外层函数的局部变量进行修改
def wrapper():
count = 1
def inner():
nonlocal count
count += 1
print(count) # 1
inner()
print(count) # 2
wrapper()
-
-
三、函数名的运用
-
函数名指向的是函数的内存地址,函数名+()就可执行此函数
-
函数名就是变量
-
函数名可以作为容器类数据类型内容的元素
-
函数名可以作为函数的参数
-
函数名可以作为函数的返回值
#1.函数名指向的是函数的内存地址
def func():
print(666)
func()
#2.函数名就是变量
def func():
print(666)
f = func
f1 = f
f2 = f1
f() #相当于func() 666
func() #相当于func() 666
f1() #相当于func() 666
f2() #相当于func() 666
def func():
print('in func')
def func1():
print('in func1')
func1 = func
func1() #相当于func() in func
#3.函数名可以作为容器类数据类型的元素
def func1():
print('in func1')
def func2():
print('in func2')
def func3():
print('in func3')
l1 = [func1,func2,func3]
for i in l1:
i()
#结果依次调用 func1,func2,func3
in func1
in func2
in func3
#4.函数名可以作为函数的参数
def func(a):
print(a)
print('in func')
b = 3
func(b)
print(func)
def func():
print('in func')
def func1(x):
x()
print('in func1')
func1(func)
# #5.函数名可作为函数的返回值
def func():
print('in func')
def func1(x):
print('in func1')
return x
ret = func1(func)
ret()
四、新特性:格式化输出(3.6x以后的适用)
可以加表达式,可以结合函数写:
# %s format
# name = '太白'
# age = 18
# msg = '我叫%s,今年%s' %(name,age)
# msg1 = '我叫{},今年{}'.format(name,age)
# 新特性:格式化输出
name = '太白'
age = 18
msg = f'我叫{name},今年{age}'
print(msg)
count = 7
print(f'最终结果:{count**2}')
name = 'barry'
msg = f'我的名字是{name.upper()}'
print(msg)
#加表达式:
dic = {'name':'alex','age':13}
msg = f'我叫{dic["name"]},今年{dic["age"]}'
print(msg)
#结合函数:
def _sum(a,b):
return a+b
msg = f'最终结果为:{_sum(10,20)}'
print(msg)
# ! , : { } ;这些标点不能出现在{} 这里面。
优点:
-
结构更加简化
-
可以结合表达式、函数进行使用
-
效率提升很多
-
-