函数的其他关键点*与**,函数的对象可以当做变量去使用,函数的嵌套,名称空间

今日内容

1.*与**在形参与实参中的应用

可变长参数

  • 可变长指的是参数的个数不固定
  • 站在实参角度,实参是用来为形参赋值的,如果实参的个数不固定,那么必须要有对应的形参能够接受溢出实参

1.1在形参名前加*

  • *会把溢出的位置实参存成元组,然后赋值其后的形参名
def func(x,*y): #y=(2,3,4)  元组
    print(x)
    print(y)
   
func(1,2,3,4)         #y=(2,3,4)  元组
func(1)               #y=()  空元组
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=(2,3,4)
    print(x)
    print(y)


func(1,a=111,b=222,c=333)
func(a=111, b=222, x=1, c=333)

1.3 在实参前加*:

  • 会把其后的值打撒成位置实参
 def func(x, y, z):
     print(x, y, z)
 nums = [1, 2, 3]

 func(*nums)  # func(1,2,3)

1.4在实参前加**:

  • **会把其后的值打散成关键字实参
 def func(x, y, z):
     print(x, y, z)

 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)

2.函数对象指的是函数可以被当成变量去使用

def foo():  # foo = 函数的内存地址
    print('from foo')

2.1 可以被赋值

f = foo
print(f is foo)
f()

2.2 可以当作参数传给一个函数

def bar(func):
    print(func)
    func()
bar(foo)

2.3 可以当成一个函数的返回值

def bar(func):
    return func
res=bar(foo)
print(res)

2.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('输入的指令不存在')

3.函数的嵌套

def bar():
    print('from bar')

def foo():
    print('from foo')
    bar()

foo()

3.1 调用

#调用的案例
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)

3.1 定义

  • 定义在函数内的函数特点是: 正常情况只能在函数体内调用
def f1():
    print('from f1')
    # f2 = 函数的内存地址
    def f2():
        print("from f2")

f1()

圆面积和周长的嵌套示例

from math import pi # 取他人已经做好的pi 也就是去π

def circle(radius,mode=0):#需要输入的值,其中radius就是半径值,mode的意思就是默认为0,如果用户不输入就一直是0,如果输入就只能输入0/1.
    def perimiter(radius):#函数一
        return 2 * pi * radius
    def area(radius):#函数二
        return pi * (radius ** 2)
    if mode == 0: #如果用户输入为0 则执行rimiter
        return perimiter(radius)
    elif mode == 1:# 如果用户输入为1 则执行radius
        return area(radius)

res1=circle(3,0)
res2=circle(3,1)
print(res1)
print(res2)

4.名称空间

  • 名字的查找优先级:
  • **从当前位置往外查找,如果当前是在局部:**局部名称空间->全局名称空间->内置名称空间
  • **从当前位置往外查找,如果当前是在全局:**全局名称空间->内置名称空间

4.1内置名称空间:

  • 存放的是内置的名字 ,如print\input\len

  • 生命周期: 解释器启动则产生,解释器关闭则销毁

4.2 全局名称空间:

  • 存放的是顶级的名字

  • 生命周期: python程序运行时则产生,python程序结束则销毁

4.3局部名称空间:

  • 函数内的名字

  • 生命周期: 调用函数时则产生,函数调用结束则销毁

  • #   名称空间可以理解为一层套一层的关系,问题是嵌套关系是在函数定义阶段生成的,还是在函数调用阶段生成的???
    #   一个非常重要的结论:名称空间的嵌套关系是函数定义阶段(即扫描语法时)就固定死的,与函数的调用位置无关
    
4.1

x = 111

def foo():
    print(x)
def bar(f):
    x=222
    f()
    
4.2

bar(foo)

x = 111
def func():
    print(x)
    x=2222
func()

练习一

# x=0
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(4*)
  • nonlocal(3*)
案例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)
posted @ 2020-07-20 18:53  Orange-ONE  阅读(129)  评论(0)    收藏  举报