龙空技术网

Python教程——14.闭包

HKXYdd 458

前言:

此时朋友们对“python闭包的条件”大致比较注意,大家都想要分析一些“python闭包的条件”的相关文章。那么小编在网摘上汇集了一些有关“python闭包的条件””的相关资讯,希望兄弟们能喜欢,咱们快快来了解一下吧!

引入

想想看怎样用程序实现下面的功能呢?

在一个聊天软件中显示是谁发送了这条信息,即:一条信息标记了是谁发送的

今天我们要研究的知识点是闭包,实现上述功能的方式可能有多种,但是闭包会更简单。

问题解决

普通方式

def say(user_name, content):    print("(%s):%s" % (user_name, content))user_name1 = "张三"user_name2 = "李四"say(user_name1, "今天吃了么?")say(user_name2, "吃了~")say(user_name1, "吃了啥?")say(user_name2, "一头牛~")say(user_name1, "为啥不给我吃?")say(user_name2, "我一个人刚刚好~~")say(user_name1, "友谊的小船说翻就翻!")say(user_name2, "我会游泳~~~")

运行效果如下:

(张三):今天吃了么?(李四):吃了~(张三):吃了啥?(李四):一头牛~(张三):为啥不给我吃?(李四):我一个人刚刚好~~(张三):友谊的小船说翻就翻!(李四):我会游泳~~~

小总结:

上述代码已经实现了要求,但是每次发送信息时需要将用户名称传递到say函数中,相对比较麻烦

面向对象的方式解决上述问题

class Person(object):    def __init__(self, name):        self.user_name = name    def say(self, content):        print("(%s):%s" % (self.user_name, content))p1 = Person("张三")p2 = Person("李四")p1.say("今天吃了么?")p2.say("吃了~")p1.say("吃了啥?")p2.say("一头牛~")p1.say("为啥不给我吃?")p2.say("我一个人刚刚好~~")p1.say("友谊的小船说翻就翻!")p2.say("我会游泳~~~")

运行结果:

(张三):今天吃了么?(李四):吃了~(张三):吃了啥?(李四):一头牛~(张三):为啥不给我吃?(李四):我一个人刚刚好~~(张三):友谊的小船说翻就翻!(李四):我会游泳~~~

小总结:

通过面向对象的方式能够实现上述要求,但是发现使用了类以及对象,总体感觉还是较为复杂,再者说继承的object类中有很多默认的方法,既然这个程序不需要,显然会造成一定的浪费

使用闭包解决上述问题

def person(name):    def say(content):        print("(%s):%s" % (name, content))    return sayp1 = person("张三")p2 = person("李四")p1("今天吃了么?")p2("吃了~")p1("吃了啥?")p2("一头牛~")p1("为啥不给我吃?")p2("我一个人刚刚好~~")p1("友谊的小船说翻就翻!")p2("我会游泳~~~")

函数引用

# 定义函数可以理解为:# 定义了一个全局变量,其变量名字是函数的名字,即test# 这个test变量指向了一个代码块,这个代码块是函数# 其实就是说test保存了一个代码块的地址,即引用def test():    print("--- in test func----")test()  # 这是调用函数ret = test # 用另外一个变量 复制了 test这个引用,导致ret变量也指向那个 函数代码块# 下面输出的2个地址信息是相同的print(id(ret))print(id(test))# 通过引用调用函数ret()

运行结果:

--- in test func----140212571149040140212571149040--- in test func----

闭包的概念

闭包(closure) 定义非常抽象,很难看懂

下面尝试从概念上去理解一下闭包:

在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。闭包可以用来在一个函数与一组“私有”变量之间创建关联关系。在给定函数被多次调用的过程中,这些私有变量能够保持其持久性。 —— 维基百科闭包_(计算机科学)

用比较容易懂的人话说:就是当某个函数被当成对象返回时,夹带了外部变量,就形成了一个闭包。可以这样理解,闭包就是能够读取其他函数内部变量的函数

看如下案例,便于理解什么是闭包:

def make_printer(msg):  # 可以认为是 外部函数    def printer():  # 可以认为是 内部函数        print(msg)    return printer  # 返回的内部函数的引用printer = make_printer('Good!')printer()

运行结果:

Good

闭包案例

代码示例:

def test(number):    def test_in(number_in):        print("in test_in 函数, number_in is %d" % number_in)        return number + number_in    return test_in# 给test函数赋值,这个20就是给参数numberret = test(20)# 注意这里的100其实给参数number_inprint(ret(100))# 注意这里的200其实给参数number_inprint(ret(200))

运行结果:

in test_in 函数, number_in is 100120in test_in 函数, number_in is 200220

使用闭包需要注意的问题

由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。因此可以手动解除对匿名函数的引用,以便释放内存。

使用闭包修改外部函数中的变量

def counter(start=0):    def add_one():        nonlocal start  # nonlocal 关键字用于在嵌套函数内部使用变量,其中变量不应属于内部函数。        start += 1        return start    return add_onec1 = counter(5)  # 创建一个闭包print(c1())print(c1())c2 = counter(50)  # 创建另外一个闭包print(c2())print(c2())print(c1())print(c1())print(c2())print(c2())

运行结果:

675152895354

多个闭包

如上面的代码中,调用了2次counter,也就意味着创建了2个闭包,并且每个闭包之间没有任何关系。

大家是否有种感觉,好像闭包与对象有些类似。确实是这样的,对象其实可通俗的理解为数据(属性) + 功能(方法),而闭包也可以理解为数据 + 功能,只不过此时数据是外部函数中的那些局部变量或者形参,而功能则是内部函数。对象适合完成较为复杂的功能,而闭包则更轻量

闭包总结闭包定义是在函数内再嵌套函数闭包是可以访问另一个函数局部作用域中变量的函数闭包可以读取另外一个函数内部的变量闭包可以让参数和变量不会被垃圾回收机制回收,始终保持在内存中(而普通的函数调用结束后 会被Python解释器自动释放局部变量)

标签: #python闭包的条件