*与**在形参与实参中的应用
一:可变长参数
可变长指的是参数的个数不固定。
站在实参的角度,实参是用来为形参赋值的,如果实参的个数不固定,那么必须要有对应的形参能够接收溢出实参。
==============>在形参中用*与**<==============
1.1 在形参名前加*:*会把溢出的位置实参存成元组,然后赋值其后的形参名
def func(x,*y): # y=(2,3,4)
print(x)
print(y)
func(1,2,3,4)
func(1)
func() # 位置形参x必须被传值
示范:
def add(*nums):
res = 0
for num in nums:
res += num
return res
res=add(1, 2, 3)
print(res)
1.2 在形参名前加**:**会把溢出的关键字实参存成字典,然后赋值其后的形参名
def func(x, **y): # y = {'a': 111, 'b': 222, 'c': 333}
print(x)
print(y)
func(1,a=111,b=222,c=333)
func(a=111, b=222, x=1, c=333)
=================>在实参中用*与**<====================
def func(x, y, z):
print(x, y, z)
1.3 在实参前加*:*会把其后的值打散成位置实参
nums = [1, 2, 3]
func(*nums) # func(1,2,3)
1.4 在实参前加**:**会把其后的值打散关键字实参
dic = {'y': 111, 'z': 222, 'x': 333}
func(**dic) # func(y=111,z=222,x=333)
============>在形参与实参中混用*与**<==============
def index(x,y,z,a,b,c):
print("index===>",x,y,z,a,b,c)
def wrapper(*args, **kwargs): # args=(1, 2, 3,) kwargs={"a":1,"b":2,"c":3}
index(*args, **kwargs) # index(*(1, 2, 3,),**{"a":1,"b":2,"c":3})
# index(1,2,3,c=3,b=2,a=1)
wrapper(1, 2, 3, a=111, b=222, c=333)
二、了解知识:命名关键字形参(**)
def func(x, y=222, *args, n=777,m, **kwargs): # m,n必须按照关键字实参的格式为其赋值
print(x) # 1
print(y) # 2
print(args) # (3,4,5)
print("m===>", m)
print("n===>", n)
print(kwargs)
# func(1,2,3,4,5,6666666)
# func(1,2,3,4,5,m=6666666)
func(1, 2, 3, 4, 5, n=88888,m=6666666, a=11, b=22, c=33)
三、函数对象
函数对象指的是函数可以被当成变量去使用
def foo(): # foo = 函数的内存地址
print('from foo')
1、 可以被赋值
f = foo
print(f is foo) # 返回值为True
f()
2、 可以当作参数传给一个函数
def bar(func):
print(func)
func()
bar(foo)
3、 可以当成一个函数的返回值
def bar(func):
return func
res=bar(foo)
print(res)
4、 可以当成容器类型的元素
l = [foo]
print(l)
l[0]()
示例:
def login():
print('登录功能......')
def withdraw():
print('提现功能......')
def transfer():
print('转账功能......')
def recharge():
print('充值功能')
func_dic={
"1": [login,"登录"],
"2": [withdraw,"提现"],
"3": [transfer,"转账"],
"4": [recharge,"充值"]
}
# func_dic["1"][0]()
while True:
print("0 退出")
for k in func_dic:
print("%s %s" %(k,func_dic[k][1]))
choice = input("请输入你的指令编号: ").strip()
if choice == "0":
break
if choice in func_dic:
func_dic[choice][0]()
else:
print('输入的指令不存在')
四、函数的嵌套
1、 函数的嵌套调用
def bar():
print('from bar')
def foo():
print('from foo')
bar()
foo()
# from foo
# from bar
案例:
# 判断四个数中最大的
def max2(x,y):
if x > y:
return x
else:
return y
def max4(a,b,c,d):
res1 = max2(a,b)
res2 = max2(res1,c)
res3 = max2(res2,d)
print(res3)
max4(1,2,3,4)
2、 函数的嵌套定义
def f1():
print('from f1')
# f2 = 函数的内存地址
def f2():
print("from f2")
f1() # 并没有执行f2(),结果为 from f1
定义在函数内的函数特点是: 正常情况只能在函数体内调用
# 计算圆周长和面积
from math import pi
def circle(radius,mode=0):
def perimiter(radius):
return 2 * pi * radius
def area(radius):
return pi * (radius ** 2)
if mode == 0:
return perimiter(radius)
elif mode == 1:
return area(radius)
res1=circle(3,0)
res2=circle(3,1)
print(res1)
print(res2)
五、名称空间和作用域
名称空间: 就是存放名字的地方
1、 内置名称空间: 存放的是内置的名字,如print\input\len
生命周期: 解释器启动则产生,解释器关闭则销毁
2、 全局名称空间: 存放的是顶级的名字
生命周期: python程序运行时则产生,python程序结束则销毁
3、 局部名称空间:函数内的名字
生命周期: 调用函数时则产生,函数调用结束则销毁
名字的查找优先级:
1、 从当前位置往外查找,如果当前是在局部:局部名称空间->全局名称空间->内置名称空间
2、 从当前位置往外查找,如果当前是在全局:全局名称空间->内置名称空间
示范1:
def func():
len = 222
# print(len)
# len = 111
func()
print(len)
# 打印结果是python内置的input函数:<built-in function len>
一个非常重要的结论:名称空间的嵌套关系是函数定义阶段(即扫描语法时)就固定死的,与函数的调用位置无关
x = 111
def func():
print(x)
x=222
func()
# 此处运行报错,原因是
reason
1、全局范围/全局作用域:内置名称空间+全局名称空间
特点:全局存活,全局有效
2、局部范围/局部作用域:局部名称空间
特点:临时存活,局部有效
了解:
global(****): Python中定义函数时,若想在函数内部对函数外的变量进行操作,就需要在函数内部声明其为global。如果局部要对全局变量修改,则在局部声明该全局变量。
nonlocal(***):nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量,用于函数嵌套时使用
案例1
x = 10
def func(x): # x = 值10的内存地址
# x = 值10的内存地址
x = 20
func(x) # func(值10的内存地址)
print(x)
案例2
x = [11,22,33]
def func(x): # x = 列表[11,22,33]的内存地址
# x = 列表[11,22,33]的内存地址
# x=444444444444
x[0] = 66666
func(x) # func(列表[11,22,33]的内存地址)
print(x)
案例3
x = [11,22,33]
def func():
x[0] = 66666
func()
print(x)
案例4
x = 10
def func():
global x
x=22
func()
print(x)
案例5:nonlocal声明名字是来自于外层函数的(***)
x = 10
def f1():
x=111
def f2():
nonlocal x
x=222
f2()
print(x)
f1()
print(x)
网友评论