其他分享
首页 > 其他分享> > 19、闭包

19、闭包

作者:互联网

嵌套定义函数

在函数内部定义函数

def outter():
    def inner():
        print('Inside inner')

    print('Inside outter')
    inner()

outter()    

实现信息隐藏

def outter():
    def inner():
        print('inside inner')

    print('inside outter')        
    inner()

# 这里将会报错。因为函数 inner 对外部是不可见的
inner()  

实现信息隐藏的例子

函数 f1、f2、f3 是用于实现 complex 的辅助函数,我们希望它们仅仅能够被 complex 调用,而不会被其它函数调用。如果可以将函数 f1、f2、f3 定义在函数 complex 的内部,如下所示:

def complex():
    def f1():
        print('Inside f1')
    def f2():
        print('Inside f2')
    def f3():
        print('Inside f3')

    print('Inside complex')
    f1()
    f2()
    f3()

内部函数访问外部函数的局部变量

def outter():
    local = 123

    def inner():
        print('Inside inner, local = {}'.format(local))

    inner()

outter()

局部变量的生命周期

通常情况下,函数执行完后,函数内部的局部变量就不存在了。在嵌套定义函数的情况下,如果内部函数访问了外部函数的局部变量,外部函数执行完毕后,内部函数仍然可以访问外部函数的局部变量。示例代码如下:

def outter():
    local = 123

    def inner():
        print('Inside inner, local = %d ' % local)

    return inner

closure = outter()
closure()

调用函数 closure() 时,外部函数 outter 已经执行完,外部函数 outter 将内部函数 inner 返回并保存到变量 closure。调用函数 closure() 相当于调用内部函数 inner(),因此,在外部函数 outter 已经执行完的情况下,内部函数 inner 仍然可以访问外部函数的局部变量 local。

闭包的概念

对照闭包的定义,外部函数定义了局部变量 local,引用了局部变量 local 的内部函数 inner 就是闭包。闭包的独特之处在于:外部函数 outter 创造了局部变量 local, 即使外部函数 outter 已经执行完,内部函数 inner 仍然可以继续访问它引用的局部变量 local。

闭包的应用

概述

闭包经常用于 GUI 编程的事件响应处理函数。编程语言 Javascript 被用于浏览器的用户界面交互,使用 Javascript 编写事件响应处理函数时,闭包也是经常提及的知识点。

Tk 简介

Tkinter 是 Python 的标准 GUI 库,Python 使用 Tkinter 可以快速的创建 GUI 应用程序。

例子 1:显示一个窗口

import tkinter

root = tkinter.Tk()
root.mainloop()

若提示模块错误,可以在终端中输入如下命令:

sudo apt-get install python3-tk
python3 test.py

之后即可开启窗口

例子 2:显示一个 button

import tkinter

root = tkinter.Tk()
button = tkinter.Button(root, text = 'Button')
button.pack()
root.mainloop()

例子 3:为 button 增加一个事件处理函数

import tkinter

def on_button_click():
    print('Button is clicked')

root = tkinter.Tk()
button = tkinter.Button(root, text = 'Button', command = on_button_click)
button.pack()
root.mainloop()

如何实现计算器

为了区分是哪一个按键被点击了,可以为不同的按键设定不同的按键处理函数,如下所示:

import tkinter

def on_button0_click():
    print('Button 0 is clicked')

def on_button1_click():
    print('Button 1 is clicked')

def on_button2_click():
    print('Button 2 is clicked')

root = tkinter.Tk()

button0 = tkinter.Button(root, text = 'Button 0', command = on_button0_click)
button0.pack()

button1 = tkinter.Button(root, text = 'Button 1', command = on_button1_click)
button1.pack()

button2 = tkinter.Button(root, text = 'Button 2', command = on_button2_click)
button2.pack()

root.mainloop()

显然,这样的方式是很不合理的,在一个完整的计算器程序中,存在 20 多个按键,如果对每个按键都编写一个事件处理函数,就需要编写 20 多个事件处理函数。在下面的小节中,通过使用闭包解决这个问题。

例子 4:使用闭包为多个 button 增加事件处理函数

在上面的小节中,面临的问题是:需要为每个 button 编写一个事件处理函数。本小节编写一个事件处理函数响应所有的按键点击事件,代码如下:

import tkinter

def build_button(root, i):
    def on_button_click():
        print('Button %d is clicked' % i)

    title = 'Button ' + str(i)
    button = tkinter.Button(root, text = title, command = on_button_click)
    button.pack()

root = tkinter.Tk()
# 使用 for 循环调用 build_button 创建 3 个 button
for i in range(3):
    build_button(root, i)
root.mainloop()

参考资料

http://www.imooc.com/wiki/pythonlesson1/pythonbag.html

标签:闭包,函数,19,button,inner,root,Button,def
来源: https://www.cnblogs.com/tiansz/p/16437546.html