函数对象

函数对象

函数是第一类对象:即函数可以被当做数据处理。

def func():
    print('from func')

print(func)

<function func at 0x00B46858>

一、函数对象的四大功能

1、函数名可以被引用

def func():
    print('from func')

f = func  # 函数名被引用
f()  # from func

2、函数名可以被当做参数传递给其他函数

def func():
    print('from func')

def deco(args):
    print(args)  # <function func at 0x00D66858>
    args()  # from func
    print('from index')  # from index
deco(func)  # 当做参数传递

3、函数名可以当做其他函数的返回值

def deco():
    print('from deco')

def func():
    print('func')  
    return deco
res = func()  # func
print(res)  # <function deco at 0x00CF6858>
res()  # from deco

4、函数名可以当做容器类型的元素

def func():
    print('from func')

print(func())  # None


l = [1,2,func,func()]
print(l)  # [1, 2, <function func at 0x01776858>, None]
def register():
    username = input('username>>>:').strip()
    pwd = input('password>>>>:').strip()
    print(username,pwd)
    print('register....')

def login():
    print('login...')

def transfer():
    print('transfer...')

def shopping():
    print('shopping...')

def pay():
    print('pay....')

func_msg = """
1 注册
2 登录 
3 转账
4 付款
q 退出
"""
func_dict = {
    '1':register,
    '2':login,
    '3':transfer,
    '4':pay,
}
while True:
    print(func_msg)
    choice = input('请选择你想要的功能').strip()
    if choice == 'q':
        break

    func = func_dict.get(choice)
    if func:
        func()
    else:
        print('你想要的功能暂时没有')

函数的嵌套调用

函数的调用

在函数内部调用其他函数,是为了使用函数的功能,将复杂的逻辑简单化。

def index():
    func()
    print('index')
def func():
    print('func')

index()
def my_max(x,y):
    if x > y:
        return x
    return y

def my_max4(a,b,c,d):
    res1 = my_max(a,b)
    res2 = my_max(res1,c)
    res3 = my_max(res2,d)
    return res3

print(my_max4(1,6,8,0))  # 8

函数的嵌套

函数的嵌套是为了用户通过一个函数的操作,实现不同的功能。比如ATM自动取款机。

def outer():
    x = 1
    print('outer')
    def inner():
        print('inner')
    return inner

res = outer()  # outer
res()  # inner
func_msg = {
    0:'注册',
    1:'登录',
    2:'购物',
}
def all_func(number):

    def register():

        print('register')

    def login():

        print('login')

    def transfer():

        print('shopping')
    func_dict = {
        0:register,
        1:login,
        2:transfer,
    }
    fun_choice = func_dict.get(choice)
    fun_choice()
while True:
    print(f'请选择{func_msg}')
    choice = int(input('请输入你的选择?>>>>').strip())
    all_func(choice)

名称空间与作用域

函数内部的函数只能在函数内部调用,不能在函数外部调用。

def deco():
    def func():
        print('from func')

    func()

func()  # name 'func' is not defined

一、名称空间

简单来说就是存放名字的地方。

名称空间就是存放变量名与变量值的内存地址的绑定关系的地方。

要想访问一个变量的值,必须先去名称空间中拿到对应的名字,才能够访问变量的值

1.1、 内置名称空间

python解释器提前给你定义好的名字(已经存放到内置名称空间中了),如len、print、int

生命周期:只要python解释器启动就会生效,关闭python解释器时失效。

1.2、 全局名称空间

文件级别的代码

x = 1
if 1==1:
    y == 2
print(y)
while True:
    z = 3

x,y,z都会放到全局名称空间,if for while,无论嵌套多少层,它们内部创建的名字都是全局名称空间的。

生命周期:py文件执行时生效,在py文件执行结束后失效。

1.3、局部名称空间

函数体内部创建的名字都属于局部名称空间

生命周期:函数被调用的时候生效,函数运行结束失效。

1.4、程序的执行顺序(加载顺序)

名称空间的执行顺序为:内置——全局——局部

1.5、查找顺序

查找顺序为:从当前的所在位置开始查找,如果当前所在的位置为局部名称空间,则顺序为:局部——全局——内置

x = 111
def f1():
    x = 222
    def f2():
        x = 333
        def f3():
            # x = 444
            def f4():
                # x = 555
                print(x)
            # x = 777
            f4()
            x = 777
        f3()
    f2()
f1()  # free variable 'x' referenced before assignment in enclosing scope
# x先从f4函数内部开始找,发现没有,就到f3函数内部开始找,发现f4里面有一个x = 777,但是要想传递给x,必须得先执行f4()函数,f4函数内部没有x,就会往外部寻找,一直循环,知道报错。(能看到葡萄但是吃不到葡萄)

函数在定义阶段查找名字的顺序已经被固定了,不会因为函数的调用位置变化而改变。

x = 111
def outer():
    def inner():
        print('from inner',x)
    return inner
f = outer()
x = 222
f()  # from inner 222
# x的查找顺序,先在inner函数内部开始查找,发现没有,之后在外部开始查找,这个外部是x=222
x = 111
def outer():
    def inner():
        print('from inner',x)
    return inner
f = outer()
def func():
    x = 333
    f()
func()  # from inner 111
# x的查找顺序,就是outer函数和inner函数执行后,x的查找顺序,发现在外部,x=111
x = 111
def outer():
    def inner():
        print('from inner',x)
        x = 666666
    return inner
f = outer()
f()  # UnboundLocalError: local variable 'x' referenced 
# x的查找顺序,先从本身开始查找,发现有x=66666,但是取不到。会提示报错

二、作用域

2.1、全局作用域

全局作用域:全局有效,全局存活,包含内置名称空间和全局名称空间。

2.1、局部作用域

局部作用域:局部有效,临时存储,只包含局部名称空间。

2.3、注意点

作用域关系在函数定义阶段就已经固定死了,与函数的调用无关。

x = 1
def f1():
    print(x)  # 函数定义阶段,x=1,就已经被固定了。

def f2():
    x = 10
    f1()  # 所以函数无论被如何调用,都是一个整体

f2()

global、nonlocal关键字

global在局部修改全局的变量、修改的是不可变数据类型。可变数据类型会自动修改,不要用global。

# 可变数据类型可直接在局部修改全局的变量
x = []
def func():
    x.append('嘿嘿嘿')

func()
print(x)  # ['嘿嘿嘿']
# global 修改局部变量为全局变量
x = 1
username = 'jason'
def func():
    global x,username  # 将局部变量x,username的值999,'egon',修改为全局变量x,username的值
    x = 999
    username = 'egon'
func()
print(x)  # x = 999
print(username)  # username = 'egon'
# nonlocal 修改局部变量为局部变量
def func():
    x = 1
    def index():
        nonlocal x  # 将局部变量index函数内部的x的值2,修改为局部变量fun函数的x的值
        x =2
    index()
    print(x)
func()

global:局部修改全局,如果想修改多个,用逗号隔开

nonlocal:局部修改局部,如果想修改多个,用逗号隔开

Never,Never,Never give up.

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注