1.可变长的参数
# *与**在形参与实参中的应用
# 1.可变长参数
# 可变长指的是参数的个数不固定
# 站在实参的角度,实参是为形参赋值的,如果实参的个数不固定,那么必须要有对应的形参能够接受溢出的实参
# 在形参名前加一个*: *会把溢出的实参存成元组,然后赋值给其后的形参名
def func(x, *y):
print(x)
print(y)
func(1, 2, 3, 4)# y = 2,3,4
func(1)# y = ()
# func() #位置形参x必须被传值
# 示范:
def add(*nums):
res =0
for numin nums:
res += num
return res
res = add(1, 2, 3)
print(res)
# 1.2在形参名前加**:**会把溢出的关键字实参存成字典,然后赋值给其后的形参名
def func(x, **y):
print(x)
print(y)
func(1, a=11, b=22, c=33)# y = {'a': 11, 'b': 22, 'c': 33}
func(a=11, b=22, c=33, x=1)# y = {'a': 11, 'b': 22, 'c': 33}
# =================>在实参中用*于**<========================
# 1.3在实参前加*: *会把后面的值打散成位置实参
def func(x, y, z):
print(x, y, z)
nums = [1, 2, 3]
func(*nums)# 这里就把列表nums打散成位置实参与位置形参想,与位置形参x,y,z一一对应
# 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":111,"b":222,"c":333} 先压缩
index(*args, **kwargs)# index(*(1, 2, 3,),**{"a":111,"b":222,"c":333}) 在解压
# index(1,2,3,c=333,b=222,a=111)
# index===> 1 2 3 111 222 333 会输出最原始元素格式
wrapper(1, 2, 3, a=111, b=222, c=333)
# def func(x,y=222,*args,**kwargs):
# pass
# 命名关键字形参(**)
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)
2.函数对象
# 函数对象指的是函数可以被当成变量去使用
def foo():
print('from foo')
# 1.可以被赋值
f = foo
print(fis foo)
f()
# 2.可以当做参数传给一个函数
def bar(func):
print(func)
func()# ()的作用是调用函数 ,没有括号就是调用函数名
bar(foo)
# 3.可以当成一个函数的返回值
def bar(func):
return func
res = bar(foo)
print(res)# 这个返回的是函数名的ID
# 4.可以当成容器类型的元素
l = [foo]
print(l)# 打印ID
l[0]()# 调用函数
# 示例
login_user =None
name ='Hans'
pwd ='123'
def lohin():
print('登录功能。。。')
inp_name =input('name>>')
ino_pwd =input('password>>')
if inp_name == nameand ino_pwd == pwd:
print('登录成功')
global login_user
login_user =True
else:
print('登录失败')
def withdraw():
print('提现功能。。。')
def transfer():
print('转账功能。。。')
def recharge():
print('充值功能。。。')
func_dic={# 功能和函数名写入一个字典方便调用
'1':[lohin,'登录'],
'2':[withdraw,'提现'],
'3':[transfer,'转账'],
'4':[recharge,'充值']
}
while True:
print('0 退出')
for kin func_dic:
print('%s %s'%(k,func_dic[k][1]))
num =input('请输入你的指令编号》》').strip()
if num =='0':
login_user =False
break
if numin func_dic:
if login_useris True:
func_dic[num][0]()# 输入什么代号就在后面加()来调用函数
else:
print('请先登录')
func_dic['1'][0]()
else:
print('指令不存在')
3.函数嵌套
# 1函数嵌套调用
def bar():
print('bar')
def foo():
print('foo')
bar()
foo()
# 案例:
def max2(x,y):# 先写一个两两比较的函数
if x>y:
return x
def max4(a,b,c,d):# 求四个数的最大值 在其中调用小函数
res1 = max2(a,b)
res2 = max2(res1,c)
res3 = max2(res2,d)
print(res3)
max4(21,548,88,566)
# 2 函数嵌套定义
def f1():
print('f1')
# f2 = 函数的内存地址
def f2():
print('f2')
f2()
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: # 模式0是算周长
# return perimiter(radius)
# elif mode == 1: # 模式1是算面积
# return area(radius)
#
# res1=circle(3,0)
# res2=circle(3,1)
# print(res1)
# print(res2)
#
def func():
x =10
print(x)
def f2():
print('from f2')
f2()
func()
print(x)# 无法引用函数内的变量 会直接报错
4.名称空间与作用域
# 一 名称空间: 就是存放名字的地方
# 1 内置名称空间: 存放的是内置的名字,如print\input\len
# 生命周期: 解释器启动则产生,解释器关闭则销毁
# 2 全局名称空间: 存放的是顶级的名字
# 生命周期: python程序运行时则产生,python程序结束则销毁
# x = 10 # 放在全局名称空间
#
# def func(): # 在全局名称空间
# x = 111 # 在局域名称空间
# print(x)
#
#
# if 1:
# y = 6666 # 这里的y是全局名称空间
# 3 局部名称空间:函数内的名字
# 生命周期: 调用函数时则产生,函数调用结束则销毁
# 名字的查找优先级:
# 从当前位置往外查找,如果当前是在局部:局部名称空间->全局名称空间->内置名称空间
# 从当前位置往外查找,如果当前是在全局:全局名称空间->内置名称空间
# 示范1:
# def func():
# len = 222
# # print(len)
#
# # len = 111
#
# func() # 222
#
# print(len) # 111
# 名称空间可以理解为一层套一层的关系,问题是嵌套关系是在函数定义阶段生成的,还是在函数调用阶段生成的???
def foo():
print(x)
def bar(f):
x=222
f()# 调用
x =111
bar(foo)# foo这个函数找到的x是全局变量的x
# 一个非常重要的结论:名称空间的嵌套关系是函数定义阶段(即扫描语法时)就固定死的,与函数的调用位置无关
# x = 111
# def func():
# print(x) # 报错
# x=2222
#
# func()
# 练习
# x=0 # 通过注释不同的x赋值会带来不同的结果
# def f1():
# x=1
# def f2():
# x=2
# print(x)
#
# f2()
#
# f1()
# len = 111
#
# def f1():
# len=2222
#
# def f2():
# len=3333
#
# f1()
# f2()
# 全局范围/全局作用域:内置名称空间+全局名称空间
# 特点:全局存活,全局有效
# 局部范围/局部作用域:局部名称空间
# 特点:临时存活,局部有效
# 了解:
# global(****)
# 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 # 面对不可变类型 只能用global来修改全局名称空间的变量
# 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)