函数对象

函数对象

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

def func):
    print'from func')

printfunc)

<function func at 0x00B46858>

一、函数对象的四大功能

1、函数名可以被引用

def func):
    print'from func')

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

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

def func):
    print'from func')

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

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

def deco):
    print'from deco')

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

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

def func):
    print'from func')

printfunc))  # None


l = [1,2,func,func)]
printl)  # [1, 2, <function func at 0x01776858>, None]
def register):
    username = input'username>>>:').strip)
    pwd = input'password>>>>:').strip)
    printusername,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:
    printfunc_msg)
    choice = input'请选择你想要的功能').strip)
    if choice == 'q':
        break

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

函数的嵌套调用

函数的调用

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

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

index)
def my_maxx,y):
    if x > y:
        return x
    return y

def my_max4a,b,c,d):
    res1 = my_maxa,b)
    res2 = my_maxres1,c)
    res3 = my_maxres2,d)
    return res3

printmy_max41,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_funcnumber):

    def register):

        print'register')

    def login):

        print'login')

    def transfer):

        print'shopping')
    func_dict = {
        0:register,
        1:login,
        2:transfer,
    }
    fun_choice = func_dict.getchoice)
    fun_choice)
while True:
    printf'请选择{func_msg}')
    choice = intinput'请输入你的选择?>>>>').strip))
    all_funcchoice)

名称空间与作用域

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

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
printy)
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
                printx)
            # 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):
    printx)  # 函数定义阶段,x=1,就已经被固定了。

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

f2)

global、nonlocal关键字

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

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

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

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

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

Never,Never,Never give up.

Published by

风君子

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

发表回复

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