函数对象与闭包

一、函数对象


函数对象的本质:函数对象的本质是是一个变量,它可以被引用、可以作为一个容器对象的元素、可以作为函数的参数,甚至可以是一个函数的返回值。

(1)作为被引用的对象

def student(name, age, gender='male'):    # student --> 0xffee0fc2
    print('{0}的信息如下:\n姓名:{0}\n年龄:{1}\n性别:{2}'.format(name, age, gender))
s = student    # s -->0xffee0fc2
s('王鹏',18)
s('姜春',18,gender='female')

(2)作为一个容器对象的元素

复制代码
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from prettytable import PrettyTable


def login():
    print('登录功能!')


def save():
    print('存钱功能!')


def transfer():
    print('转账功能!')


def withdraw():
    print('取钱功能!')


def check_banlance():
    print('查询余额功能!')


def register():
    print('注册功能!')


func_choice= {
    '0': ('退出', None),
    '1': ('登录', login),
    '2': ('存钱', save),
    '3': ('转账', transfer),
    '4': ('取钱', withdraw),
    '5': ('查询余额', check_banlance),
    '6': ('注册', register)
}


def atm_interface():
    while True:
        tb = PrettyTable(field_names=['功能编号', '功能名称'])
        for k in func_choice:
            tb.add_row([k, func_choice[k][0]])
        print(tb)
        user_choice = input('请输入功能编号:').strip()
        if not user_choice.isdigit():
            print('请输入一个正整数!')
            continue
        elif user_choice == '0':
            break
        elif user_choice in func_choice:
            func_choice[k][1]()
        else:
            print('该功能尚未支持!')
            _continue = input('是否继续(y,n):').strip().lower()
            if _continue == 'y':
                continue
            else:break


atm_interface()
复制代码

(3)作为一个参数传入另外一个函数

复制代码
def outter(func):
    def wrapper():
        res = func()
        print('hello,oldboy!')
        return res
    return wrapper

def test():
    print('hello,shanghai!')

test = outter(test)
test()
复制代码
sudo+ssh://root@192.168.80.130:22/usr/bin/python -u //practice/day16/practice_4.py
hello,shanghai!
hello,oldboy!

(4)函数的返回值可以是一个函数

复制代码
def student():
    print('hello, oldboy!')
def test(func):
    print(func)
    return func
print(student)
test(student)()


sudo+ssh://root@192.168.80.130:22/usr/bin/python -u //practice/day16/practice_4.py
<function student at 0x7ffb17de3ee0>
<function student at 0x7ffb17de3ee0>
hello, oldboy!
复制代码

二、函数的嵌套


 

(1)函数的嵌套调用

在函数的调用过程中,又调用了其他的函数

复制代码
def mymax(x,y):
    return x if x>y else y
def vmax(a,b,c,d):
    res1=mymax(a,b)
    res2=mymax(c,d)
    return mymax(res1,res2)
print('[4,6,1,3]中最大的数是:{}'.format(vmax(4,6,1,3)))
复制代码

(2)函数的嵌套定义

在函数的定义过程中,包含另外一个函数的定义

复制代码
#!/usr/bin/env python
#-*- coding:utf-8 -*-

from math import pi

def circle(radius,action=0):
    """
      action参数:(0,1)
             0 -->求圆的周长 2*pi*radius
             1 -->求圆的面积 pi*(radius**2)
    """
    def perimeter():return 2*pi*radius
    def area():return pi*(radius**2)

    if action == 0:
        res = perimeter()
    else:res = area()
    return res
print('半径为4的圆的周长为:{:.2f}'.format(circle(4)))
print('半径为6的圆的面积为:{:.2f}'.format(circle(6,action=1)))
复制代码

三、闭包函数


 

# 闭包函数=名称空间与作用域+函数嵌套+函数对象

核心点:名字的查找关系是以函数定义阶段为准

(1)‘闭’与‘包’

# 闭”函数:该函数是内嵌函数
# 包"函数:该函数包含对外层函数作用域名字的引用(不是对全局作用域)
复制代码
# 闭包函数:名称空间与作用域的应用+函数嵌套
def f1():
    x = 2333
    def f2():
        print(x)
    f2()

# 闭包函数:函数对象
def f1():
    x = 2333
    def f2():
        print(x)
    return f2

f = f1()
f()
复制代码

(2)闭包的用途

向函数传参的另外一种方式

复制代码
# 两种为函数体传参的方式
# 方式一:直接把函数体需要的参数定义成形参
def f2(x):
    print(x)

f2(1)
f2(2)
f2(3)

# 方式二:
def f1(x): # x=3
    x=3
    def f2():
        print(x)
    return f2

x=f1(3)
print(x)

x()

# 应用场景
import requests

# 传参的方案一:
def get(url):
    response=requests.get(url)
    print(len(response.text))

get('https://www.baidu.com')
get('https://www.cnblogs.com/linhaifeng')
get('https://zhuanlan.zhihu.com/p/109056932')


# 传参的方案二:
def outter(url):
    # url='https://www.baidu.com'
    def get():
        response=requests.get(url)
        print(len(response.text))
    return get

baidu=outter('https://www.baidu.com')
baidu()

cnblogs=outter('https://www.cnblogs.com/linhaifeng')
cnblogs()

zhihu=outter('https://zhuanlan.zhihu.com/p/109056932')
zhihu()
复制代码
posted @ 2020-03-20 19:49  迎着阳光  阅读(108)  评论(0编辑  收藏  举报